From 19daa9a1f5c4bdf4b79d1f7790aec210ce86a6e2 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 3 Jun 2026 16:30:09 +1000 Subject: [PATCH 01/16] added custom types and methods --- crates/goose-sdk/src/custom_requests.rs | 95 ++++++++++++++++++- .../goose/src/acp/server/custom_dispatch.rs | 8 +- crates/goose/src/acp/server/extensions.rs | 6 +- 3 files changed, 99 insertions(+), 10 deletions(-) diff --git a/crates/goose-sdk/src/custom_requests.rs b/crates/goose-sdk/src/custom_requests.rs index 5b007574bbd5..b27654c27fd9 100644 --- a/crates/goose-sdk/src/custom_requests.rs +++ b/crates/goose-sdk/src/custom_requests.rs @@ -1,3 +1,4 @@ +use agent_client_protocol::schema::McpServer; use agent_client_protocol::{JsonRpcRequest, JsonRpcResponse}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -147,19 +148,95 @@ pub struct DeleteSessionRequest { pub session_id: String, } +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum GooseExtension { + Builtin { + name: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + description: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + display_name: Option, + }, + Platform { + name: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + description: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + display_name: Option, + }, + Mcp { + server: McpServer, + #[serde(default, rename = "envKeys", skip_serializing_if = "Vec::is_empty")] + env_keys: Vec, + #[serde(default, skip_serializing_if = "Option::is_none")] + description: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + timeout: Option, + }, + InlinePython { + name: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + description: Option, + code: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + timeout: Option, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + dependencies: Vec, + }, + Frontend { + name: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + description: Option, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + tools: Vec, + #[serde(default, skip_serializing_if = "Option::is_none")] + instructions: Option, + }, +} + +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct GooseExtensionEntry { + pub extension: GooseExtension, + pub enabled: bool, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub config_key: Option, +} + +/// List Goose-owned extension definitions available to configure or enable. +#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] +#[request( + method = "_goose/unstable/extensions/available", + response = GetAvailableExtensionsResponse +)] +pub struct GetAvailableExtensionsRequest {} + +#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcResponse)] +#[serde(rename_all = "camelCase")] +pub struct GetAvailableExtensionsResponse { + pub extensions: Vec, +} + /// List configured extensions and any warnings. #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] -#[request(method = "_goose/unstable/config/extensions/list", response = GetExtensionsResponse)] -pub struct GetExtensionsRequest {} +#[request( + method = "_goose/unstable/config/extensions/list", + response = GetConfigExtensionsResponse +)] +pub struct GetConfigExtensionsRequest {} /// List configured extensions and any warnings. #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcResponse)] -pub struct GetExtensionsResponse { +pub struct GetConfigExtensionsResponse { /// Array of ExtensionEntry objects with `enabled` flag, `configKey`, and flattened config details. pub extensions: Vec, pub warnings: Vec, } +pub type GetExtensionsRequest = GetConfigExtensionsRequest; +pub type GetExtensionsResponse = GetConfigExtensionsResponse; + /// Persist a new extension to the user's global goose config. #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] #[request(method = "_goose/unstable/config/extensions/add", response = EmptyResponse)] @@ -183,6 +260,18 @@ pub struct RemoveConfigExtensionRequest { pub config_key: String, } +/// Set the `enabled` flag for a persisted extension in the user's global goose config. +#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] +#[request( + method = "_goose/unstable/config/extensions/set-enabled", + response = EmptyResponse +)] +#[serde(rename_all = "camelCase")] +pub struct SetConfigExtensionEnabledRequest { + pub config_key: String, + pub enabled: bool, +} + /// Toggle the `enabled` flag for a persisted extension in the user's global goose config. #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] #[request(method = "_goose/unstable/config/extensions/toggle", response = EmptyResponse)] diff --git a/crates/goose/src/acp/server/custom_dispatch.rs b/crates/goose/src/acp/server/custom_dispatch.rs index 81c6e67107e1..2856acfc14e9 100644 --- a/crates/goose/src/acp/server/custom_dispatch.rs +++ b/crates/goose/src/acp/server/custom_dispatch.rs @@ -75,11 +75,11 @@ impl GooseAcpAgent { self.on_delete_session(req).await } - #[custom_method(GetExtensionsRequest)] - async fn dispatch_get_extensions( + #[custom_method(GetConfigExtensionsRequest)] + async fn dispatch_get_config_extensions( &self, - ) -> Result { - self.on_get_extensions().await + ) -> Result { + self.on_get_config_extensions().await } #[custom_method(AddConfigExtensionRequest)] diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index b45e0407b02f..9dd6cbdbe82b 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -30,9 +30,9 @@ impl GooseAcpAgent { Ok(EmptyResponse {}) } - pub(super) async fn on_get_extensions( + pub(super) async fn on_get_config_extensions( &self, - ) -> Result { + ) -> Result { let extensions = crate::config::extensions::get_all_extensions() .into_iter() .filter(|ext| { @@ -55,7 +55,7 @@ impl GooseAcpAgent { }) .collect::, _>>() .internal_err()?; - Ok(GetExtensionsResponse { + Ok(GetConfigExtensionsResponse { extensions: extensions_json, warnings, }) From aef792a3dc166422cc637133e6362a547b40b309 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 3 Jun 2026 17:03:42 +1000 Subject: [PATCH 02/16] added goose core extensionConfig to acp types --- crates/goose-sdk/src/custom_requests.rs | 6 +- crates/goose/src/acp/server/extensions.rs | 404 +++++++++++++++++- .../goose/tests/acp_custom_requests_test.rs | 66 ++- 3 files changed, 450 insertions(+), 26 deletions(-) diff --git a/crates/goose-sdk/src/custom_requests.rs b/crates/goose-sdk/src/custom_requests.rs index b27654c27fd9..2ca7473f6a54 100644 --- a/crates/goose-sdk/src/custom_requests.rs +++ b/crates/goose-sdk/src/custom_requests.rs @@ -173,6 +173,8 @@ pub enum GooseExtension { description: Option, #[serde(default, skip_serializing_if = "Option::is_none")] timeout: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + socket: Option, }, InlinePython { name: String, @@ -229,8 +231,8 @@ pub struct GetConfigExtensionsRequest {} /// List configured extensions and any warnings. #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcResponse)] pub struct GetConfigExtensionsResponse { - /// Array of ExtensionEntry objects with `enabled` flag, `configKey`, and flattened config details. - pub extensions: Vec, + pub extensions: Vec, + #[serde(default, skip_serializing_if = "Vec::is_empty")] pub warnings: Vec, } diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index 9dd6cbdbe82b..818106b2f359 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -1,4 +1,386 @@ use super::*; +use agent_client_protocol::schema::{HttpHeader, McpServerHttp, McpServerStdio}; + +fn empty_string_to_none(value: &str) -> Option { + if value.is_empty() { + None + } else { + Some(value.to_string()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::agents::extension::Envs; + use agent_client_protocol::schema::McpServer; + use rmcp::model::Tool; + use std::collections::HashMap; + + #[test] + fn builtin_config_converts_to_goose_builtin_extension() { + let config = ExtensionConfig::Builtin { + name: "developer".to_string(), + description: "Developer tools".to_string(), + display_name: Some("Developer".to_string()), + timeout: Some(30), + bundled: Some(true), + available_tools: vec!["shell".to_string()], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("builtin should be supported"); + + let GooseExtension::Builtin { + name, + description, + display_name, + } = extension + else { + panic!("expected builtin extension"); + }; + + assert_eq!(name, "developer"); + assert_eq!(description.as_deref(), Some("Developer tools")); + assert_eq!(display_name.as_deref(), Some("Developer")); + } + + #[test] + fn platform_config_converts_to_goose_platform_extension() { + let config = ExtensionConfig::Platform { + name: "todo".to_string(), + description: "Todo tools".to_string(), + display_name: Some("Todo".to_string()), + bundled: Some(true), + available_tools: vec!["write_todos".to_string()], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("platform should be supported"); + + let GooseExtension::Platform { + name, + description, + display_name, + } = extension + else { + panic!("expected platform extension"); + }; + + assert_eq!(name, "todo"); + assert_eq!(description.as_deref(), Some("Todo tools")); + assert_eq!(display_name.as_deref(), Some("Todo")); + } + + #[test] + fn stdio_config_converts_to_goose_mcp_extension_without_literal_envs() { + let config = ExtensionConfig::Stdio { + name: "test-stdio".to_string(), + description: "Test stdio".to_string(), + cmd: "test-command".to_string(), + args: vec!["--flag".to_string(), "value".to_string()], + envs: Envs::new(HashMap::from([( + "SECRET_TOKEN".to_string(), + "literal-secret".to_string(), + )])), + env_keys: vec!["SECRET_TOKEN".to_string()], + timeout: Some(42), + bundled: None, + available_tools: vec![], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("stdio should be supported"); + + let GooseExtension::Mcp { + server, + env_keys, + description, + timeout, + socket, + } = extension + else { + panic!("expected mcp extension"); + }; + + assert_eq!(env_keys, vec!["SECRET_TOKEN"]); + assert_eq!(description.as_deref(), Some("Test stdio")); + assert_eq!(timeout, Some(42)); + assert_eq!(socket, None); + + let McpServer::Stdio(stdio) = server else { + panic!("expected stdio server"); + }; + + assert_eq!(stdio.name, "test-stdio"); + assert_eq!(stdio.command.to_string_lossy(), "test-command"); + assert_eq!(stdio.args, vec!["--flag", "value"]); + assert!(stdio.env.is_empty(), "literal envs should not be exposed"); + } + + #[test] + fn streamable_http_config_converts_to_goose_mcp_extension_without_literal_envs() { + let config = ExtensionConfig::StreamableHttp { + name: "test-http".to_string(), + description: "Test HTTP".to_string(), + uri: "https://example.com/mcp".to_string(), + envs: Envs::new(HashMap::from([( + "API_TOKEN".to_string(), + "literal-secret".to_string(), + )])), + env_keys: vec!["API_TOKEN".to_string()], + headers: HashMap::from([( + "Authorization".to_string(), + "Bearer ${API_TOKEN}".to_string(), + )]), + timeout: Some(99), + socket: Some("@egress.sock".to_string()), + bundled: None, + available_tools: vec![], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("streamable http should be supported"); + + let GooseExtension::Mcp { + server, + env_keys, + description, + timeout, + socket, + } = extension + else { + panic!("expected mcp extension"); + }; + + assert_eq!(env_keys, vec!["API_TOKEN"]); + assert_eq!(description.as_deref(), Some("Test HTTP")); + assert_eq!(timeout, Some(99)); + assert_eq!(socket.as_deref(), Some("@egress.sock")); + + let McpServer::Http(http) = server else { + panic!("expected http server"); + }; + + assert_eq!(http.name, "test-http"); + assert_eq!(http.url, "https://example.com/mcp"); + assert_eq!(http.headers.len(), 1); + assert_eq!(http.headers[0].name, "Authorization"); + assert_eq!(http.headers[0].value, "Bearer ${API_TOKEN}"); + } + + #[test] + fn inline_python_config_converts_to_goose_inline_python_extension() { + let config = ExtensionConfig::InlinePython { + name: "python-tools".to_string(), + description: "Python tools".to_string(), + code: "print('hello')".to_string(), + timeout: Some(12), + dependencies: Some(vec!["requests".to_string()]), + available_tools: vec!["fetch".to_string()], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("inline python should be supported"); + + let GooseExtension::InlinePython { + name, + description, + code, + timeout, + dependencies, + } = extension + else { + panic!("expected inline python extension"); + }; + + assert_eq!(name, "python-tools"); + assert_eq!(description.as_deref(), Some("Python tools")); + assert_eq!(code, "print('hello')"); + assert_eq!(timeout, Some(12)); + assert_eq!(dependencies, vec!["requests"]); + } + + #[test] + fn frontend_config_converts_to_goose_frontend_extension() { + let tool = Tool::new( + "pick_color", + "Pick a color", + serde_json::json!({ + "type": "object", + "properties": { + "hex": { "type": "string" } + } + }) + .as_object() + .expect("schema should be object") + .clone(), + ); + let config = ExtensionConfig::Frontend { + name: "frontend-tools".to_string(), + description: "Frontend tools".to_string(), + tools: vec![tool], + instructions: Some("Use frontend tools carefully".to_string()), + bundled: None, + available_tools: vec!["pick_color".to_string()], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("frontend should be supported"); + + let GooseExtension::Frontend { + name, + description, + tools, + instructions, + } = extension + else { + panic!("expected frontend extension"); + }; + + assert_eq!(name, "frontend-tools"); + assert_eq!(description.as_deref(), Some("Frontend tools")); + assert_eq!( + instructions.as_deref(), + Some("Use frontend tools carefully") + ); + assert_eq!(tools.len(), 1); + assert_eq!(tools[0]["name"], "pick_color"); + assert_eq!(tools[0]["description"], "Pick a color"); + } + + #[test] + fn sse_config_is_skipped() { + let config = ExtensionConfig::Sse { + name: "legacy-sse".to_string(), + description: "Legacy SSE".to_string(), + uri: Some("https://example.com/sse".to_string()), + }; + + let extension = config_to_goose_extension(&config).expect("conversion should succeed"); + + assert!(extension.is_none()); + } +} + +fn config_to_goose_extension( + config: &ExtensionConfig, +) -> Result, agent_client_protocol::Error> { + let extension = match config { + ExtensionConfig::Builtin { + name, + description, + display_name, + .. + } => GooseExtension::Builtin { + name: name.clone(), + description: empty_string_to_none(description), + display_name: display_name.clone(), + }, + ExtensionConfig::Platform { + name, + description, + display_name, + .. + } => GooseExtension::Platform { + name: name.clone(), + description: empty_string_to_none(description), + display_name: display_name.clone(), + }, + ExtensionConfig::Stdio { + name, + description, + cmd, + args, + env_keys, + timeout, + .. + } => GooseExtension::Mcp { + server: McpServer::Stdio(McpServerStdio::new(name, cmd).args(args.clone())), + env_keys: env_keys.clone(), + description: empty_string_to_none(description), + timeout: *timeout, + socket: None, + }, + ExtensionConfig::StreamableHttp { + name, + description, + uri, + env_keys, + headers, + timeout, + socket, + .. + } => { + let headers = headers + .iter() + .map(|(key, value)| HttpHeader::new(key, value)) + .collect(); + GooseExtension::Mcp { + server: McpServer::Http(McpServerHttp::new(name, uri).headers(headers)), + env_keys: env_keys.clone(), + description: empty_string_to_none(description), + timeout: *timeout, + socket: socket.clone(), + } + } + ExtensionConfig::Frontend { + name, + description, + tools, + instructions, + .. + } => { + let tools = tools + .iter() + .map(serde_json::to_value) + .collect::, _>>() + .internal_err()?; + GooseExtension::Frontend { + name: name.clone(), + description: empty_string_to_none(description), + tools, + instructions: instructions.clone(), + } + } + ExtensionConfig::InlinePython { + name, + description, + code, + timeout, + dependencies, + .. + } => GooseExtension::InlinePython { + name: name.clone(), + description: empty_string_to_none(description), + code: code.clone(), + timeout: *timeout, + dependencies: dependencies.clone().unwrap_or_default(), + }, + ExtensionConfig::Sse { .. } => return Ok(None), + }; + Ok(Some(extension)) +} + +fn config_entry_to_goose_entry( + entry: crate::config::extensions::ExtensionEntry, +) -> Result, agent_client_protocol::Error> { + let config_key = entry.config.key(); + let Some(extension) = config_to_goose_extension(&entry.config)? else { + return Ok(None); + }; + Ok(Some(GooseExtensionEntry { + extension, + enabled: entry.enabled, + config_key: Some(config_key), + })) +} impl GooseAcpAgent { pub(super) async fn on_add_extension( @@ -40,23 +422,15 @@ impl GooseAcpAgent { }) .collect::>(); let warnings = crate::config::extensions::get_warnings(); - let extensions_json = extensions + let extensions = extensions .into_iter() - .map(|e| { - let config_key = e.config.key(); - let mut value = serde_json::to_value(&e)?; - if let Some(obj) = value.as_object_mut() { - obj.insert( - "config_key".to_string(), - serde_json::Value::String(config_key), - ); - } - Ok::<_, serde_json::Error>(value) - }) - .collect::, _>>() - .internal_err()?; + .map(config_entry_to_goose_entry) + .collect::, _>>()? + .into_iter() + .flatten() + .collect::>(); Ok(GetConfigExtensionsResponse { - extensions: extensions_json, + extensions, warnings, }) } diff --git a/crates/goose/tests/acp_custom_requests_test.rs b/crates/goose/tests/acp_custom_requests_test.rs index 24e237e49606..f4d97e6e8056 100644 --- a/crates/goose/tests/acp_custom_requests_test.rs +++ b/crates/goose/tests/acp_custom_requests_test.rs @@ -7,11 +7,14 @@ use common_tests::fixtures::{ run_test, send_custom, Connection, PermissionDecision, Session, SessionData, TestConnectionConfig, }; +use fs_err as fs; use goose::acp::server::AcpProviderFactory; +use goose::config::base::CONFIG_YAML_NAME; use goose::model::ModelConfig; use goose::providers::base::{MessageStream, Provider}; use goose::providers::errors::ProviderError; -use goose_test_support::{EnforceSessionId, IgnoreSessionId}; +use goose_test_support::{EnforceSessionId, IgnoreSessionId, TEST_MODEL}; +use serial_test::serial; use std::path::PathBuf; use std::sync::{Arc, Mutex}; @@ -98,7 +101,37 @@ fn test_custom_get_tools() { } #[test] +#[serial] fn test_custom_get_extensions() { + let config_key = "test-stdio-acp-config-list"; + let temp_dir = tempfile::tempdir().unwrap(); + let temp_root = temp_dir.path().to_string_lossy().to_string(); + let _guard = env_lock::lock_env([ + ("GOOSE_PATH_ROOT", Some(temp_root.as_str())), + ("EXTENSIONS", None::<&str>), + ]); + let config_dir = temp_dir.path().join("config"); + fs::create_dir_all(&config_dir).unwrap(); + let config_yaml = format!( + r#"GOOSE_MODEL: {TEST_MODEL} +GOOSE_PROVIDER: openai +extensions: + {config_key}: + enabled: true + type: stdio + name: {config_key} + description: Test stdio + cmd: test-command + args: + - --flag + - value + env_keys: + - SECRET_TOKEN + timeout: 42 +"# + ); + fs::write(config_dir.join(CONFIG_YAML_NAME), config_yaml).unwrap(); + run_test(async move { let openai = OpenAiFixture::new(vec![], Arc::new(EnforceSessionId::default())).await; let conn = AcpServerConnection::new(TestConnectionConfig::default(), openai).await; @@ -112,14 +145,29 @@ fn test_custom_get_extensions() { assert!(result.is_ok(), "expected ok, got: {:?}", result); let response = result.unwrap(); - assert!( - response.get("extensions").is_some(), - "missing 'extensions' field" - ); - assert!( - response.get("warnings").is_some(), - "missing 'warnings' field" - ); + let extensions = response + .get("extensions") + .and_then(|extensions| extensions.as_array()) + .expect("extensions should be an array"); + let entry = extensions + .iter() + .find(|entry| entry["configKey"] == config_key) + .unwrap_or_else(|| panic!("missing seeded extension entry in response: {response:#?}")); + assert_eq!(entry["enabled"], true); + assert_eq!(entry["configKey"], config_key); + + let extension = &entry["extension"]; + assert_eq!(extension["type"], "mcp"); + assert_eq!(extension["envKeys"], serde_json::json!(["SECRET_TOKEN"])); + assert_eq!(extension["description"], "Test stdio"); + assert_eq!(extension["timeout"], 42); + assert!(extension.get("socket").is_none()); + + let server = &extension["server"]; + assert_eq!(server["name"], config_key); + assert_eq!(server["command"], "test-command"); + assert_eq!(server["args"], serde_json::json!(["--flag", "value"])); + assert_eq!(server["env"], serde_json::json!([])); }); } From e74af4c0505fd21d51c00cff81a11d967138bd35 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 3 Jun 2026 18:17:14 +1000 Subject: [PATCH 03/16] added available extension custom method --- .../goose/src/acp/server/custom_dispatch.rs | 7 ++++ crates/goose/src/acp/server/extensions.rs | 14 +++++++ crates/goose/src/builtin_extension.rs | 4 ++ crates/goose/src/config/extensions.rs | 34 +++++++++++++++ crates/goose/src/config/mod.rs | 6 +-- .../goose/tests/acp_custom_requests_test.rs | 42 +++++++++++++++++++ 6 files changed, 104 insertions(+), 3 deletions(-) diff --git a/crates/goose/src/acp/server/custom_dispatch.rs b/crates/goose/src/acp/server/custom_dispatch.rs index 2856acfc14e9..4cdbd77cd1c8 100644 --- a/crates/goose/src/acp/server/custom_dispatch.rs +++ b/crates/goose/src/acp/server/custom_dispatch.rs @@ -82,6 +82,13 @@ impl GooseAcpAgent { self.on_get_config_extensions().await } + #[custom_method(GetAvailableExtensionsRequest)] + async fn dispatch_get_available_extensions( + &self, + ) -> Result { + self.on_get_available_extensions().await + } + #[custom_method(AddConfigExtensionRequest)] async fn dispatch_add_config_extension( &self, diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index 818106b2f359..565665a30739 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -435,6 +435,20 @@ impl GooseAcpAgent { }) } + pub(super) async fn on_get_available_extensions( + &self, + ) -> Result { + let extensions = crate::config::get_available_extensions() + .into_iter() + .map(|config| config_to_goose_extension(&config)) + .collect::, _>>()? + .into_iter() + .flatten() + .collect::>(); + + Ok(GetAvailableExtensionsResponse { extensions }) + } + pub(super) async fn on_add_config_extension( &self, req: AddConfigExtensionRequest, diff --git a/crates/goose/src/builtin_extension.rs b/crates/goose/src/builtin_extension.rs index c69a44cf1cb5..5dfa5984d10a 100644 --- a/crates/goose/src/builtin_extension.rs +++ b/crates/goose/src/builtin_extension.rs @@ -22,3 +22,7 @@ pub fn register_builtin_extensions(extensions: HashMap<&'static str, SpawnServer pub fn get_builtin_extension(name: &str) -> Option { BUILTIN_REGISTRY.read().unwrap().get(name).cloned() } + +pub fn get_builtin_extension_names() -> Vec<&'static str> { + BUILTIN_REGISTRY.read().unwrap().keys().copied().collect() +} diff --git a/crates/goose/src/config/extensions.rs b/crates/goose/src/config/extensions.rs index 460a6e93ebf5..d2c16d137ebd 100644 --- a/crates/goose/src/config/extensions.rs +++ b/crates/goose/src/config/extensions.rs @@ -145,6 +145,40 @@ pub fn get_enabled_extensions_with_config(config: &Config) -> Vec Vec { + let mut builtin_names = crate::builtin_extension::get_builtin_extension_names(); + builtin_names.sort_unstable(); + + let mut platform_definitions = PLATFORM_EXTENSIONS + .values() + .filter(|definition| !definition.hidden) + .collect::>(); + platform_definitions.sort_unstable_by_key(|definition| definition.name); + + builtin_names + .into_iter() + .map(|name| ExtensionConfig::Builtin { + name: name.to_string(), + description: String::new(), + display_name: Some(name.to_string()), + timeout: None, + bundled: Some(true), + available_tools: Vec::new(), + }) + .chain( + platform_definitions + .into_iter() + .map(|definition| ExtensionConfig::Platform { + name: definition.name.to_string(), + description: definition.description.to_string(), + display_name: Some(definition.display_name.to_string()), + bundled: Some(true), + available_tools: Vec::new(), + }), + ) + .collect() +} + pub fn get_warnings() -> Vec { let raw: Mapping = Config::global() .get_param(EXTENSIONS_CONFIG_KEY) diff --git a/crates/goose/src/config/mod.rs b/crates/goose/src/config/mod.rs index 402c835f8783..ae6c46265fc2 100644 --- a/crates/goose/src/config/mod.rs +++ b/crates/goose/src/config/mod.rs @@ -17,9 +17,9 @@ pub use base::{merge_config_values, Config, ConfigError}; pub use declarative_providers::DeclarativeProviderConfig; pub use experiments::ExperimentManager; pub use extensions::{ - get_all_extension_names, get_all_extensions, get_enabled_extensions, get_extension_by_name, - get_warnings, is_extension_enabled, remove_extension, resolve_extensions_for_new_session, - set_extension, set_extension_enabled, ExtensionEntry, + get_all_extension_names, get_all_extensions, get_available_extensions, get_enabled_extensions, + get_extension_by_name, get_warnings, is_extension_enabled, remove_extension, + resolve_extensions_for_new_session, set_extension, set_extension_enabled, ExtensionEntry, }; pub use goose_mode::GooseMode; pub use permission::PermissionManager; diff --git a/crates/goose/tests/acp_custom_requests_test.rs b/crates/goose/tests/acp_custom_requests_test.rs index f4d97e6e8056..71afee0ece3d 100644 --- a/crates/goose/tests/acp_custom_requests_test.rs +++ b/crates/goose/tests/acp_custom_requests_test.rs @@ -171,6 +171,48 @@ extensions: }); } +#[test] +fn test_custom_get_available_extensions() { + run_test(async move { + let openai = OpenAiFixture::new(vec![], Arc::new(EnforceSessionId::default())).await; + let conn = AcpServerConnection::new(TestConnectionConfig::default(), openai).await; + + let result = send_custom( + conn.cx(), + "_goose/unstable/extensions/available", + serde_json::json!({}), + ) + .await; + assert!(result.is_ok(), "expected ok, got: {:?}", result); + + let response = result.unwrap(); + let extensions = response + .get("extensions") + .and_then(|extensions| extensions.as_array()) + .expect("extensions should be an array"); + assert!(!extensions.is_empty(), "extensions should not be empty"); + assert!( + extensions.iter().all(|extension| matches!( + extension["type"].as_str(), + Some("builtin" | "platform") + )), + "available extensions should only include builtin and platform entries" + ); + assert!( + extensions.iter().any(|extension| { + extension["type"] == "platform" && extension["name"] == "developer" + }), + "developer platform extension should be available" + ); + assert!( + !extensions.iter().any(|extension| { + extension["type"] == "platform" && extension["name"] == "orchestrator" + }), + "hidden orchestrator platform extension should not be available" + ); + }); +} + #[test] fn test_new_session_passes_cwd_to_provider_factory() { run_test(async move { From d3253a08d4ef8b376d0870277d001261e2918c57 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 3 Jun 2026 19:17:27 +1000 Subject: [PATCH 04/16] reimplement add, remove, set-enable for config extensions --- crates/goose-sdk/src/custom_requests.rs | 26 +- .../goose/src/acp/server/custom_dispatch.rs | 8 +- crates/goose/src/acp/server/extensions.rs | 365 ++++++++++++++++-- crates/goose/src/config/extensions.rs | 18 +- crates/goose/src/config/mod.rs | 5 +- .../goose/tests/acp_custom_requests_test.rs | 114 ++++-- 6 files changed, 458 insertions(+), 78 deletions(-) diff --git a/crates/goose-sdk/src/custom_requests.rs b/crates/goose-sdk/src/custom_requests.rs index 2ca7473f6a54..c043e18d58f8 100644 --- a/crates/goose-sdk/src/custom_requests.rs +++ b/crates/goose-sdk/src/custom_requests.rs @@ -197,6 +197,16 @@ pub enum GooseExtension { }, } +impl Default for GooseExtension { + fn default() -> Self { + Self::Builtin { + name: String::new(), + description: None, + display_name: None, + } + } +} + #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct GooseExtensionEntry { @@ -244,12 +254,7 @@ pub type GetExtensionsResponse = GetConfigExtensionsResponse; #[request(method = "_goose/unstable/config/extensions/add", response = EmptyResponse)] #[serde(rename_all = "camelCase")] pub struct AddConfigExtensionRequest { - pub name: String, - /// Extension configuration. Must be a JSON object matching one of the - /// `ExtensionConfig` variants (e.g. `stdio`, `streamable_http`, `builtin`). - /// `name` and `enabled` are injected server-side. - #[serde(default)] - pub extension_config: serde_json::Value, + pub extension: GooseExtension, #[serde(default)] pub enabled: bool, } @@ -274,15 +279,6 @@ pub struct SetConfigExtensionEnabledRequest { pub enabled: bool, } -/// Toggle the `enabled` flag for a persisted extension in the user's global goose config. -#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] -#[request(method = "_goose/unstable/config/extensions/toggle", response = EmptyResponse)] -#[serde(rename_all = "camelCase")] -pub struct ToggleConfigExtensionRequest { - pub config_key: String, - pub enabled: bool, -} - #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] #[request(method = "_goose/unstable/session/extensions/list", response = GetSessionExtensionsResponse)] #[serde(rename_all = "camelCase")] diff --git a/crates/goose/src/acp/server/custom_dispatch.rs b/crates/goose/src/acp/server/custom_dispatch.rs index 4cdbd77cd1c8..4d542eaf74b6 100644 --- a/crates/goose/src/acp/server/custom_dispatch.rs +++ b/crates/goose/src/acp/server/custom_dispatch.rs @@ -105,12 +105,12 @@ impl GooseAcpAgent { self.on_remove_config_extension(req).await } - #[custom_method(ToggleConfigExtensionRequest)] - async fn dispatch_toggle_config_extension( + #[custom_method(SetConfigExtensionEnabledRequest)] + async fn dispatch_set_config_extension_enabled( &self, - req: ToggleConfigExtensionRequest, + req: SetConfigExtensionEnabledRequest, ) -> Result { - self.on_toggle_config_extension(req).await + self.on_set_config_extension_enabled(req).await } #[custom_method(GetSessionExtensionsRequest)] diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index 565665a30739..5c9dfca017f5 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -267,6 +267,218 @@ mod tests { assert!(extension.is_none()); } + + #[test] + fn goose_mcp_stdio_extension_converts_to_config_without_literal_envs() { + let extension = GooseExtension::Mcp { + server: McpServer::Stdio( + McpServerStdio::new("test-stdio", "test-command") + .args(vec!["--flag".to_string(), "value".to_string()]) + .env(vec![agent_client_protocol::schema::EnvVariable::new( + "SECRET_TOKEN", + "literal-secret", + )]), + ), + env_keys: vec!["SECRET_TOKEN".to_string()], + description: Some("Test stdio".to_string()), + timeout: Some(42), + socket: None, + }; + + let config = goose_extension_to_config(extension).expect("conversion should succeed"); + + let ExtensionConfig::Stdio { + name, + description, + cmd, + args, + envs, + env_keys, + timeout, + bundled, + available_tools, + } = config + else { + panic!("expected stdio config"); + }; + + assert_eq!(name, "test-stdio"); + assert_eq!(description, "Test stdio"); + assert_eq!(cmd, "test-command"); + assert_eq!(args, vec!["--flag", "value"]); + assert!( + envs.get_env().is_empty(), + "literal envs should not be persisted" + ); + assert_eq!(env_keys, vec!["SECRET_TOKEN"]); + assert_eq!(timeout, Some(42)); + assert_eq!(bundled, Some(false)); + assert!(available_tools.is_empty()); + } + + #[test] + fn goose_mcp_streamable_http_extension_converts_to_config_without_literal_envs() { + let extension = GooseExtension::Mcp { + server: McpServer::Http( + McpServerHttp::new("test-http", "https://example.com/mcp").headers(vec![ + HttpHeader::new("Authorization", "Bearer ${API_TOKEN}"), + ]), + ), + env_keys: vec!["API_TOKEN".to_string()], + description: Some("Test HTTP".to_string()), + timeout: Some(99), + socket: Some("@egress.sock".to_string()), + }; + + let config = goose_extension_to_config(extension).expect("conversion should succeed"); + + let ExtensionConfig::StreamableHttp { + name, + description, + uri, + envs, + env_keys, + headers, + timeout, + socket, + bundled, + available_tools, + } = config + else { + panic!("expected streamable http config"); + }; + + assert_eq!(name, "test-http"); + assert_eq!(description, "Test HTTP"); + assert_eq!(uri, "https://example.com/mcp"); + assert!( + envs.get_env().is_empty(), + "literal envs should not be persisted" + ); + assert_eq!(env_keys, vec!["API_TOKEN"]); + assert_eq!( + headers, + HashMap::from([( + "Authorization".to_string(), + "Bearer ${API_TOKEN}".to_string() + )]) + ); + assert_eq!(timeout, Some(99)); + assert_eq!(socket.as_deref(), Some("@egress.sock")); + assert_eq!(bundled, Some(false)); + assert!(available_tools.is_empty()); + } + + #[test] + fn goose_inline_python_extension_converts_to_config() { + let extension = GooseExtension::InlinePython { + name: "python-tools".to_string(), + description: Some("Python tools".to_string()), + code: "print('hello')".to_string(), + timeout: Some(12), + dependencies: vec!["requests".to_string()], + }; + + let config = goose_extension_to_config(extension).expect("conversion should succeed"); + + let ExtensionConfig::InlinePython { + name, + description, + code, + timeout, + dependencies, + available_tools, + } = config + else { + panic!("expected inline python config"); + }; + + assert_eq!(name, "python-tools"); + assert_eq!(description, "Python tools"); + assert_eq!(code, "print('hello')"); + assert_eq!(timeout, Some(12)); + assert_eq!(dependencies, Some(vec!["requests".to_string()])); + assert!(available_tools.is_empty()); + } + + #[test] + fn goose_frontend_extension_converts_to_config() { + let tool = serde_json::json!({ + "name": "pick_color", + "description": "Pick a color", + "inputSchema": { + "type": "object", + "properties": { + "hex": { "type": "string" } + } + } + }); + let extension = GooseExtension::Frontend { + name: "frontend-tools".to_string(), + description: Some("Frontend tools".to_string()), + tools: vec![tool], + instructions: Some("Use frontend tools carefully".to_string()), + }; + + let config = goose_extension_to_config(extension).expect("conversion should succeed"); + + let ExtensionConfig::Frontend { + name, + description, + tools, + instructions, + bundled, + available_tools, + } = config + else { + panic!("expected frontend config"); + }; + + assert_eq!(name, "frontend-tools"); + assert_eq!(description, "Frontend tools"); + assert_eq!(tools.len(), 1); + assert_eq!(tools[0].name, "pick_color"); + assert_eq!(tools[0].description.as_deref(), Some("Pick a color")); + assert_eq!( + instructions.as_deref(), + Some("Use frontend tools carefully") + ); + assert_eq!(bundled, Some(false)); + assert!(available_tools.is_empty()); + } + + #[test] + fn goose_builtin_and_platform_extensions_are_rejected_for_config_add() { + let builtin = GooseExtension::Builtin { + name: "developer".to_string(), + description: None, + display_name: None, + }; + let platform = GooseExtension::Platform { + name: "todo".to_string(), + description: None, + display_name: None, + }; + + assert!(goose_extension_to_config(builtin).is_err()); + assert!(goose_extension_to_config(platform).is_err()); + } + + #[test] + fn goose_mcp_sse_extension_is_rejected_for_config_add() { + let extension = GooseExtension::Mcp { + server: McpServer::Sse(agent_client_protocol::schema::McpServerSse::new( + "legacy-sse", + "https://example.com/sse", + )), + env_keys: Vec::new(), + description: None, + timeout: None, + socket: None, + }; + + assert!(goose_extension_to_config(extension).is_err()); + } } fn config_to_goose_extension( @@ -368,6 +580,102 @@ fn config_to_goose_extension( Ok(Some(extension)) } +fn goose_extension_to_config( + extension: GooseExtension, +) -> Result { + let config = match extension { + GooseExtension::Builtin { .. } | GooseExtension::Platform { .. } => { + return Err(agent_client_protocol::Error::invalid_params() + .data("builtin and platform extensions cannot be added to persistent config")); + } + GooseExtension::Mcp { + server, + env_keys, + description, + timeout, + socket, + } => match server { + McpServer::Stdio(stdio) => { + if socket.is_some() { + return Err(agent_client_protocol::Error::invalid_params() + .data("socket is only supported for streamable_http MCP extensions")); + } + ExtensionConfig::Stdio { + name: stdio.name, + description: description.unwrap_or_default(), + cmd: stdio.command.to_string_lossy().to_string(), + args: stdio.args, + envs: crate::agents::extension::Envs::default(), + env_keys, + timeout, + bundled: Some(false), + available_tools: Vec::new(), + } + } + McpServer::Http(http) => ExtensionConfig::StreamableHttp { + name: http.name, + description: description.unwrap_or_default(), + uri: http.url, + envs: crate::agents::extension::Envs::default(), + env_keys, + headers: http + .headers + .into_iter() + .map(|header| (header.name, header.value)) + .collect(), + timeout, + socket, + bundled: Some(false), + available_tools: Vec::new(), + }, + McpServer::Sse(_) => { + return Err(agent_client_protocol::Error::invalid_params() + .data("SSE is unsupported, migrate to streamable_http")); + } + _ => { + return Err( + agent_client_protocol::Error::invalid_params().data("unsupported MCP server") + ); + } + }, + GooseExtension::InlinePython { + name, + description, + code, + timeout, + dependencies, + } => ExtensionConfig::InlinePython { + name, + description: description.unwrap_or_default(), + code, + timeout, + dependencies: (!dependencies.is_empty()).then_some(dependencies), + available_tools: Vec::new(), + }, + GooseExtension::Frontend { + name, + description, + tools, + instructions, + } => ExtensionConfig::Frontend { + name, + description: description.unwrap_or_default(), + tools: tools + .into_iter() + .map(serde_json::from_value) + .collect::, _>>() + .map_err(|error| { + agent_client_protocol::Error::invalid_params() + .data(format!("bad frontend tool: {error}")) + })?, + instructions, + bundled: Some(false), + available_tools: Vec::new(), + }, + }; + Ok(config) +} + fn config_entry_to_goose_entry( entry: crate::config::extensions::ExtensionEntry, ) -> Result, agent_client_protocol::Error> { @@ -382,6 +690,25 @@ fn config_entry_to_goose_entry( })) } +fn is_server_owned_extension_config(config: &ExtensionConfig) -> bool { + matches!( + config, + ExtensionConfig::Builtin { .. } | ExtensionConfig::Platform { .. } + ) || matches!( + config, + ExtensionConfig::Stdio { + bundled: Some(true), + .. + } | ExtensionConfig::StreamableHttp { + bundled: Some(true), + .. + } | ExtensionConfig::Frontend { + bundled: Some(true), + .. + } + ) +} + impl GooseAcpAgent { pub(super) async fn on_add_extension( &self, @@ -453,22 +780,7 @@ impl GooseAcpAgent { &self, req: AddConfigExtensionRequest, ) -> Result { - let mut obj = match req.extension_config { - serde_json::Value::Object(obj) => obj, - _ => { - return Err(agent_client_protocol::Error::invalid_params() - .data("extensionConfig must be a JSON object")); - } - }; - obj.insert( - "name".to_string(), - serde_json::Value::String(req.name.clone()), - ); - - let config: crate::agents::ExtensionConfig = - serde_json::from_value(serde_json::Value::Object(obj)).map_err(|e| { - agent_client_protocol::Error::invalid_params().data(format!("bad config: {e}")) - })?; + let config = goose_extension_to_config(req.extension)?; crate::config::extensions::set_extension(crate::config::extensions::ExtensionEntry { enabled: req.enabled, @@ -481,25 +793,28 @@ impl GooseAcpAgent { &self, req: RemoveConfigExtensionRequest, ) -> Result { - let keys = crate::config::extensions::get_all_extension_names(); - if !keys.iter().any(|k| k == &req.config_key) { - return Err(agent_client_protocol::Error::invalid_params() - .data(format!("Extension '{}' not found", req.config_key))); + if let Some(entry) = crate::config::get_extension_entry_by_key(&req.config_key) { + if is_server_owned_extension_config(&entry.config) { + return Err(agent_client_protocol::Error::invalid_params() + .data(format!("Extension '{}' cannot be removed", req.config_key))); + } } + crate::config::extensions::remove_extension(&req.config_key); Ok(EmptyResponse {}) } - pub(super) async fn on_toggle_config_extension( + pub(super) async fn on_set_config_extension_enabled( &self, - req: ToggleConfigExtensionRequest, + req: SetConfigExtensionEnabledRequest, ) -> Result { - let keys = crate::config::extensions::get_all_extension_names(); - if !keys.iter().any(|k| k == &req.config_key) { + let updated = + crate::config::extensions::set_extension_enabled(&req.config_key, req.enabled); + if !updated { return Err(agent_client_protocol::Error::invalid_params() .data(format!("Extension '{}' not found", req.config_key))); } - crate::config::extensions::set_extension_enabled(&req.config_key, req.enabled); + Ok(EmptyResponse {}) } diff --git a/crates/goose/src/config/extensions.rs b/crates/goose/src/config/extensions.rs index d2c16d137ebd..f45092b67a28 100644 --- a/crates/goose/src/config/extensions.rs +++ b/crates/goose/src/config/extensions.rs @@ -93,6 +93,10 @@ pub fn get_extension_by_name(name: &str) -> Option { .map(|entry| entry.config.clone()) } +pub fn get_extension_entry_by_key(key: &str) -> Option { + get_extensions_map().get(key).cloned() +} + pub fn set_extension(entry: ExtensionEntry) { let mut extensions = get_extensions_map(); let key = entry.config.key(); @@ -106,12 +110,16 @@ pub fn remove_extension(key: &str) { save_extensions_map(extensions); } -pub fn set_extension_enabled(key: &str, enabled: bool) { +/// Returns true when an existing extension was updated, false when the key was missing. +pub fn set_extension_enabled(key: &str, enabled: bool) -> bool { let mut extensions = get_extensions_map(); - if let Some(entry) = extensions.get_mut(key) { - entry.enabled = enabled; - save_extensions_map(extensions); - } + let Some(entry) = extensions.get_mut(key) else { + return false; + }; + + entry.enabled = enabled; + save_extensions_map(extensions); + true } pub fn get_all_extensions() -> Vec { diff --git a/crates/goose/src/config/mod.rs b/crates/goose/src/config/mod.rs index ae6c46265fc2..e5aa019c2a2a 100644 --- a/crates/goose/src/config/mod.rs +++ b/crates/goose/src/config/mod.rs @@ -18,8 +18,9 @@ pub use declarative_providers::DeclarativeProviderConfig; pub use experiments::ExperimentManager; pub use extensions::{ get_all_extension_names, get_all_extensions, get_available_extensions, get_enabled_extensions, - get_extension_by_name, get_warnings, is_extension_enabled, remove_extension, - resolve_extensions_for_new_session, set_extension, set_extension_enabled, ExtensionEntry, + get_extension_by_name, get_extension_entry_by_key, get_warnings, is_extension_enabled, + remove_extension, resolve_extensions_for_new_session, set_extension, set_extension_enabled, + ExtensionEntry, }; pub use goose_mode::GooseMode; pub use permission::PermissionManager; diff --git a/crates/goose/tests/acp_custom_requests_test.rs b/crates/goose/tests/acp_custom_requests_test.rs index 71afee0ece3d..b8a201a2fe3d 100644 --- a/crates/goose/tests/acp_custom_requests_test.rs +++ b/crates/goose/tests/acp_custom_requests_test.rs @@ -103,7 +103,7 @@ fn test_custom_get_tools() { #[test] #[serial] fn test_custom_get_extensions() { - let config_key = "test-stdio-acp-config-list"; + let config_key = "test-stdio-acp-mutation-flow"; let temp_dir = tempfile::tempdir().unwrap(); let temp_root = temp_dir.path().to_string_lossy().to_string(); let _guard = env_lock::lock_env([ @@ -115,19 +115,6 @@ fn test_custom_get_extensions() { let config_yaml = format!( r#"GOOSE_MODEL: {TEST_MODEL} GOOSE_PROVIDER: openai -extensions: - {config_key}: - enabled: true - type: stdio - name: {config_key} - description: Test stdio - cmd: test-command - args: - - --flag - - value - env_keys: - - SECRET_TOKEN - timeout: 42 "# ); fs::write(config_dir.join(CONFIG_YAML_NAME), config_yaml).unwrap(); @@ -136,23 +123,57 @@ extensions: let openai = OpenAiFixture::new(vec![], Arc::new(EnforceSessionId::default())).await; let conn = AcpServerConnection::new(TestConnectionConfig::default(), openai).await; - let result = send_custom( + let add_result = send_custom( conn.cx(), - "_goose/unstable/config/extensions/list", - serde_json::json!({}), + "_goose/unstable/config/extensions/add", + serde_json::json!({ + "enabled": true, + "extension": { + "type": "mcp", + "description": "Test stdio", + "envKeys": ["SECRET_TOKEN"], + "timeout": 42, + "server": { + "type": "stdio", + "name": config_key, + "command": "test-command", + "args": ["--flag", "value"], + "env": [ + { + "name": "SECRET_TOKEN", + "value": "literal-secret" + } + ] + } + } + }), ) .await; - assert!(result.is_ok(), "expected ok, got: {:?}", result); + assert!(add_result.is_ok(), "expected ok, got: {:?}", add_result); - let response = result.unwrap(); - let extensions = response - .get("extensions") - .and_then(|extensions| extensions.as_array()) - .expect("extensions should be an array"); - let entry = extensions - .iter() - .find(|entry| entry["configKey"] == config_key) - .unwrap_or_else(|| panic!("missing seeded extension entry in response: {response:#?}")); + let list_extension = || async { + let result = send_custom( + conn.cx(), + "_goose/unstable/config/extensions/list", + serde_json::json!({}), + ) + .await; + assert!(result.is_ok(), "expected ok, got: {:?}", result); + + let response = result.unwrap(); + let extensions = response + .get("extensions") + .and_then(|extensions| extensions.as_array()) + .expect("extensions should be an array"); + extensions + .iter() + .find(|entry| entry["configKey"] == config_key) + .cloned() + }; + + let entry = list_extension() + .await + .unwrap_or_else(|| panic!("missing added extension entry")); assert_eq!(entry["enabled"], true); assert_eq!(entry["configKey"], config_key); @@ -168,6 +189,45 @@ extensions: assert_eq!(server["command"], "test-command"); assert_eq!(server["args"], serde_json::json!(["--flag", "value"])); assert_eq!(server["env"], serde_json::json!([])); + + let set_enabled_result = send_custom( + conn.cx(), + "_goose/unstable/config/extensions/set-enabled", + serde_json::json!({ + "configKey": config_key, + "enabled": false, + }), + ) + .await; + assert!( + set_enabled_result.is_ok(), + "expected ok, got: {:?}", + set_enabled_result + ); + + let entry = list_extension() + .await + .unwrap_or_else(|| panic!("missing disabled extension entry")); + assert_eq!(entry["enabled"], false); + + let remove_result = send_custom( + conn.cx(), + "_goose/unstable/config/extensions/remove", + serde_json::json!({ + "configKey": config_key, + }), + ) + .await; + assert!( + remove_result.is_ok(), + "expected ok, got: {:?}", + remove_result + ); + + assert!( + list_extension().await.is_none(), + "removed extension should not be listed" + ); }); } From 9d26cb31950b39ee46e79488ef1874f0a2e0881e Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 3 Jun 2026 19:25:07 +1000 Subject: [PATCH 05/16] reorder --- crates/goose/src/acp/server/extensions.rs | 1371 +++++++++++---------- 1 file changed, 686 insertions(+), 685 deletions(-) diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index 5c9dfca017f5..c48c23d948d1 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -1,492 +1,153 @@ use super::*; -use agent_client_protocol::schema::{HttpHeader, McpServerHttp, McpServerStdio}; +use crate::agents::extension::Envs; +use crate::config::extensions::ExtensionEntry; +use agent_client_protocol::schema::{ + EnvVariable, HttpHeader, McpServer, McpServerHttp, McpServerSse, McpServerStdio, +}; -fn empty_string_to_none(value: &str) -> Option { - if value.is_empty() { - None - } else { - Some(value.to_string()) +impl GooseAcpAgent { + pub(super) async fn on_add_extension( + &self, + req: AddExtensionRequest, + ) -> Result { + let session_id = &req.session_id; + let config: ExtensionConfig = serde_json::from_value(req.config).map_err(|e| { + agent_client_protocol::Error::invalid_params().data(format!("bad config: {e}")) + })?; + let agent = self.get_session_agent(&req.session_id, None).await?; + agent + .add_extension(config, session_id) + .await + .internal_err()?; + Ok(EmptyResponse {}) } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::agents::extension::Envs; - use agent_client_protocol::schema::McpServer; - use rmcp::model::Tool; - use std::collections::HashMap; - #[test] - fn builtin_config_converts_to_goose_builtin_extension() { - let config = ExtensionConfig::Builtin { - name: "developer".to_string(), - description: "Developer tools".to_string(), - display_name: Some("Developer".to_string()), - timeout: Some(30), - bundled: Some(true), - available_tools: vec!["shell".to_string()], - }; + pub(super) async fn on_remove_extension( + &self, + req: RemoveExtensionRequest, + ) -> Result { + let session_id = &req.session_id; + let agent = self.get_session_agent(&req.session_id, None).await?; + agent + .remove_extension(&req.name, session_id) + .await + .internal_err()?; + Ok(EmptyResponse {}) + } - let extension = config_to_goose_extension(&config) - .expect("conversion should succeed") - .expect("builtin should be supported"); + pub(super) async fn on_get_config_extensions( + &self, + ) -> Result { + let extensions = crate::config::extensions::get_all_extensions() + .into_iter() + .filter(|ext| { + !crate::agents::extension_manager::is_hidden_extension(&ext.config.name()) + }) + .collect::>(); + let warnings = crate::config::extensions::get_warnings(); + let extensions = extensions + .into_iter() + .map(config_entry_to_goose_entry) + .collect::, _>>()? + .into_iter() + .flatten() + .collect::>(); + Ok(GetConfigExtensionsResponse { + extensions, + warnings, + }) + } - let GooseExtension::Builtin { - name, - description, - display_name, - } = extension - else { - panic!("expected builtin extension"); - }; + pub(super) async fn on_get_available_extensions( + &self, + ) -> Result { + let extensions = crate::config::get_available_extensions() + .into_iter() + .map(|config| config_to_goose_extension(&config)) + .collect::, _>>()? + .into_iter() + .flatten() + .collect::>(); - assert_eq!(name, "developer"); - assert_eq!(description.as_deref(), Some("Developer tools")); - assert_eq!(display_name.as_deref(), Some("Developer")); + Ok(GetAvailableExtensionsResponse { extensions }) } - #[test] - fn platform_config_converts_to_goose_platform_extension() { - let config = ExtensionConfig::Platform { - name: "todo".to_string(), - description: "Todo tools".to_string(), - display_name: Some("Todo".to_string()), - bundled: Some(true), - available_tools: vec!["write_todos".to_string()], - }; + pub(super) async fn on_add_config_extension( + &self, + req: AddConfigExtensionRequest, + ) -> Result { + let config = goose_extension_to_config(req.extension)?; - let extension = config_to_goose_extension(&config) - .expect("conversion should succeed") - .expect("platform should be supported"); + crate::config::extensions::set_extension(ExtensionEntry { + enabled: req.enabled, + config, + }); + Ok(EmptyResponse {}) + } - let GooseExtension::Platform { - name, - description, - display_name, - } = extension - else { - panic!("expected platform extension"); - }; + pub(super) async fn on_remove_config_extension( + &self, + req: RemoveConfigExtensionRequest, + ) -> Result { + if let Some(entry) = crate::config::get_extension_entry_by_key(&req.config_key) { + if is_server_owned_extension_config(&entry.config) { + return Err(agent_client_protocol::Error::invalid_params() + .data(format!("Extension '{}' cannot be removed", req.config_key))); + } + } - assert_eq!(name, "todo"); - assert_eq!(description.as_deref(), Some("Todo tools")); - assert_eq!(display_name.as_deref(), Some("Todo")); + crate::config::extensions::remove_extension(&req.config_key); + Ok(EmptyResponse {}) } - #[test] - fn stdio_config_converts_to_goose_mcp_extension_without_literal_envs() { - let config = ExtensionConfig::Stdio { - name: "test-stdio".to_string(), - description: "Test stdio".to_string(), - cmd: "test-command".to_string(), - args: vec!["--flag".to_string(), "value".to_string()], - envs: Envs::new(HashMap::from([( - "SECRET_TOKEN".to_string(), - "literal-secret".to_string(), - )])), - env_keys: vec!["SECRET_TOKEN".to_string()], - timeout: Some(42), - bundled: None, - available_tools: vec![], - }; + pub(super) async fn on_set_config_extension_enabled( + &self, + req: SetConfigExtensionEnabledRequest, + ) -> Result { + let updated = + crate::config::extensions::set_extension_enabled(&req.config_key, req.enabled); + if !updated { + return Err(agent_client_protocol::Error::invalid_params() + .data(format!("Extension '{}' not found", req.config_key))); + } - let extension = config_to_goose_extension(&config) - .expect("conversion should succeed") - .expect("stdio should be supported"); + Ok(EmptyResponse {}) + } - let GooseExtension::Mcp { - server, - env_keys, - description, - timeout, - socket, - } = extension - else { - panic!("expected mcp extension"); - }; + pub(super) async fn on_get_session_extensions( + &self, + req: GetSessionExtensionsRequest, + ) -> Result { + let session_id = &req.session_id; + let session = self + .session_manager + .get_session(session_id, false) + .await + .internal_err()?; - assert_eq!(env_keys, vec!["SECRET_TOKEN"]); - assert_eq!(description.as_deref(), Some("Test stdio")); - assert_eq!(timeout, Some(42)); - assert_eq!(socket, None); + let extensions = EnabledExtensionsState::extensions_or_default( + Some(&session.extension_data), + crate::config::Config::global(), + ); - let McpServer::Stdio(stdio) = server else { - panic!("expected stdio server"); - }; + let extensions_json = extensions + .into_iter() + .map(|e| serde_json::to_value(&e)) + .collect::, _>>() + .internal_err()?; - assert_eq!(stdio.name, "test-stdio"); - assert_eq!(stdio.command.to_string_lossy(), "test-command"); - assert_eq!(stdio.args, vec!["--flag", "value"]); - assert!(stdio.env.is_empty(), "literal envs should not be exposed"); + Ok(GetSessionExtensionsResponse { + extensions: extensions_json, + }) } +} - #[test] - fn streamable_http_config_converts_to_goose_mcp_extension_without_literal_envs() { - let config = ExtensionConfig::StreamableHttp { - name: "test-http".to_string(), - description: "Test HTTP".to_string(), - uri: "https://example.com/mcp".to_string(), - envs: Envs::new(HashMap::from([( - "API_TOKEN".to_string(), - "literal-secret".to_string(), - )])), - env_keys: vec!["API_TOKEN".to_string()], - headers: HashMap::from([( - "Authorization".to_string(), - "Bearer ${API_TOKEN}".to_string(), - )]), - timeout: Some(99), - socket: Some("@egress.sock".to_string()), - bundled: None, - available_tools: vec![], - }; - - let extension = config_to_goose_extension(&config) - .expect("conversion should succeed") - .expect("streamable http should be supported"); - - let GooseExtension::Mcp { - server, - env_keys, - description, - timeout, - socket, - } = extension - else { - panic!("expected mcp extension"); - }; - - assert_eq!(env_keys, vec!["API_TOKEN"]); - assert_eq!(description.as_deref(), Some("Test HTTP")); - assert_eq!(timeout, Some(99)); - assert_eq!(socket.as_deref(), Some("@egress.sock")); - - let McpServer::Http(http) = server else { - panic!("expected http server"); - }; - - assert_eq!(http.name, "test-http"); - assert_eq!(http.url, "https://example.com/mcp"); - assert_eq!(http.headers.len(), 1); - assert_eq!(http.headers[0].name, "Authorization"); - assert_eq!(http.headers[0].value, "Bearer ${API_TOKEN}"); - } - - #[test] - fn inline_python_config_converts_to_goose_inline_python_extension() { - let config = ExtensionConfig::InlinePython { - name: "python-tools".to_string(), - description: "Python tools".to_string(), - code: "print('hello')".to_string(), - timeout: Some(12), - dependencies: Some(vec!["requests".to_string()]), - available_tools: vec!["fetch".to_string()], - }; - - let extension = config_to_goose_extension(&config) - .expect("conversion should succeed") - .expect("inline python should be supported"); - - let GooseExtension::InlinePython { - name, - description, - code, - timeout, - dependencies, - } = extension - else { - panic!("expected inline python extension"); - }; - - assert_eq!(name, "python-tools"); - assert_eq!(description.as_deref(), Some("Python tools")); - assert_eq!(code, "print('hello')"); - assert_eq!(timeout, Some(12)); - assert_eq!(dependencies, vec!["requests"]); - } - - #[test] - fn frontend_config_converts_to_goose_frontend_extension() { - let tool = Tool::new( - "pick_color", - "Pick a color", - serde_json::json!({ - "type": "object", - "properties": { - "hex": { "type": "string" } - } - }) - .as_object() - .expect("schema should be object") - .clone(), - ); - let config = ExtensionConfig::Frontend { - name: "frontend-tools".to_string(), - description: "Frontend tools".to_string(), - tools: vec![tool], - instructions: Some("Use frontend tools carefully".to_string()), - bundled: None, - available_tools: vec!["pick_color".to_string()], - }; - - let extension = config_to_goose_extension(&config) - .expect("conversion should succeed") - .expect("frontend should be supported"); - - let GooseExtension::Frontend { - name, - description, - tools, - instructions, - } = extension - else { - panic!("expected frontend extension"); - }; - - assert_eq!(name, "frontend-tools"); - assert_eq!(description.as_deref(), Some("Frontend tools")); - assert_eq!( - instructions.as_deref(), - Some("Use frontend tools carefully") - ); - assert_eq!(tools.len(), 1); - assert_eq!(tools[0]["name"], "pick_color"); - assert_eq!(tools[0]["description"], "Pick a color"); - } - - #[test] - fn sse_config_is_skipped() { - let config = ExtensionConfig::Sse { - name: "legacy-sse".to_string(), - description: "Legacy SSE".to_string(), - uri: Some("https://example.com/sse".to_string()), - }; - - let extension = config_to_goose_extension(&config).expect("conversion should succeed"); - - assert!(extension.is_none()); - } - - #[test] - fn goose_mcp_stdio_extension_converts_to_config_without_literal_envs() { - let extension = GooseExtension::Mcp { - server: McpServer::Stdio( - McpServerStdio::new("test-stdio", "test-command") - .args(vec!["--flag".to_string(), "value".to_string()]) - .env(vec![agent_client_protocol::schema::EnvVariable::new( - "SECRET_TOKEN", - "literal-secret", - )]), - ), - env_keys: vec!["SECRET_TOKEN".to_string()], - description: Some("Test stdio".to_string()), - timeout: Some(42), - socket: None, - }; - - let config = goose_extension_to_config(extension).expect("conversion should succeed"); - - let ExtensionConfig::Stdio { - name, - description, - cmd, - args, - envs, - env_keys, - timeout, - bundled, - available_tools, - } = config - else { - panic!("expected stdio config"); - }; - - assert_eq!(name, "test-stdio"); - assert_eq!(description, "Test stdio"); - assert_eq!(cmd, "test-command"); - assert_eq!(args, vec!["--flag", "value"]); - assert!( - envs.get_env().is_empty(), - "literal envs should not be persisted" - ); - assert_eq!(env_keys, vec!["SECRET_TOKEN"]); - assert_eq!(timeout, Some(42)); - assert_eq!(bundled, Some(false)); - assert!(available_tools.is_empty()); - } - - #[test] - fn goose_mcp_streamable_http_extension_converts_to_config_without_literal_envs() { - let extension = GooseExtension::Mcp { - server: McpServer::Http( - McpServerHttp::new("test-http", "https://example.com/mcp").headers(vec![ - HttpHeader::new("Authorization", "Bearer ${API_TOKEN}"), - ]), - ), - env_keys: vec!["API_TOKEN".to_string()], - description: Some("Test HTTP".to_string()), - timeout: Some(99), - socket: Some("@egress.sock".to_string()), - }; - - let config = goose_extension_to_config(extension).expect("conversion should succeed"); - - let ExtensionConfig::StreamableHttp { - name, - description, - uri, - envs, - env_keys, - headers, - timeout, - socket, - bundled, - available_tools, - } = config - else { - panic!("expected streamable http config"); - }; - - assert_eq!(name, "test-http"); - assert_eq!(description, "Test HTTP"); - assert_eq!(uri, "https://example.com/mcp"); - assert!( - envs.get_env().is_empty(), - "literal envs should not be persisted" - ); - assert_eq!(env_keys, vec!["API_TOKEN"]); - assert_eq!( - headers, - HashMap::from([( - "Authorization".to_string(), - "Bearer ${API_TOKEN}".to_string() - )]) - ); - assert_eq!(timeout, Some(99)); - assert_eq!(socket.as_deref(), Some("@egress.sock")); - assert_eq!(bundled, Some(false)); - assert!(available_tools.is_empty()); - } - - #[test] - fn goose_inline_python_extension_converts_to_config() { - let extension = GooseExtension::InlinePython { - name: "python-tools".to_string(), - description: Some("Python tools".to_string()), - code: "print('hello')".to_string(), - timeout: Some(12), - dependencies: vec!["requests".to_string()], - }; - - let config = goose_extension_to_config(extension).expect("conversion should succeed"); - - let ExtensionConfig::InlinePython { - name, - description, - code, - timeout, - dependencies, - available_tools, - } = config - else { - panic!("expected inline python config"); - }; - - assert_eq!(name, "python-tools"); - assert_eq!(description, "Python tools"); - assert_eq!(code, "print('hello')"); - assert_eq!(timeout, Some(12)); - assert_eq!(dependencies, Some(vec!["requests".to_string()])); - assert!(available_tools.is_empty()); - } - - #[test] - fn goose_frontend_extension_converts_to_config() { - let tool = serde_json::json!({ - "name": "pick_color", - "description": "Pick a color", - "inputSchema": { - "type": "object", - "properties": { - "hex": { "type": "string" } - } - } - }); - let extension = GooseExtension::Frontend { - name: "frontend-tools".to_string(), - description: Some("Frontend tools".to_string()), - tools: vec![tool], - instructions: Some("Use frontend tools carefully".to_string()), - }; - - let config = goose_extension_to_config(extension).expect("conversion should succeed"); - - let ExtensionConfig::Frontend { - name, - description, - tools, - instructions, - bundled, - available_tools, - } = config - else { - panic!("expected frontend config"); - }; - - assert_eq!(name, "frontend-tools"); - assert_eq!(description, "Frontend tools"); - assert_eq!(tools.len(), 1); - assert_eq!(tools[0].name, "pick_color"); - assert_eq!(tools[0].description.as_deref(), Some("Pick a color")); - assert_eq!( - instructions.as_deref(), - Some("Use frontend tools carefully") - ); - assert_eq!(bundled, Some(false)); - assert!(available_tools.is_empty()); - } - - #[test] - fn goose_builtin_and_platform_extensions_are_rejected_for_config_add() { - let builtin = GooseExtension::Builtin { - name: "developer".to_string(), - description: None, - display_name: None, - }; - let platform = GooseExtension::Platform { - name: "todo".to_string(), - description: None, - display_name: None, - }; - - assert!(goose_extension_to_config(builtin).is_err()); - assert!(goose_extension_to_config(platform).is_err()); - } - - #[test] - fn goose_mcp_sse_extension_is_rejected_for_config_add() { - let extension = GooseExtension::Mcp { - server: McpServer::Sse(agent_client_protocol::schema::McpServerSse::new( - "legacy-sse", - "https://example.com/sse", - )), - env_keys: Vec::new(), - description: None, - timeout: None, - socket: None, - }; - - assert!(goose_extension_to_config(extension).is_err()); - } -} - -fn config_to_goose_extension( - config: &ExtensionConfig, -) -> Result, agent_client_protocol::Error> { - let extension = match config { - ExtensionConfig::Builtin { - name, +fn config_to_goose_extension( + config: &ExtensionConfig, +) -> Result, agent_client_protocol::Error> { + let extension = match config { + ExtensionConfig::Builtin { + name, description, display_name, .. @@ -594,254 +255,594 @@ fn goose_extension_to_config( description, timeout, socket, - } => match server { - McpServer::Stdio(stdio) => { - if socket.is_some() { - return Err(agent_client_protocol::Error::invalid_params() - .data("socket is only supported for streamable_http MCP extensions")); - } - ExtensionConfig::Stdio { - name: stdio.name, - description: description.unwrap_or_default(), - cmd: stdio.command.to_string_lossy().to_string(), - args: stdio.args, - envs: crate::agents::extension::Envs::default(), - env_keys, - timeout, - bundled: Some(false), - available_tools: Vec::new(), - } - } - McpServer::Http(http) => ExtensionConfig::StreamableHttp { - name: http.name, - description: description.unwrap_or_default(), - uri: http.url, - envs: crate::agents::extension::Envs::default(), - env_keys, - headers: http - .headers - .into_iter() - .map(|header| (header.name, header.value)) - .collect(), - timeout, - socket, - bundled: Some(false), - available_tools: Vec::new(), - }, - McpServer::Sse(_) => { - return Err(agent_client_protocol::Error::invalid_params() - .data("SSE is unsupported, migrate to streamable_http")); - } - _ => { - return Err( - agent_client_protocol::Error::invalid_params().data("unsupported MCP server") - ); - } - }, - GooseExtension::InlinePython { + } => match server { + McpServer::Stdio(stdio) => { + if socket.is_some() { + return Err(agent_client_protocol::Error::invalid_params() + .data("socket is only supported for streamable_http MCP extensions")); + } + ExtensionConfig::Stdio { + name: stdio.name, + description: description.unwrap_or_default(), + cmd: stdio.command.to_string_lossy().to_string(), + args: stdio.args, + envs: Envs::default(), + env_keys, + timeout, + bundled: Some(false), + available_tools: Vec::new(), + } + } + McpServer::Http(http) => ExtensionConfig::StreamableHttp { + name: http.name, + description: description.unwrap_or_default(), + uri: http.url, + envs: Envs::default(), + env_keys, + headers: http + .headers + .into_iter() + .map(|header| (header.name, header.value)) + .collect(), + timeout, + socket, + bundled: Some(false), + available_tools: Vec::new(), + }, + McpServer::Sse(_) => { + return Err(agent_client_protocol::Error::invalid_params() + .data("SSE is unsupported, migrate to streamable_http")); + } + _ => { + return Err( + agent_client_protocol::Error::invalid_params().data("unsupported MCP server") + ); + } + }, + GooseExtension::InlinePython { + name, + description, + code, + timeout, + dependencies, + } => ExtensionConfig::InlinePython { + name, + description: description.unwrap_or_default(), + code, + timeout, + dependencies: (!dependencies.is_empty()).then_some(dependencies), + available_tools: Vec::new(), + }, + GooseExtension::Frontend { + name, + description, + tools, + instructions, + } => ExtensionConfig::Frontend { + name, + description: description.unwrap_or_default(), + tools: tools + .into_iter() + .map(serde_json::from_value) + .collect::, _>>() + .map_err(|error| { + agent_client_protocol::Error::invalid_params() + .data(format!("bad frontend tool: {error}")) + })?, + instructions, + bundled: Some(false), + available_tools: Vec::new(), + }, + }; + Ok(config) +} + +fn config_entry_to_goose_entry( + entry: ExtensionEntry, +) -> Result, agent_client_protocol::Error> { + let config_key = entry.config.key(); + let Some(extension) = config_to_goose_extension(&entry.config)? else { + return Ok(None); + }; + Ok(Some(GooseExtensionEntry { + extension, + enabled: entry.enabled, + config_key: Some(config_key), + })) +} + +fn is_server_owned_extension_config(config: &ExtensionConfig) -> bool { + matches!( + config, + ExtensionConfig::Builtin { .. } | ExtensionConfig::Platform { .. } + ) || matches!( + config, + ExtensionConfig::Stdio { + bundled: Some(true), + .. + } | ExtensionConfig::StreamableHttp { + bundled: Some(true), + .. + } | ExtensionConfig::Frontend { + bundled: Some(true), + .. + } + ) +} + +fn empty_string_to_none(value: &str) -> Option { + if value.is_empty() { + None + } else { + Some(value.to_string()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::agents::extension::Envs; + use agent_client_protocol::schema::{McpServer, McpServerSse}; + use rmcp::model::Tool; + use std::collections::HashMap; + + #[test] + fn builtin_config_converts_to_goose_builtin_extension() { + let config = ExtensionConfig::Builtin { + name: "developer".to_string(), + description: "Developer tools".to_string(), + display_name: Some("Developer".to_string()), + timeout: Some(30), + bundled: Some(true), + available_tools: vec!["shell".to_string()], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("builtin should be supported"); + + let GooseExtension::Builtin { + name, + description, + display_name, + } = extension + else { + panic!("expected builtin extension"); + }; + + assert_eq!(name, "developer"); + assert_eq!(description.as_deref(), Some("Developer tools")); + assert_eq!(display_name.as_deref(), Some("Developer")); + } + + #[test] + fn platform_config_converts_to_goose_platform_extension() { + let config = ExtensionConfig::Platform { + name: "todo".to_string(), + description: "Todo tools".to_string(), + display_name: Some("Todo".to_string()), + bundled: Some(true), + available_tools: vec!["write_todos".to_string()], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("platform should be supported"); + + let GooseExtension::Platform { + name, + description, + display_name, + } = extension + else { + panic!("expected platform extension"); + }; + + assert_eq!(name, "todo"); + assert_eq!(description.as_deref(), Some("Todo tools")); + assert_eq!(display_name.as_deref(), Some("Todo")); + } + + #[test] + fn stdio_config_converts_to_goose_mcp_extension_without_literal_envs() { + let config = ExtensionConfig::Stdio { + name: "test-stdio".to_string(), + description: "Test stdio".to_string(), + cmd: "test-command".to_string(), + args: vec!["--flag".to_string(), "value".to_string()], + envs: Envs::new(HashMap::from([( + "SECRET_TOKEN".to_string(), + "literal-secret".to_string(), + )])), + env_keys: vec!["SECRET_TOKEN".to_string()], + timeout: Some(42), + bundled: None, + available_tools: vec![], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("stdio should be supported"); + + let GooseExtension::Mcp { + server, + env_keys, + description, + timeout, + socket, + } = extension + else { + panic!("expected mcp extension"); + }; + + assert_eq!(env_keys, vec!["SECRET_TOKEN"]); + assert_eq!(description.as_deref(), Some("Test stdio")); + assert_eq!(timeout, Some(42)); + assert_eq!(socket, None); + + let McpServer::Stdio(stdio) = server else { + panic!("expected stdio server"); + }; + + assert_eq!(stdio.name, "test-stdio"); + assert_eq!(stdio.command.to_string_lossy(), "test-command"); + assert_eq!(stdio.args, vec!["--flag", "value"]); + assert!(stdio.env.is_empty(), "literal envs should not be exposed"); + } + + #[test] + fn streamable_http_config_converts_to_goose_mcp_extension_without_literal_envs() { + let config = ExtensionConfig::StreamableHttp { + name: "test-http".to_string(), + description: "Test HTTP".to_string(), + uri: "https://example.com/mcp".to_string(), + envs: Envs::new(HashMap::from([( + "API_TOKEN".to_string(), + "literal-secret".to_string(), + )])), + env_keys: vec!["API_TOKEN".to_string()], + headers: HashMap::from([( + "Authorization".to_string(), + "Bearer ${API_TOKEN}".to_string(), + )]), + timeout: Some(99), + socket: Some("@egress.sock".to_string()), + bundled: None, + available_tools: vec![], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("streamable http should be supported"); + + let GooseExtension::Mcp { + server, + env_keys, + description, + timeout, + socket, + } = extension + else { + panic!("expected mcp extension"); + }; + + assert_eq!(env_keys, vec!["API_TOKEN"]); + assert_eq!(description.as_deref(), Some("Test HTTP")); + assert_eq!(timeout, Some(99)); + assert_eq!(socket.as_deref(), Some("@egress.sock")); + + let McpServer::Http(http) = server else { + panic!("expected http server"); + }; + + assert_eq!(http.name, "test-http"); + assert_eq!(http.url, "https://example.com/mcp"); + assert_eq!(http.headers.len(), 1); + assert_eq!(http.headers[0].name, "Authorization"); + assert_eq!(http.headers[0].value, "Bearer ${API_TOKEN}"); + } + + #[test] + fn inline_python_config_converts_to_goose_inline_python_extension() { + let config = ExtensionConfig::InlinePython { + name: "python-tools".to_string(), + description: "Python tools".to_string(), + code: "print('hello')".to_string(), + timeout: Some(12), + dependencies: Some(vec!["requests".to_string()]), + available_tools: vec!["fetch".to_string()], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("inline python should be supported"); + + let GooseExtension::InlinePython { name, description, code, timeout, dependencies, - } => ExtensionConfig::InlinePython { - name, - description: description.unwrap_or_default(), - code, - timeout, - dependencies: (!dependencies.is_empty()).then_some(dependencies), - available_tools: Vec::new(), - }, - GooseExtension::Frontend { + } = extension + else { + panic!("expected inline python extension"); + }; + + assert_eq!(name, "python-tools"); + assert_eq!(description.as_deref(), Some("Python tools")); + assert_eq!(code, "print('hello')"); + assert_eq!(timeout, Some(12)); + assert_eq!(dependencies, vec!["requests"]); + } + + #[test] + fn frontend_config_converts_to_goose_frontend_extension() { + let tool = Tool::new( + "pick_color", + "Pick a color", + serde_json::json!({ + "type": "object", + "properties": { + "hex": { "type": "string" } + } + }) + .as_object() + .expect("schema should be object") + .clone(), + ); + let config = ExtensionConfig::Frontend { + name: "frontend-tools".to_string(), + description: "Frontend tools".to_string(), + tools: vec![tool], + instructions: Some("Use frontend tools carefully".to_string()), + bundled: None, + available_tools: vec!["pick_color".to_string()], + }; + + let extension = config_to_goose_extension(&config) + .expect("conversion should succeed") + .expect("frontend should be supported"); + + let GooseExtension::Frontend { name, description, tools, instructions, - } => ExtensionConfig::Frontend { - name, - description: description.unwrap_or_default(), - tools: tools - .into_iter() - .map(serde_json::from_value) - .collect::, _>>() - .map_err(|error| { - agent_client_protocol::Error::invalid_params() - .data(format!("bad frontend tool: {error}")) - })?, - instructions, - bundled: Some(false), - available_tools: Vec::new(), - }, - }; - Ok(config) -} + } = extension + else { + panic!("expected frontend extension"); + }; -fn config_entry_to_goose_entry( - entry: crate::config::extensions::ExtensionEntry, -) -> Result, agent_client_protocol::Error> { - let config_key = entry.config.key(); - let Some(extension) = config_to_goose_extension(&entry.config)? else { - return Ok(None); - }; - Ok(Some(GooseExtensionEntry { - extension, - enabled: entry.enabled, - config_key: Some(config_key), - })) -} + assert_eq!(name, "frontend-tools"); + assert_eq!(description.as_deref(), Some("Frontend tools")); + assert_eq!( + instructions.as_deref(), + Some("Use frontend tools carefully") + ); + assert_eq!(tools.len(), 1); + assert_eq!(tools[0]["name"], "pick_color"); + assert_eq!(tools[0]["description"], "Pick a color"); + } -fn is_server_owned_extension_config(config: &ExtensionConfig) -> bool { - matches!( - config, - ExtensionConfig::Builtin { .. } | ExtensionConfig::Platform { .. } - ) || matches!( - config, - ExtensionConfig::Stdio { - bundled: Some(true), - .. - } | ExtensionConfig::StreamableHttp { - bundled: Some(true), - .. - } | ExtensionConfig::Frontend { - bundled: Some(true), - .. - } - ) -} + #[test] + fn sse_config_is_skipped() { + let config = ExtensionConfig::Sse { + name: "legacy-sse".to_string(), + description: "Legacy SSE".to_string(), + uri: Some("https://example.com/sse".to_string()), + }; -impl GooseAcpAgent { - pub(super) async fn on_add_extension( - &self, - req: AddExtensionRequest, - ) -> Result { - let session_id = &req.session_id; - let config: ExtensionConfig = serde_json::from_value(req.config).map_err(|e| { - agent_client_protocol::Error::invalid_params().data(format!("bad config: {e}")) - })?; - let agent = self.get_session_agent(&req.session_id, None).await?; - agent - .add_extension(config, session_id) - .await - .internal_err()?; - Ok(EmptyResponse {}) + let extension = config_to_goose_extension(&config).expect("conversion should succeed"); + + assert!(extension.is_none()); } - pub(super) async fn on_remove_extension( - &self, - req: RemoveExtensionRequest, - ) -> Result { - let session_id = &req.session_id; - let agent = self.get_session_agent(&req.session_id, None).await?; - agent - .remove_extension(&req.name, session_id) - .await - .internal_err()?; - Ok(EmptyResponse {}) + #[test] + fn goose_mcp_stdio_extension_converts_to_config_without_literal_envs() { + let extension = GooseExtension::Mcp { + server: McpServer::Stdio( + McpServerStdio::new("test-stdio", "test-command") + .args(vec!["--flag".to_string(), "value".to_string()]) + .env(vec![agent_client_protocol::schema::EnvVariable::new( + "SECRET_TOKEN", + "literal-secret", + )]), + ), + env_keys: vec!["SECRET_TOKEN".to_string()], + description: Some("Test stdio".to_string()), + timeout: Some(42), + socket: None, + }; + + let config = goose_extension_to_config(extension).expect("conversion should succeed"); + + let ExtensionConfig::Stdio { + name, + description, + cmd, + args, + envs, + env_keys, + timeout, + bundled, + available_tools, + } = config + else { + panic!("expected stdio config"); + }; + + assert_eq!(name, "test-stdio"); + assert_eq!(description, "Test stdio"); + assert_eq!(cmd, "test-command"); + assert_eq!(args, vec!["--flag", "value"]); + assert!( + envs.get_env().is_empty(), + "literal envs should not be persisted" + ); + assert_eq!(env_keys, vec!["SECRET_TOKEN"]); + assert_eq!(timeout, Some(42)); + assert_eq!(bundled, Some(false)); + assert!(available_tools.is_empty()); } - pub(super) async fn on_get_config_extensions( - &self, - ) -> Result { - let extensions = crate::config::extensions::get_all_extensions() - .into_iter() - .filter(|ext| { - !crate::agents::extension_manager::is_hidden_extension(&ext.config.name()) - }) - .collect::>(); - let warnings = crate::config::extensions::get_warnings(); - let extensions = extensions - .into_iter() - .map(config_entry_to_goose_entry) - .collect::, _>>()? - .into_iter() - .flatten() - .collect::>(); - Ok(GetConfigExtensionsResponse { - extensions, - warnings, - }) - } + #[test] + fn goose_mcp_streamable_http_extension_converts_to_config_without_literal_envs() { + let extension = GooseExtension::Mcp { + server: McpServer::Http( + McpServerHttp::new("test-http", "https://example.com/mcp").headers(vec![ + HttpHeader::new("Authorization", "Bearer ${API_TOKEN}"), + ]), + ), + env_keys: vec!["API_TOKEN".to_string()], + description: Some("Test HTTP".to_string()), + timeout: Some(99), + socket: Some("@egress.sock".to_string()), + }; - pub(super) async fn on_get_available_extensions( - &self, - ) -> Result { - let extensions = crate::config::get_available_extensions() - .into_iter() - .map(|config| config_to_goose_extension(&config)) - .collect::, _>>()? - .into_iter() - .flatten() - .collect::>(); + let config = goose_extension_to_config(extension).expect("conversion should succeed"); - Ok(GetAvailableExtensionsResponse { extensions }) + let ExtensionConfig::StreamableHttp { + name, + description, + uri, + envs, + env_keys, + headers, + timeout, + socket, + bundled, + available_tools, + } = config + else { + panic!("expected streamable http config"); + }; + + assert_eq!(name, "test-http"); + assert_eq!(description, "Test HTTP"); + assert_eq!(uri, "https://example.com/mcp"); + assert!( + envs.get_env().is_empty(), + "literal envs should not be persisted" + ); + assert_eq!(env_keys, vec!["API_TOKEN"]); + assert_eq!( + headers, + HashMap::from([( + "Authorization".to_string(), + "Bearer ${API_TOKEN}".to_string() + )]) + ); + assert_eq!(timeout, Some(99)); + assert_eq!(socket.as_deref(), Some("@egress.sock")); + assert_eq!(bundled, Some(false)); + assert!(available_tools.is_empty()); } - pub(super) async fn on_add_config_extension( - &self, - req: AddConfigExtensionRequest, - ) -> Result { - let config = goose_extension_to_config(req.extension)?; + #[test] + fn goose_inline_python_extension_converts_to_config() { + let extension = GooseExtension::InlinePython { + name: "python-tools".to_string(), + description: Some("Python tools".to_string()), + code: "print('hello')".to_string(), + timeout: Some(12), + dependencies: vec!["requests".to_string()], + }; - crate::config::extensions::set_extension(crate::config::extensions::ExtensionEntry { - enabled: req.enabled, - config, - }); - Ok(EmptyResponse {}) + let config = goose_extension_to_config(extension).expect("conversion should succeed"); + + let ExtensionConfig::InlinePython { + name, + description, + code, + timeout, + dependencies, + available_tools, + } = config + else { + panic!("expected inline python config"); + }; + + assert_eq!(name, "python-tools"); + assert_eq!(description, "Python tools"); + assert_eq!(code, "print('hello')"); + assert_eq!(timeout, Some(12)); + assert_eq!(dependencies, Some(vec!["requests".to_string()])); + assert!(available_tools.is_empty()); } - pub(super) async fn on_remove_config_extension( - &self, - req: RemoveConfigExtensionRequest, - ) -> Result { - if let Some(entry) = crate::config::get_extension_entry_by_key(&req.config_key) { - if is_server_owned_extension_config(&entry.config) { - return Err(agent_client_protocol::Error::invalid_params() - .data(format!("Extension '{}' cannot be removed", req.config_key))); + #[test] + fn goose_frontend_extension_converts_to_config() { + let tool = serde_json::json!({ + "name": "pick_color", + "description": "Pick a color", + "inputSchema": { + "type": "object", + "properties": { + "hex": { "type": "string" } + } } - } + }); + let extension = GooseExtension::Frontend { + name: "frontend-tools".to_string(), + description: Some("Frontend tools".to_string()), + tools: vec![tool], + instructions: Some("Use frontend tools carefully".to_string()), + }; - crate::config::extensions::remove_extension(&req.config_key); - Ok(EmptyResponse {}) - } + let config = goose_extension_to_config(extension).expect("conversion should succeed"); - pub(super) async fn on_set_config_extension_enabled( - &self, - req: SetConfigExtensionEnabledRequest, - ) -> Result { - let updated = - crate::config::extensions::set_extension_enabled(&req.config_key, req.enabled); - if !updated { - return Err(agent_client_protocol::Error::invalid_params() - .data(format!("Extension '{}' not found", req.config_key))); - } + let ExtensionConfig::Frontend { + name, + description, + tools, + instructions, + bundled, + available_tools, + } = config + else { + panic!("expected frontend config"); + }; - Ok(EmptyResponse {}) + assert_eq!(name, "frontend-tools"); + assert_eq!(description, "Frontend tools"); + assert_eq!(tools.len(), 1); + assert_eq!(tools[0].name, "pick_color"); + assert_eq!(tools[0].description.as_deref(), Some("Pick a color")); + assert_eq!( + instructions.as_deref(), + Some("Use frontend tools carefully") + ); + assert_eq!(bundled, Some(false)); + assert!(available_tools.is_empty()); } - pub(super) async fn on_get_session_extensions( - &self, - req: GetSessionExtensionsRequest, - ) -> Result { - let session_id = &req.session_id; - let session = self - .session_manager - .get_session(session_id, false) - .await - .internal_err()?; + #[test] + fn goose_builtin_and_platform_extensions_are_rejected_for_config_add() { + let builtin = GooseExtension::Builtin { + name: "developer".to_string(), + description: None, + display_name: None, + }; + let platform = GooseExtension::Platform { + name: "todo".to_string(), + description: None, + display_name: None, + }; - let extensions = EnabledExtensionsState::extensions_or_default( - Some(&session.extension_data), - crate::config::Config::global(), - ); + assert!(goose_extension_to_config(builtin).is_err()); + assert!(goose_extension_to_config(platform).is_err()); + } - let extensions_json = extensions - .into_iter() - .map(|e| serde_json::to_value(&e)) - .collect::, _>>() - .internal_err()?; + #[test] + fn goose_mcp_sse_extension_is_rejected_for_config_add() { + let extension = GooseExtension::Mcp { + server: McpServer::Sse(McpServerSse::new("legacy-sse", "https://example.com/sse")), + env_keys: Vec::new(), + description: None, + timeout: None, + socket: None, + }; - Ok(GetSessionExtensionsResponse { - extensions: extensions_json, - }) + assert!(goose_extension_to_config(extension).is_err()); } } From adf02fdad826852fa19e0d5801a6ffe13726c390 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 3 Jun 2026 20:25:14 +1000 Subject: [PATCH 06/16] update the schema --- crates/goose/acp-meta.json | 13 +- crates/goose/acp-schema.json | 473 +++++++++++++++++++++- crates/goose/src/acp/server/extensions.rs | 2 +- ui/sdk/src/generated/client.gen.ts | 37 +- ui/sdk/src/generated/index.ts | 15 +- ui/sdk/src/generated/types.gen.ts | 216 +++++++++- ui/sdk/src/generated/zod.gen.ts | 190 ++++++++- 7 files changed, 877 insertions(+), 69 deletions(-) diff --git a/crates/goose/acp-meta.json b/crates/goose/acp-meta.json index e1d6679ef976..12e366f120e8 100644 --- a/crates/goose/acp-meta.json +++ b/crates/goose/acp-meta.json @@ -42,8 +42,13 @@ }, { "method": "_goose/unstable/config/extensions/list", - "requestType": "GetExtensionsRequest_unstable", - "responseType": "GetExtensionsResponse_unstable" + "requestType": "GetConfigExtensionsRequest_unstable", + "responseType": "GetConfigExtensionsResponse_unstable" + }, + { + "method": "_goose/unstable/extensions/available", + "requestType": "GetAvailableExtensionsRequest_unstable", + "responseType": "GetAvailableExtensionsResponse_unstable" }, { "method": "_goose/unstable/config/extensions/add", @@ -56,8 +61,8 @@ "responseType": "EmptyResponse" }, { - "method": "_goose/unstable/config/extensions/toggle", - "requestType": "ToggleConfigExtensionRequest_unstable", + "method": "_goose/unstable/config/extensions/set-enabled", + "requestType": "SetConfigExtensionEnabledRequest_unstable", "responseType": "EmptyResponse" }, { diff --git a/crates/goose/acp-schema.json b/crates/goose/acp-schema.json index 9afa77e6c4a0..de665330aafd 100644 --- a/crates/goose/acp-schema.json +++ b/crates/goose/acp-schema.json @@ -224,19 +224,20 @@ "x-side": "agent", "x-method": "session/delete" }, - "GetExtensionsRequest_unstable": { + "GetConfigExtensionsRequest_unstable": { "type": "object", "description": "List configured extensions and any warnings.", "x-side": "agent", "x-method": "_goose/unstable/config/extensions/list" }, - "GetExtensionsResponse_unstable": { + "GetConfigExtensionsResponse_unstable": { "type": "object", "properties": { "extensions": { "type": "array", - "items": {}, - "description": "Array of ExtensionEntry objects with `enabled` flag, `configKey`, and flattened config details." + "items": { + "$ref": "#/$defs/GooseExtensionEntry" + } }, "warnings": { "type": "array", @@ -246,22 +247,433 @@ } }, "required": [ - "extensions", - "warnings" + "extensions" ], "description": "List configured extensions and any warnings.", "x-side": "agent", "x-method": "_goose/unstable/config/extensions/list" }, - "AddConfigExtensionRequest_unstable": { + "GooseExtensionEntry": { + "type": "object", + "properties": { + "extension": { + "$ref": "#/$defs/GooseExtension" + }, + "enabled": { + "type": "boolean" + }, + "configKey": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "extension", + "enabled" + ] + }, + "GooseExtension": { + "oneOf": [ + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "const": "builtin" + } + }, + "required": [ + "type", + "name" + ] + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "const": "platform" + } + }, + "required": [ + "type", + "name" + ] + }, + { + "type": "object", + "properties": { + "server": { + "$ref": "#/$defs/McpServer" + }, + "envKeys": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "timeout": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "socket": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "const": "mcp" + } + }, + "required": [ + "type", + "server" + ] + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "code": { + "type": "string" + }, + "timeout": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "dependencies": { + "type": "array", + "items": { + "type": "string" + } + }, + "type": { + "type": "string", + "const": "inline_python" + } + }, + "required": [ + "type", + "name", + "code" + ] + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "tools": { + "type": "array", + "items": {} + }, + "instructions": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "const": "frontend" + } + }, + "required": [ + "type", + "name" + ] + } + ] + }, + "McpServer": { + "anyOf": [ + { + "$ref": "#/$defs/McpServerHttp", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "http" + } + }, + "required": [ + "type" + ], + "description": "HTTP transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.http` is `true`." + }, + { + "$ref": "#/$defs/McpServerSse", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "sse" + } + }, + "required": [ + "type" + ], + "description": "SSE transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`." + }, + { + "$ref": "#/$defs/McpServerStdio", + "description": "Stdio transport configuration\n\nAll Agents MUST support this transport." + } + ], + "description": "Configuration for connecting to an MCP (Model Context Protocol) server.\n\nMCP servers provide tools and context that the agent can use when\nprocessing prompts.\n\nSee protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)" + }, + "HttpHeader": { "type": "object", "properties": { "name": { - "type": "string" + "type": "string", + "description": "The name of the HTTP header." }, - "extensionConfig": { - "description": "Extension configuration. Must be a JSON object matching one of the\n`ExtensionConfig` variants (e.g. `stdio`, `streamable_http`, `builtin`).\n`name` and `enabled` are injected server-side.", - "default": null + "value": { + "type": "string", + "description": "The value to set for the HTTP header." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + } + }, + "required": [ + "name", + "value" + ], + "description": "An HTTP header to set when making requests to the MCP server." + }, + "McpServerHttp": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Human-readable name identifying this MCP server." + }, + "url": { + "type": "string", + "description": "URL to the MCP server." + }, + "headers": { + "type": "array", + "items": { + "$ref": "#/$defs/HttpHeader" + }, + "description": "HTTP headers to set when making requests to the MCP server." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + } + }, + "required": [ + "name", + "url", + "headers" + ], + "description": "HTTP transport configuration for MCP." + }, + "McpServerSse": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Human-readable name identifying this MCP server." + }, + "url": { + "type": "string", + "description": "URL to the MCP server." + }, + "headers": { + "type": "array", + "items": { + "$ref": "#/$defs/HttpHeader" + }, + "description": "HTTP headers to set when making requests to the MCP server." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + } + }, + "required": [ + "name", + "url", + "headers" + ], + "description": "SSE transport configuration for MCP." + }, + "McpServerStdio": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Human-readable name identifying this MCP server." + }, + "command": { + "type": "string", + "description": "Path to the MCP server executable." + }, + "args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Command-line arguments to pass to the MCP server." + }, + "env": { + "type": "array", + "items": { + "$ref": "#/$defs/EnvVariable" + }, + "description": "Environment variables to set when launching the MCP server." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + } + }, + "required": [ + "name", + "command", + "args", + "env" + ], + "description": "Stdio transport configuration for MCP." + }, + "EnvVariable": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the environment variable." + }, + "value": { + "type": "string", + "description": "The value to set for the environment variable." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + } + }, + "required": [ + "name", + "value" + ], + "description": "An environment variable to set when launching an MCP server." + }, + "GetAvailableExtensionsRequest_unstable": { + "type": "object", + "description": "List Goose-owned extension definitions available to configure or enable.", + "x-side": "agent", + "x-method": "_goose/unstable/extensions/available" + }, + "GetAvailableExtensionsResponse_unstable": { + "type": "object", + "properties": { + "extensions": { + "type": "array", + "items": { + "$ref": "#/$defs/GooseExtension" + } + } + }, + "required": [ + "extensions" + ], + "x-side": "agent", + "x-method": "_goose/unstable/extensions/available" + }, + "AddConfigExtensionRequest_unstable": { + "type": "object", + "properties": { + "extension": { + "$ref": "#/$defs/GooseExtension" }, "enabled": { "type": "boolean", @@ -269,7 +681,7 @@ } }, "required": [ - "name" + "extension" ], "description": "Persist a new extension to the user's global goose config.", "x-side": "agent", @@ -289,7 +701,7 @@ "x-side": "agent", "x-method": "_goose/unstable/config/extensions/remove" }, - "ToggleConfigExtensionRequest_unstable": { + "SetConfigExtensionEnabledRequest_unstable": { "type": "object", "properties": { "configKey": { @@ -303,9 +715,9 @@ "configKey", "enabled" ], - "description": "Toggle the `enabled` flag for a persisted extension in the user's global goose config.", + "description": "Set the `enabled` flag for a persisted extension in the user's global goose config.", "x-side": "agent", - "x-method": "_goose/unstable/config/extensions/toggle" + "x-method": "_goose/unstable/config/extensions/set-enabled" }, "GetSessionExtensionsRequest_unstable": { "type": "object", @@ -2738,11 +3150,20 @@ { "allOf": [ { - "$ref": "#/$defs/GetExtensionsRequest_unstable" + "$ref": "#/$defs/GetConfigExtensionsRequest_unstable" } ], "description": "Params for _goose/unstable/config/extensions/list", - "title": "GetExtensionsRequest_unstable" + "title": "GetConfigExtensionsRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GetAvailableExtensionsRequest_unstable" + } + ], + "description": "Params for _goose/unstable/extensions/available", + "title": "GetAvailableExtensionsRequest_unstable" }, { "allOf": [ @@ -2765,11 +3186,11 @@ { "allOf": [ { - "$ref": "#/$defs/ToggleConfigExtensionRequest_unstable" + "$ref": "#/$defs/SetConfigExtensionEnabledRequest_unstable" } ], - "description": "Params for _goose/unstable/config/extensions/toggle", - "title": "ToggleConfigExtensionRequest_unstable" + "description": "Params for _goose/unstable/config/extensions/set-enabled", + "title": "SetConfigExtensionEnabledRequest_unstable" }, { "allOf": [ @@ -3241,10 +3662,18 @@ { "allOf": [ { - "$ref": "#/$defs/GetExtensionsResponse_unstable" + "$ref": "#/$defs/GetConfigExtensionsResponse_unstable" + } + ], + "title": "GetConfigExtensionsResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GetAvailableExtensionsResponse_unstable" } ], - "title": "GetExtensionsResponse_unstable" + "title": "GetAvailableExtensionsResponse_unstable" }, { "allOf": [ diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index c48c23d948d1..c70f0782b8e0 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -2,7 +2,7 @@ use super::*; use crate::agents::extension::Envs; use crate::config::extensions::ExtensionEntry; use agent_client_protocol::schema::{ - EnvVariable, HttpHeader, McpServer, McpServerHttp, McpServerSse, McpServerStdio, + HttpHeader, McpServer, McpServerHttp, McpServerStdio, }; impl GooseAcpAgent { diff --git a/ui/sdk/src/generated/client.gen.ts b/ui/sdk/src/generated/client.gen.ts index 22beacb47533..381471f870ad 100644 --- a/ui/sdk/src/generated/client.gen.ts +++ b/ui/sdk/src/generated/client.gen.ts @@ -44,8 +44,10 @@ import type { ExportSessionResponse_unstable, ExportSourceRequest_unstable, ExportSourceResponse_unstable, - GetExtensionsRequest_unstable, - GetExtensionsResponse_unstable, + GetAvailableExtensionsRequest_unstable, + GetAvailableExtensionsResponse_unstable, + GetConfigExtensionsRequest_unstable, + GetConfigExtensionsResponse_unstable, GetSessionExtensionsRequest_unstable, GetSessionExtensionsResponse_unstable, GetToolsRequest_unstable, @@ -91,8 +93,8 @@ import type { RemoveConfigExtensionRequest_unstable, RemoveExtensionRequest_unstable, RenameSessionRequest_unstable, + SetConfigExtensionEnabledRequest_unstable, SetSessionSystemPromptRequest_unstable, - ToggleConfigExtensionRequest_unstable, UnarchiveSessionRequest_unstable, UpdateSessionProjectRequest_unstable, UpdateSourceRequest_unstable, @@ -112,7 +114,8 @@ import { zDictationTranscribeResponse_unstable, zExportSessionResponse_unstable, zExportSourceResponse_unstable, - zGetExtensionsResponse_unstable, + zGetAvailableExtensionsResponse_unstable, + zGetConfigExtensionsResponse_unstable, zGetSessionExtensionsResponse_unstable, zGetToolsResponse_unstable, zGooseToolCallResponse_unstable, @@ -204,15 +207,27 @@ export class GooseExtClient { } async configExtensionsList_unstable( - params: GetExtensionsRequest_unstable, - ): Promise { + params: GetConfigExtensionsRequest_unstable, + ): Promise { const raw = await this.conn.extMethod( "_goose/unstable/config/extensions/list", params, ); - return zGetExtensionsResponse_unstable.parse( + return zGetConfigExtensionsResponse_unstable.parse( raw, - ) as GetExtensionsResponse_unstable; + ) as GetConfigExtensionsResponse_unstable; + } + + async extensionsAvailable_unstable( + params: GetAvailableExtensionsRequest_unstable, + ): Promise { + const raw = await this.conn.extMethod( + "_goose/unstable/extensions/available", + params, + ); + return zGetAvailableExtensionsResponse_unstable.parse( + raw, + ) as GetAvailableExtensionsResponse_unstable; } async configExtensionsAdd_unstable( @@ -230,11 +245,11 @@ export class GooseExtClient { ); } - async configExtensionsToggle_unstable( - params: ToggleConfigExtensionRequest_unstable, + async configExtensionsSetEnabled_unstable( + params: SetConfigExtensionEnabledRequest_unstable, ): Promise { await this.conn.extMethod( - "_goose/unstable/config/extensions/toggle", + "_goose/unstable/config/extensions/set-enabled", params, ); } diff --git a/ui/sdk/src/generated/index.ts b/ui/sdk/src/generated/index.ts index 85a63bc04964..d3b66cb39f2c 100644 --- a/ui/sdk/src/generated/index.ts +++ b/ui/sdk/src/generated/index.ts @@ -1,6 +1,6 @@ // This file is auto-generated by @hey-api/openapi-ts -export type { AddConfigExtensionRequest_unstable, AddExtensionRequest_unstable, ArchiveSessionRequest_unstable, CreateSourceRequest_unstable, CreateSourceResponse_unstable, CustomProviderConfigDto, CustomProviderCreateRequest_unstable, CustomProviderCreateResponse_unstable, CustomProviderDeleteRequest_unstable, CustomProviderDeleteResponse_unstable, CustomProviderReadRequest_unstable, CustomProviderReadResponse_unstable, CustomProviderUpdateRequest_unstable, CustomProviderUpdateResponse_unstable, DefaultsReadRequest_unstable, DefaultsReadResponse_unstable, DefaultsSaveRequest_unstable, DeleteSessionRequest, DeleteSourceRequest_unstable, DictationConfigRequest_unstable, DictationConfigResponse_unstable, DictationDownloadProgress, DictationLocalModelStatus, DictationModelCancelRequest_unstable, DictationModelDeleteRequest_unstable, DictationModelDownloadProgressRequest_unstable, DictationModelDownloadProgressResponse_unstable, DictationModelDownloadRequest_unstable, DictationModelOption, DictationModelSelectRequest_unstable, DictationModelsListRequest_unstable, DictationModelsListResponse_unstable, DictationProviderStatusEntry, DictationSecretDeleteRequest_unstable, DictationSecretSaveRequest_unstable, DictationTranscribeRequest_unstable, DictationTranscribeResponse_unstable, EmptyResponse, ExportSessionRequest_unstable, ExportSessionResponse_unstable, ExportSourceRequest_unstable, ExportSourceResponse_unstable, ExtRequest, ExtResponse, GetExtensionsRequest_unstable, GetExtensionsResponse_unstable, GetSessionExtensionsRequest_unstable, GetSessionExtensionsResponse_unstable, GetToolsRequest_unstable, GetToolsResponse_unstable, GooseToolCallRequest_unstable, GooseToolCallResponse_unstable, ImportSessionRequest_unstable, ImportSessionResponse_unstable, ImportSourcesRequest_unstable, ImportSourcesResponse_unstable, ListProvidersRequest_unstable, ListProvidersResponse_unstable, ListSourcesRequest_unstable, ListSourcesResponse_unstable, OnboardingImportApplyRequest_unstable, OnboardingImportApplyResponse_unstable, OnboardingImportCandidate, OnboardingImportCounts, OnboardingImportScanRequest_unstable, OnboardingImportScanResponse_unstable, OnboardingImportSourceKind, PreferenceKey, PreferencesReadRequest_unstable, PreferencesReadResponse_unstable, PreferencesRemoveRequest_unstable, PreferencesSaveRequest_unstable, PreferenceValue, ProviderCatalogListRequest_unstable, ProviderCatalogListResponse_unstable, ProviderCatalogTemplateRequest_unstable, ProviderCatalogTemplateResponse_unstable, ProviderConfigAuthenticateRequest_unstable, ProviderConfigChangeResponse_unstable, ProviderConfigDeleteRequest_unstable, ProviderConfigFieldUpdate, ProviderConfigFieldValueDto, ProviderConfigKey, ProviderConfigReadRequest_unstable, ProviderConfigReadResponse_unstable, ProviderConfigSaveRequest_unstable, ProviderConfigStatusDto, ProviderConfigStatusRequest_unstable, ProviderConfigStatusResponse_unstable, ProviderInventoryEntryDto, ProviderInventoryModelDto, ProviderSetupCatalogEntryDto, ProviderSetupCatalogListRequest_unstable, ProviderSetupCatalogListResponse_unstable, ProviderSetupCategoryDto, ProviderSetupFieldDto, ProviderSetupGroupDto, ProviderSetupMethodDto, ProviderSupportedModelsListRequest_unstable, ProviderSupportedModelsListResponse_unstable, ProviderTemplateCapabilitiesDto, ProviderTemplateCatalogEntryDto, ProviderTemplateDto, ProviderTemplateModelDto, ReadResourceRequest_unstable, ReadResourceResponse_unstable, RefreshProviderInventoryRequest_unstable, RefreshProviderInventoryResponse_unstable, RefreshProviderInventorySkipDto, RefreshProviderInventorySkipReasonDto, RemoveConfigExtensionRequest_unstable, RemoveExtensionRequest_unstable, RenameSessionRequest_unstable, SessionSystemPromptMode, SetSessionSystemPromptRequest_unstable, SourceEntry, SourceScope, SourceType, ToggleConfigExtensionRequest_unstable, UnarchiveSessionRequest_unstable, UpdateSessionProjectRequest_unstable, UpdateSourceRequest_unstable, UpdateSourceResponse_unstable, UpdateWorkingDirRequest_unstable } from './types.gen.js'; +export type { AddConfigExtensionRequest_unstable, AddExtensionRequest_unstable, ArchiveSessionRequest_unstable, CreateSourceRequest_unstable, CreateSourceResponse_unstable, CustomProviderConfigDto, CustomProviderCreateRequest_unstable, CustomProviderCreateResponse_unstable, CustomProviderDeleteRequest_unstable, CustomProviderDeleteResponse_unstable, CustomProviderReadRequest_unstable, CustomProviderReadResponse_unstable, CustomProviderUpdateRequest_unstable, CustomProviderUpdateResponse_unstable, DefaultsReadRequest_unstable, DefaultsReadResponse_unstable, DefaultsSaveRequest_unstable, DeleteSessionRequest, DeleteSourceRequest_unstable, DictationConfigRequest_unstable, DictationConfigResponse_unstable, DictationDownloadProgress, DictationLocalModelStatus, DictationModelCancelRequest_unstable, DictationModelDeleteRequest_unstable, DictationModelDownloadProgressRequest_unstable, DictationModelDownloadProgressResponse_unstable, DictationModelDownloadRequest_unstable, DictationModelOption, DictationModelSelectRequest_unstable, DictationModelsListRequest_unstable, DictationModelsListResponse_unstable, DictationProviderStatusEntry, DictationSecretDeleteRequest_unstable, DictationSecretSaveRequest_unstable, DictationTranscribeRequest_unstable, DictationTranscribeResponse_unstable, EmptyResponse, EnvVariable, ExportSessionRequest_unstable, ExportSessionResponse_unstable, ExportSourceRequest_unstable, ExportSourceResponse_unstable, ExtRequest, ExtResponse, GetAvailableExtensionsRequest_unstable, GetAvailableExtensionsResponse_unstable, GetConfigExtensionsRequest_unstable, GetConfigExtensionsResponse_unstable, GetSessionExtensionsRequest_unstable, GetSessionExtensionsResponse_unstable, GetToolsRequest_unstable, GetToolsResponse_unstable, GooseExtension, GooseExtensionEntry, GooseToolCallRequest_unstable, GooseToolCallResponse_unstable, HttpHeader, ImportSessionRequest_unstable, ImportSessionResponse_unstable, ImportSourcesRequest_unstable, ImportSourcesResponse_unstable, ListProvidersRequest_unstable, ListProvidersResponse_unstable, ListSourcesRequest_unstable, ListSourcesResponse_unstable, McpServer, McpServerHttp, McpServerSse, McpServerStdio, OnboardingImportApplyRequest_unstable, OnboardingImportApplyResponse_unstable, OnboardingImportCandidate, OnboardingImportCounts, OnboardingImportScanRequest_unstable, OnboardingImportScanResponse_unstable, OnboardingImportSourceKind, PreferenceKey, PreferencesReadRequest_unstable, PreferencesReadResponse_unstable, PreferencesRemoveRequest_unstable, PreferencesSaveRequest_unstable, PreferenceValue, ProviderCatalogListRequest_unstable, ProviderCatalogListResponse_unstable, ProviderCatalogTemplateRequest_unstable, ProviderCatalogTemplateResponse_unstable, ProviderConfigAuthenticateRequest_unstable, ProviderConfigChangeResponse_unstable, ProviderConfigDeleteRequest_unstable, ProviderConfigFieldUpdate, ProviderConfigFieldValueDto, ProviderConfigKey, ProviderConfigReadRequest_unstable, ProviderConfigReadResponse_unstable, ProviderConfigSaveRequest_unstable, ProviderConfigStatusDto, ProviderConfigStatusRequest_unstable, ProviderConfigStatusResponse_unstable, ProviderInventoryEntryDto, ProviderInventoryModelDto, ProviderSetupCatalogEntryDto, ProviderSetupCatalogListRequest_unstable, ProviderSetupCatalogListResponse_unstable, ProviderSetupCategoryDto, ProviderSetupFieldDto, ProviderSetupGroupDto, ProviderSetupMethodDto, ProviderSupportedModelsListRequest_unstable, ProviderSupportedModelsListResponse_unstable, ProviderTemplateCapabilitiesDto, ProviderTemplateCatalogEntryDto, ProviderTemplateDto, ProviderTemplateModelDto, ReadResourceRequest_unstable, ReadResourceResponse_unstable, RefreshProviderInventoryRequest_unstable, RefreshProviderInventoryResponse_unstable, RefreshProviderInventorySkipDto, RefreshProviderInventorySkipReasonDto, RemoveConfigExtensionRequest_unstable, RemoveExtensionRequest_unstable, RenameSessionRequest_unstable, SessionSystemPromptMode, SetConfigExtensionEnabledRequest_unstable, SetSessionSystemPromptRequest_unstable, SourceEntry, SourceScope, SourceType, UnarchiveSessionRequest_unstable, UpdateSessionProjectRequest_unstable, UpdateSourceRequest_unstable, UpdateSourceResponse_unstable, UpdateWorkingDirRequest_unstable } from './types.gen.js'; export const GOOSE_EXT_METHODS = [ { @@ -45,8 +45,13 @@ export const GOOSE_EXT_METHODS = [ }, { method: "_goose/unstable/config/extensions/list", - requestType: "GetExtensionsRequest_unstable", - responseType: "GetExtensionsResponse_unstable", + requestType: "GetConfigExtensionsRequest_unstable", + responseType: "GetConfigExtensionsResponse_unstable", + }, + { + method: "_goose/unstable/extensions/available", + requestType: "GetAvailableExtensionsRequest_unstable", + responseType: "GetAvailableExtensionsResponse_unstable", }, { method: "_goose/unstable/config/extensions/add", @@ -59,8 +64,8 @@ export const GOOSE_EXT_METHODS = [ responseType: "EmptyResponse", }, { - method: "_goose/unstable/config/extensions/toggle", - requestType: "ToggleConfigExtensionRequest_unstable", + method: "_goose/unstable/config/extensions/set-enabled", + requestType: "SetConfigExtensionEnabledRequest_unstable", responseType: "EmptyResponse", }, { diff --git a/ui/sdk/src/generated/types.gen.ts b/ui/sdk/src/generated/types.gen.ts index 410f74ada5be..14a5306088d6 100644 --- a/ui/sdk/src/generated/types.gen.ts +++ b/ui/sdk/src/generated/types.gen.ts @@ -119,32 +119,218 @@ export type DeleteSessionRequest = { /** * List configured extensions and any warnings. */ -export type GetExtensionsRequest_unstable = { +export type GetConfigExtensionsRequest_unstable = { [key: string]: unknown; }; /** * List configured extensions and any warnings. */ -export type GetExtensionsResponse_unstable = { +export type GetConfigExtensionsResponse_unstable = { + extensions: Array; + warnings?: Array; +}; + +export type GooseExtensionEntry = { + extension: GooseExtension; + enabled: boolean; + configKey?: string | null; +}; + +export type GooseExtension = { + name: string; + description?: string | null; + display_name?: string | null; + type: 'builtin'; +} | { + name: string; + description?: string | null; + display_name?: string | null; + type: 'platform'; +} | { + server: McpServer; + envKeys?: Array; + description?: string | null; + timeout?: number | null; + socket?: string | null; + type: 'mcp'; +} | { + name: string; + description?: string | null; + code: string; + timeout?: number | null; + dependencies?: Array; + type: 'inline_python'; +} | { + name: string; + description?: string | null; + tools?: Array; + instructions?: string | null; + type: 'frontend'; +}; + +/** + * Configuration for connecting to an MCP (Model Context Protocol) server. + * + * MCP servers provide tools and context that the agent can use when + * processing prompts. + * + * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) + */ +export type McpServer = McpServerHttp | McpServerSse | McpServerStdio; + +/** + * An HTTP header to set when making requests to the MCP server. + */ +export type HttpHeader = { /** - * Array of ExtensionEntry objects with `enabled` flag, `configKey`, and flattened config details. + * The name of the HTTP header. */ - extensions: Array; - warnings: Array; + name: string; + /** + * The value to set for the HTTP header. + */ + value: string; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; }; /** - * Persist a new extension to the user's global goose config. + * HTTP transport configuration for MCP. */ -export type AddConfigExtensionRequest_unstable = { +export type McpServerHttp = { + /** + * Human-readable name identifying this MCP server. + */ + name: string; + /** + * URL to the MCP server. + */ + url: string; + /** + * HTTP headers to set when making requests to the MCP server. + */ + headers: Array; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * SSE transport configuration for MCP. + */ +export type McpServerSse = { + /** + * Human-readable name identifying this MCP server. + */ + name: string; + /** + * URL to the MCP server. + */ + url: string; + /** + * HTTP headers to set when making requests to the MCP server. + */ + headers: Array; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * Stdio transport configuration for MCP. + */ +export type McpServerStdio = { + /** + * Human-readable name identifying this MCP server. + */ name: string; /** - * Extension configuration. Must be a JSON object matching one of the - * `ExtensionConfig` variants (e.g. `stdio`, `streamable_http`, `builtin`). - * `name` and `enabled` are injected server-side. + * Path to the MCP server executable. + */ + command: string; + /** + * Command-line arguments to pass to the MCP server. + */ + args: Array; + /** + * Environment variables to set when launching the MCP server. */ - extensionConfig?: unknown; + env: Array; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * An environment variable to set when launching an MCP server. + */ +export type EnvVariable = { + /** + * The name of the environment variable. + */ + name: string; + /** + * The value to set for the environment variable. + */ + value: string; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * List Goose-owned extension definitions available to configure or enable. + */ +export type GetAvailableExtensionsRequest_unstable = { + [key: string]: unknown; +}; + +export type GetAvailableExtensionsResponse_unstable = { + extensions: Array; +}; + +/** + * Persist a new extension to the user's global goose config. + */ +export type AddConfigExtensionRequest_unstable = { + extension: GooseExtension; enabled?: boolean; }; @@ -156,9 +342,9 @@ export type RemoveConfigExtensionRequest_unstable = { }; /** - * Toggle the `enabled` flag for a persisted extension in the user's global goose config. + * Set the `enabled` flag for a persisted extension in the user's global goose config. */ -export type ToggleConfigExtensionRequest_unstable = { +export type SetConfigExtensionEnabledRequest_unstable = { configKey: string; enabled: boolean; }; @@ -1090,14 +1276,14 @@ export type DictationModelSelectRequest_unstable = { export type ExtRequest = { id: string; method: string; - params?: AddExtensionRequest_unstable | RemoveExtensionRequest_unstable | GetToolsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | DeleteSessionRequest | GetExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | ToggleConfigExtensionRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | { + params?: AddExtensionRequest_unstable | RemoveExtensionRequest_unstable | GetToolsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | DeleteSessionRequest | GetConfigExtensionsRequest_unstable | GetAvailableExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | SetConfigExtensionEnabledRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | { [key: string]: unknown; } | null; }; export type ExtResponse = { id: string; - result?: EmptyResponse | GetToolsResponse_unstable | GooseToolCallResponse_unstable | ReadResourceResponse_unstable | GetExtensionsResponse_unstable | GetSessionExtensionsResponse_unstable | ListProvidersResponse_unstable | ProviderSupportedModelsListResponse_unstable | ProviderCatalogListResponse_unstable | ProviderSetupCatalogListResponse_unstable | ProviderCatalogTemplateResponse_unstable | CustomProviderCreateResponse_unstable | CustomProviderReadResponse_unstable | CustomProviderUpdateResponse_unstable | CustomProviderDeleteResponse_unstable | RefreshProviderInventoryResponse_unstable | ProviderConfigReadResponse_unstable | ProviderConfigStatusResponse_unstable | ProviderConfigChangeResponse_unstable | PreferencesReadResponse_unstable | DefaultsReadResponse_unstable | OnboardingImportScanResponse_unstable | OnboardingImportApplyResponse_unstable | ExportSessionResponse_unstable | ImportSessionResponse_unstable | CreateSourceResponse_unstable | ListSourcesResponse_unstable | UpdateSourceResponse_unstable | ExportSourceResponse_unstable | ImportSourcesResponse_unstable | DictationTranscribeResponse_unstable | DictationConfigResponse_unstable | DictationModelsListResponse_unstable | DictationModelDownloadProgressResponse_unstable | unknown; + result?: EmptyResponse | GetToolsResponse_unstable | GooseToolCallResponse_unstable | ReadResourceResponse_unstable | GetConfigExtensionsResponse_unstable | GetAvailableExtensionsResponse_unstable | GetSessionExtensionsResponse_unstable | ListProvidersResponse_unstable | ProviderSupportedModelsListResponse_unstable | ProviderCatalogListResponse_unstable | ProviderSetupCatalogListResponse_unstable | ProviderCatalogTemplateResponse_unstable | CustomProviderCreateResponse_unstable | CustomProviderReadResponse_unstable | CustomProviderUpdateResponse_unstable | CustomProviderDeleteResponse_unstable | RefreshProviderInventoryResponse_unstable | ProviderConfigReadResponse_unstable | ProviderConfigStatusResponse_unstable | ProviderConfigChangeResponse_unstable | PreferencesReadResponse_unstable | DefaultsReadResponse_unstable | OnboardingImportScanResponse_unstable | OnboardingImportApplyResponse_unstable | ExportSessionResponse_unstable | ImportSessionResponse_unstable | CreateSourceResponse_unstable | ListSourcesResponse_unstable | UpdateSourceResponse_unstable | ExportSourceResponse_unstable | ImportSourcesResponse_unstable | DictationTranscribeResponse_unstable | DictationConfigResponse_unstable | DictationModelsListResponse_unstable | DictationModelDownloadProgressResponse_unstable | unknown; } | { error: { code: number; diff --git a/ui/sdk/src/generated/zod.gen.ts b/ui/sdk/src/generated/zod.gen.ts index efebe29bc0d9..e40086dbb012 100644 --- a/ui/sdk/src/generated/zod.gen.ts +++ b/ui/sdk/src/generated/zod.gen.ts @@ -115,22 +115,188 @@ export const zDeleteSessionRequest = z.object({ /** * List configured extensions and any warnings. */ -export const zGetExtensionsRequest_unstable = z.record(z.unknown()); +export const zGetConfigExtensionsRequest_unstable = z.record(z.unknown()); + +/** + * An HTTP header to set when making requests to the MCP server. + */ +export const zHttpHeader = z.object({ + name: z.string(), + value: z.string(), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional() +}); + +/** + * HTTP transport configuration for MCP. + */ +export const zMcpServerHttp = z.object({ + name: z.string(), + url: z.string(), + headers: z.array(zHttpHeader), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional() +}); + +/** + * SSE transport configuration for MCP. + */ +export const zMcpServerSse = z.object({ + name: z.string(), + url: z.string(), + headers: z.array(zHttpHeader), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional() +}); + +/** + * An environment variable to set when launching an MCP server. + */ +export const zEnvVariable = z.object({ + name: z.string(), + value: z.string(), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional() +}); + +/** + * Stdio transport configuration for MCP. + */ +export const zMcpServerStdio = z.object({ + name: z.string(), + command: z.string(), + args: z.array(z.string()), + env: z.array(zEnvVariable), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional() +}); + +/** + * Configuration for connecting to an MCP (Model Context Protocol) server. + * + * MCP servers provide tools and context that the agent can use when + * processing prompts. + * + * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) + */ +export const zMcpServer = z.union([ + zMcpServerHttp, + zMcpServerSse, + zMcpServerStdio +]); + +export const zGooseExtension = z.union([ + z.object({ + name: z.string(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + display_name: z.union([ + z.string(), + z.null() + ]).optional(), + type: z.literal('builtin') + }), + z.object({ + name: z.string(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + display_name: z.union([ + z.string(), + z.null() + ]).optional(), + type: z.literal('platform') + }), + z.object({ + server: zMcpServer, + envKeys: z.array(z.string()).optional(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + timeout: z.union([ + z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), + z.null() + ]).optional(), + socket: z.union([ + z.string(), + z.null() + ]).optional(), + type: z.literal('mcp') + }), + z.object({ + name: z.string(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + code: z.string(), + timeout: z.union([ + z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), + z.null() + ]).optional(), + dependencies: z.array(z.string()).optional(), + type: z.literal('inline_python') + }), + z.object({ + name: z.string(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + tools: z.array(z.unknown()).optional(), + instructions: z.union([ + z.string(), + z.null() + ]).optional(), + type: z.literal('frontend') + }) +]); + +export const zGooseExtensionEntry = z.object({ + extension: zGooseExtension, + enabled: z.boolean(), + configKey: z.union([ + z.string(), + z.null() + ]).optional() +}); /** * List configured extensions and any warnings. */ -export const zGetExtensionsResponse_unstable = z.object({ - extensions: z.array(z.unknown()), - warnings: z.array(z.string()) +export const zGetConfigExtensionsResponse_unstable = z.object({ + extensions: z.array(zGooseExtensionEntry), + warnings: z.array(z.string()).optional() +}); + +/** + * List Goose-owned extension definitions available to configure or enable. + */ +export const zGetAvailableExtensionsRequest_unstable = z.record(z.unknown()); + +export const zGetAvailableExtensionsResponse_unstable = z.object({ + extensions: z.array(zGooseExtension) }); /** * Persist a new extension to the user's global goose config. */ export const zAddConfigExtensionRequest_unstable = z.object({ - name: z.string(), - extensionConfig: z.unknown().optional().default(null), + extension: zGooseExtension, enabled: z.boolean().optional().default(false) }); @@ -142,9 +308,9 @@ export const zRemoveConfigExtensionRequest_unstable = z.object({ }); /** - * Toggle the `enabled` flag for a persisted extension in the user's global goose config. + * Set the `enabled` flag for a persisted extension in the user's global goose config. */ -export const zToggleConfigExtensionRequest_unstable = z.object({ +export const zSetConfigExtensionEnabledRequest_unstable = z.object({ configKey: z.string(), enabled: z.boolean() }); @@ -1101,10 +1267,11 @@ export const zExtRequest = z.object({ zUpdateWorkingDirRequest_unstable, zSetSessionSystemPromptRequest_unstable, zDeleteSessionRequest, - zGetExtensionsRequest_unstable, + zGetConfigExtensionsRequest_unstable, + zGetAvailableExtensionsRequest_unstable, zAddConfigExtensionRequest_unstable, zRemoveConfigExtensionRequest_unstable, - zToggleConfigExtensionRequest_unstable, + zSetConfigExtensionEnabledRequest_unstable, zGetSessionExtensionsRequest_unstable, zListProvidersRequest_unstable, zProviderSupportedModelsListRequest_unstable, @@ -1167,7 +1334,8 @@ export const zExtResponse = z.union([ zGetToolsResponse_unstable, zGooseToolCallResponse_unstable, zReadResourceResponse_unstable, - zGetExtensionsResponse_unstable, + zGetConfigExtensionsResponse_unstable, + zGetAvailableExtensionsResponse_unstable, zGetSessionExtensionsResponse_unstable, zListProvidersResponse_unstable, zProviderSupportedModelsListResponse_unstable, From 8df3c22e0b6f6d4aa7673aeb11d8cfcf827da68f Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 3 Jun 2026 21:20:06 +1000 Subject: [PATCH 07/16] cargo fmt --- crates/goose/src/acp/server/extensions.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index c70f0782b8e0..dc3a6dc9671f 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -1,9 +1,7 @@ use super::*; use crate::agents::extension::Envs; use crate::config::extensions::ExtensionEntry; -use agent_client_protocol::schema::{ - HttpHeader, McpServer, McpServerHttp, McpServerStdio, -}; +use agent_client_protocol::schema::{HttpHeader, McpServer, McpServerHttp, McpServerStdio}; impl GooseAcpAgent { pub(super) async fn on_add_extension( From 5debef938001fb1b992ec39769195a5c76ba3228 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 3 Jun 2026 21:42:25 +1000 Subject: [PATCH 08/16] include bundle in the response --- crates/goose-sdk/src/custom_requests.rs | 14 +- crates/goose/acp-schema.json | 35 ++++- crates/goose/src/acp/server/extensions.rs | 156 ++++++++++++++++------ crates/goose/src/config/extensions.rs | 4 - crates/goose/src/config/mod.rs | 5 +- ui/desktop/src/acp/extensions.ts | 78 ++++++++++- ui/sdk/src/generated/types.gen.ts | 5 + ui/sdk/src/generated/zod.gen.ts | 22 ++- 8 files changed, 264 insertions(+), 55 deletions(-) diff --git a/crates/goose-sdk/src/custom_requests.rs b/crates/goose-sdk/src/custom_requests.rs index c043e18d58f8..2c52b91f0698 100644 --- a/crates/goose-sdk/src/custom_requests.rs +++ b/crates/goose-sdk/src/custom_requests.rs @@ -157,6 +157,10 @@ pub enum GooseExtension { description: Option, #[serde(default, skip_serializing_if = "Option::is_none")] display_name: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + timeout: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + bundled: Option, }, Platform { name: String, @@ -164,6 +168,8 @@ pub enum GooseExtension { description: Option, #[serde(default, skip_serializing_if = "Option::is_none")] display_name: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + bundled: Option, }, Mcp { server: McpServer, @@ -175,6 +181,8 @@ pub enum GooseExtension { timeout: Option, #[serde(default, skip_serializing_if = "Option::is_none")] socket: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + bundled: Option, }, InlinePython { name: String, @@ -194,6 +202,8 @@ pub enum GooseExtension { tools: Vec, #[serde(default, skip_serializing_if = "Option::is_none")] instructions: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + bundled: Option, }, } @@ -203,6 +213,8 @@ impl Default for GooseExtension { name: String::new(), description: None, display_name: None, + timeout: None, + bundled: None, } } } @@ -242,7 +254,7 @@ pub struct GetConfigExtensionsRequest {} #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcResponse)] pub struct GetConfigExtensionsResponse { pub extensions: Vec, - #[serde(default, skip_serializing_if = "Vec::is_empty")] + #[serde(default)] pub warnings: Vec, } diff --git a/crates/goose/acp-schema.json b/crates/goose/acp-schema.json index de665330aafd..5f0fd53423da 100644 --- a/crates/goose/acp-schema.json +++ b/crates/goose/acp-schema.json @@ -243,7 +243,8 @@ "type": "array", "items": { "type": "string" - } + }, + "default": [] } }, "required": [ @@ -294,6 +295,20 @@ "null" ] }, + "timeout": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "bundled": { + "type": [ + "boolean", + "null" + ] + }, "type": { "type": "string", "const": "builtin" @@ -322,6 +337,12 @@ "null" ] }, + "bundled": { + "type": [ + "boolean", + "null" + ] + }, "type": { "type": "string", "const": "platform" @@ -364,6 +385,12 @@ "null" ] }, + "bundled": { + "type": [ + "boolean", + "null" + ] + }, "type": { "type": "string", "const": "mcp" @@ -436,6 +463,12 @@ "null" ] }, + "bundled": { + "type": [ + "boolean", + "null" + ] + }, "type": { "type": "string", "const": "frontend" diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index dc3a6dc9671f..a27ee9ab8b84 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -87,13 +87,6 @@ impl GooseAcpAgent { &self, req: RemoveConfigExtensionRequest, ) -> Result { - if let Some(entry) = crate::config::get_extension_entry_by_key(&req.config_key) { - if is_server_owned_extension_config(&entry.config) { - return Err(agent_client_protocol::Error::invalid_params() - .data(format!("Extension '{}' cannot be removed", req.config_key))); - } - } - crate::config::extensions::remove_extension(&req.config_key); Ok(EmptyResponse {}) } @@ -148,21 +141,27 @@ fn config_to_goose_extension( name, description, display_name, + timeout, + bundled, .. } => GooseExtension::Builtin { name: name.clone(), description: empty_string_to_none(description), display_name: display_name.clone(), + timeout: *timeout, + bundled: *bundled, }, ExtensionConfig::Platform { name, description, display_name, + bundled, .. } => GooseExtension::Platform { name: name.clone(), description: empty_string_to_none(description), display_name: display_name.clone(), + bundled: *bundled, }, ExtensionConfig::Stdio { name, @@ -171,6 +170,7 @@ fn config_to_goose_extension( args, env_keys, timeout, + bundled, .. } => GooseExtension::Mcp { server: McpServer::Stdio(McpServerStdio::new(name, cmd).args(args.clone())), @@ -178,6 +178,7 @@ fn config_to_goose_extension( description: empty_string_to_none(description), timeout: *timeout, socket: None, + bundled: *bundled, }, ExtensionConfig::StreamableHttp { name, @@ -187,6 +188,7 @@ fn config_to_goose_extension( headers, timeout, socket, + bundled, .. } => { let headers = headers @@ -199,6 +201,7 @@ fn config_to_goose_extension( description: empty_string_to_none(description), timeout: *timeout, socket: socket.clone(), + bundled: *bundled, } } ExtensionConfig::Frontend { @@ -206,6 +209,7 @@ fn config_to_goose_extension( description, tools, instructions, + bundled, .. } => { let tools = tools @@ -218,6 +222,7 @@ fn config_to_goose_extension( description: empty_string_to_none(description), tools, instructions: instructions.clone(), + bundled: *bundled, } } ExtensionConfig::InlinePython { @@ -243,16 +248,39 @@ fn goose_extension_to_config( extension: GooseExtension, ) -> Result { let config = match extension { - GooseExtension::Builtin { .. } | GooseExtension::Platform { .. } => { - return Err(agent_client_protocol::Error::invalid_params() - .data("builtin and platform extensions cannot be added to persistent config")); - } + GooseExtension::Builtin { + name, + description, + display_name, + timeout, + bundled, + } => ExtensionConfig::Builtin { + name, + description: description.unwrap_or_default(), + display_name, + timeout, + bundled, + available_tools: Vec::new(), + }, + GooseExtension::Platform { + name, + description, + display_name, + bundled, + } => ExtensionConfig::Platform { + name, + description: description.unwrap_or_default(), + display_name, + bundled, + available_tools: Vec::new(), + }, GooseExtension::Mcp { server, env_keys, description, timeout, socket, + bundled, } => match server { McpServer::Stdio(stdio) => { if socket.is_some() { @@ -267,7 +295,7 @@ fn goose_extension_to_config( envs: Envs::default(), env_keys, timeout, - bundled: Some(false), + bundled, available_tools: Vec::new(), } } @@ -284,7 +312,7 @@ fn goose_extension_to_config( .collect(), timeout, socket, - bundled: Some(false), + bundled, available_tools: Vec::new(), }, McpServer::Sse(_) => { @@ -316,6 +344,7 @@ fn goose_extension_to_config( description, tools, instructions, + bundled, } => ExtensionConfig::Frontend { name, description: description.unwrap_or_default(), @@ -328,7 +357,7 @@ fn goose_extension_to_config( .data(format!("bad frontend tool: {error}")) })?, instructions, - bundled: Some(false), + bundled, available_tools: Vec::new(), }, }; @@ -349,25 +378,6 @@ fn config_entry_to_goose_entry( })) } -fn is_server_owned_extension_config(config: &ExtensionConfig) -> bool { - matches!( - config, - ExtensionConfig::Builtin { .. } | ExtensionConfig::Platform { .. } - ) || matches!( - config, - ExtensionConfig::Stdio { - bundled: Some(true), - .. - } | ExtensionConfig::StreamableHttp { - bundled: Some(true), - .. - } | ExtensionConfig::Frontend { - bundled: Some(true), - .. - } - ) -} - fn empty_string_to_none(value: &str) -> Option { if value.is_empty() { None @@ -403,6 +413,8 @@ mod tests { name, description, display_name, + timeout, + bundled, } = extension else { panic!("expected builtin extension"); @@ -411,6 +423,8 @@ mod tests { assert_eq!(name, "developer"); assert_eq!(description.as_deref(), Some("Developer tools")); assert_eq!(display_name.as_deref(), Some("Developer")); + assert_eq!(timeout, Some(30)); + assert_eq!(bundled, Some(true)); } #[test] @@ -431,6 +445,7 @@ mod tests { name, description, display_name, + bundled, } = extension else { panic!("expected platform extension"); @@ -439,6 +454,7 @@ mod tests { assert_eq!(name, "todo"); assert_eq!(description.as_deref(), Some("Todo tools")); assert_eq!(display_name.as_deref(), Some("Todo")); + assert_eq!(bundled, Some(true)); } #[test] @@ -468,6 +484,7 @@ mod tests { description, timeout, socket, + bundled, } = extension else { panic!("expected mcp extension"); @@ -477,6 +494,7 @@ mod tests { assert_eq!(description.as_deref(), Some("Test stdio")); assert_eq!(timeout, Some(42)); assert_eq!(socket, None); + assert_eq!(bundled, None); let McpServer::Stdio(stdio) = server else { panic!("expected stdio server"); @@ -519,6 +537,7 @@ mod tests { description, timeout, socket, + bundled, } = extension else { panic!("expected mcp extension"); @@ -528,6 +547,7 @@ mod tests { assert_eq!(description.as_deref(), Some("Test HTTP")); assert_eq!(timeout, Some(99)); assert_eq!(socket.as_deref(), Some("@egress.sock")); + assert_eq!(bundled, None); let McpServer::Http(http) = server else { panic!("expected http server"); @@ -606,6 +626,7 @@ mod tests { description, tools, instructions, + bundled, } = extension else { panic!("expected frontend extension"); @@ -620,6 +641,7 @@ mod tests { assert_eq!(tools.len(), 1); assert_eq!(tools[0]["name"], "pick_color"); assert_eq!(tools[0]["description"], "Pick a color"); + assert_eq!(bundled, None); } #[test] @@ -650,6 +672,7 @@ mod tests { description: Some("Test stdio".to_string()), timeout: Some(42), socket: None, + bundled: Some(true), }; let config = goose_extension_to_config(extension).expect("conversion should succeed"); @@ -679,7 +702,7 @@ mod tests { ); assert_eq!(env_keys, vec!["SECRET_TOKEN"]); assert_eq!(timeout, Some(42)); - assert_eq!(bundled, Some(false)); + assert_eq!(bundled, Some(true)); assert!(available_tools.is_empty()); } @@ -695,6 +718,7 @@ mod tests { description: Some("Test HTTP".to_string()), timeout: Some(99), socket: Some("@egress.sock".to_string()), + bundled: Some(true), }; let config = goose_extension_to_config(extension).expect("conversion should succeed"); @@ -732,7 +756,7 @@ mod tests { ); assert_eq!(timeout, Some(99)); assert_eq!(socket.as_deref(), Some("@egress.sock")); - assert_eq!(bundled, Some(false)); + assert_eq!(bundled, Some(true)); assert!(available_tools.is_empty()); } @@ -785,6 +809,7 @@ mod tests { description: Some("Frontend tools".to_string()), tools: vec![tool], instructions: Some("Use frontend tools carefully".to_string()), + bundled: Some(true), }; let config = goose_extension_to_config(extension).expect("conversion should succeed"); @@ -810,25 +835,69 @@ mod tests { instructions.as_deref(), Some("Use frontend tools carefully") ); - assert_eq!(bundled, Some(false)); + assert_eq!(bundled, Some(true)); assert!(available_tools.is_empty()); } #[test] - fn goose_builtin_and_platform_extensions_are_rejected_for_config_add() { + fn goose_builtin_extension_converts_to_config() { let builtin = GooseExtension::Builtin { name: "developer".to_string(), - description: None, - display_name: None, + description: Some("Developer tools".to_string()), + display_name: Some("Developer".to_string()), + timeout: Some(30), + bundled: Some(true), + }; + + let config = goose_extension_to_config(builtin).expect("conversion should succeed"); + + let ExtensionConfig::Builtin { + name, + description, + display_name, + timeout, + bundled, + available_tools, + } = config + else { + panic!("expected builtin config"); }; + + assert_eq!(name, "developer"); + assert_eq!(description, "Developer tools"); + assert_eq!(display_name.as_deref(), Some("Developer")); + assert_eq!(timeout, Some(30)); + assert_eq!(bundled, Some(true)); + assert!(available_tools.is_empty()); + } + + #[test] + fn goose_platform_extension_converts_to_config() { let platform = GooseExtension::Platform { name: "todo".to_string(), - description: None, - display_name: None, + description: Some("Todo tools".to_string()), + display_name: Some("Todo".to_string()), + bundled: Some(true), + }; + + let config = goose_extension_to_config(platform).expect("conversion should succeed"); + + let ExtensionConfig::Platform { + name, + description, + display_name, + bundled, + available_tools, + } = config + else { + panic!("expected platform config"); }; - assert!(goose_extension_to_config(builtin).is_err()); - assert!(goose_extension_to_config(platform).is_err()); + assert_eq!(name, "todo"); + assert_eq!(description, "Todo tools"); + assert_eq!(display_name.as_deref(), Some("Todo")); + assert_eq!(bundled, Some(true)); + assert!(available_tools.is_empty()); } #[test] @@ -839,6 +908,7 @@ mod tests { description: None, timeout: None, socket: None, + bundled: None, }; assert!(goose_extension_to_config(extension).is_err()); diff --git a/crates/goose/src/config/extensions.rs b/crates/goose/src/config/extensions.rs index f45092b67a28..237ee8b68ad3 100644 --- a/crates/goose/src/config/extensions.rs +++ b/crates/goose/src/config/extensions.rs @@ -93,10 +93,6 @@ pub fn get_extension_by_name(name: &str) -> Option { .map(|entry| entry.config.clone()) } -pub fn get_extension_entry_by_key(key: &str) -> Option { - get_extensions_map().get(key).cloned() -} - pub fn set_extension(entry: ExtensionEntry) { let mut extensions = get_extensions_map(); let key = entry.config.key(); diff --git a/crates/goose/src/config/mod.rs b/crates/goose/src/config/mod.rs index e5aa019c2a2a..ae6c46265fc2 100644 --- a/crates/goose/src/config/mod.rs +++ b/crates/goose/src/config/mod.rs @@ -18,9 +18,8 @@ pub use declarative_providers::DeclarativeProviderConfig; pub use experiments::ExperimentManager; pub use extensions::{ get_all_extension_names, get_all_extensions, get_available_extensions, get_enabled_extensions, - get_extension_by_name, get_extension_entry_by_key, get_warnings, is_extension_enabled, - remove_extension, resolve_extensions_for_new_session, set_extension, set_extension_enabled, - ExtensionEntry, + get_extension_by_name, get_warnings, is_extension_enabled, remove_extension, + resolve_extensions_for_new_session, set_extension, set_extension_enabled, ExtensionEntry, }; pub use goose_mode::GooseMode; pub use permission::PermissionManager; diff --git a/ui/desktop/src/acp/extensions.ts b/ui/desktop/src/acp/extensions.ts index 4edcff17c52c..bf9961242fb5 100644 --- a/ui/desktop/src/acp/extensions.ts +++ b/ui/desktop/src/acp/extensions.ts @@ -1,11 +1,85 @@ import type { ExtensionResponse, ExtensionEntry } from '../api'; +import type { GooseExtensionEntry, McpServer } from '@aaif/goose-sdk'; import { getAcpClient } from './acpConnection'; +function headersToRecord(headers: { name: string; value: string }[] = []) { + return Object.fromEntries(headers.map(({ name, value }) => [name, value])); +} + +function mcpServerToExtension( + server: McpServer, + entry: GooseExtensionEntry +): ExtensionEntry | null { + const extension = entry.extension; + if (extension.type !== 'mcp') { + return null; + } + + if ('command' in server) { + return { + type: 'stdio', + enabled: entry.enabled, + name: server.name, + description: extension.description ?? '', + cmd: server.command, + args: server.args, + env_keys: extension.envKeys ?? [], + timeout: extension.timeout, + bundled: extension.bundled, + }; + } + + if ('url' in server) { + return { + type: 'streamable_http', + enabled: entry.enabled, + name: server.name, + description: extension.description ?? '', + uri: server.url, + headers: headersToRecord(server.headers), + env_keys: extension.envKeys ?? [], + timeout: extension.timeout, + socket: extension.socket, + bundled: extension.bundled, + }; + } + + return null; +} + +function gooseExtensionEntryToExtensionEntry(entry: GooseExtensionEntry): ExtensionEntry | null { + const extension = entry.extension; + + switch (extension.type) { + case 'builtin': + case 'platform': + case 'inline_python': + return { + ...extension, + description: extension.description ?? '', + enabled: entry.enabled, + }; + case 'mcp': + return mcpServerToExtension(extension.server, entry); + case 'frontend': + return { + ...extension, + description: extension.description ?? '', + tools: extension.tools ?? [], + enabled: entry.enabled, + } as ExtensionEntry; + } + + return null; +} + export async function getConfiguredExtensions(): Promise { const client = await getAcpClient(); const response = await client.goose.configExtensionsList_unstable({}); return { - extensions: response.extensions as ExtensionEntry[], - warnings: response.warnings, + extensions: response.extensions + .map(gooseExtensionEntryToExtensionEntry) + .filter((entry): entry is ExtensionEntry => entry !== null), + warnings: response.warnings ?? [], }; } diff --git a/ui/sdk/src/generated/types.gen.ts b/ui/sdk/src/generated/types.gen.ts index 14a5306088d6..dda422f17524 100644 --- a/ui/sdk/src/generated/types.gen.ts +++ b/ui/sdk/src/generated/types.gen.ts @@ -141,11 +141,14 @@ export type GooseExtension = { name: string; description?: string | null; display_name?: string | null; + timeout?: number | null; + bundled?: boolean | null; type: 'builtin'; } | { name: string; description?: string | null; display_name?: string | null; + bundled?: boolean | null; type: 'platform'; } | { server: McpServer; @@ -153,6 +156,7 @@ export type GooseExtension = { description?: string | null; timeout?: number | null; socket?: string | null; + bundled?: boolean | null; type: 'mcp'; } | { name: string; @@ -166,6 +170,7 @@ export type GooseExtension = { description?: string | null; tools?: Array; instructions?: string | null; + bundled?: boolean | null; type: 'frontend'; }; diff --git a/ui/sdk/src/generated/zod.gen.ts b/ui/sdk/src/generated/zod.gen.ts index e40086dbb012..aad31ca1f8e5 100644 --- a/ui/sdk/src/generated/zod.gen.ts +++ b/ui/sdk/src/generated/zod.gen.ts @@ -206,6 +206,14 @@ export const zGooseExtension = z.union([ z.string(), z.null() ]).optional(), + timeout: z.union([ + z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), + z.null() + ]).optional(), + bundled: z.union([ + z.boolean(), + z.null() + ]).optional(), type: z.literal('builtin') }), z.object({ @@ -218,6 +226,10 @@ export const zGooseExtension = z.union([ z.string(), z.null() ]).optional(), + bundled: z.union([ + z.boolean(), + z.null() + ]).optional(), type: z.literal('platform') }), z.object({ @@ -235,6 +247,10 @@ export const zGooseExtension = z.union([ z.string(), z.null() ]).optional(), + bundled: z.union([ + z.boolean(), + z.null() + ]).optional(), type: z.literal('mcp') }), z.object({ @@ -262,6 +278,10 @@ export const zGooseExtension = z.union([ z.string(), z.null() ]).optional(), + bundled: z.union([ + z.boolean(), + z.null() + ]).optional(), type: z.literal('frontend') }) ]); @@ -280,7 +300,7 @@ export const zGooseExtensionEntry = z.object({ */ export const zGetConfigExtensionsResponse_unstable = z.object({ extensions: z.array(zGooseExtensionEntry), - warnings: z.array(z.string()).optional() + warnings: z.array(z.string()).optional().default([]) }); /** From a0563fe0583119085fe0048c442c6913bda36738 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 3 Jun 2026 22:06:58 +1000 Subject: [PATCH 09/16] return error if client passes envs when adding extensions --- crates/goose/src/acp/server/extensions.rs | 27 ++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index a27ee9ab8b84..e193f5065a01 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -287,6 +287,11 @@ fn goose_extension_to_config( return Err(agent_client_protocol::Error::invalid_params() .data("socket is only supported for streamable_http MCP extensions")); } + if !stdio.env.is_empty() { + return Err(agent_client_protocol::Error::invalid_params().data( + "literal env values are unsupported for config extensions; use envKeys", + )); + } ExtensionConfig::Stdio { name: stdio.name, description: description.unwrap_or_default(), @@ -662,11 +667,7 @@ mod tests { let extension = GooseExtension::Mcp { server: McpServer::Stdio( McpServerStdio::new("test-stdio", "test-command") - .args(vec!["--flag".to_string(), "value".to_string()]) - .env(vec![agent_client_protocol::schema::EnvVariable::new( - "SECRET_TOKEN", - "literal-secret", - )]), + .args(vec!["--flag".to_string(), "value".to_string()]), ), env_keys: vec!["SECRET_TOKEN".to_string()], description: Some("Test stdio".to_string()), @@ -706,6 +707,22 @@ mod tests { assert!(available_tools.is_empty()); } + #[test] + fn goose_mcp_stdio_extension_rejects_literal_envs_for_config_add() { + let extension = GooseExtension::Mcp { + server: McpServer::Stdio(McpServerStdio::new("test-stdio", "test-command").env(vec![ + agent_client_protocol::schema::EnvVariable::new("SECRET_TOKEN", "literal-secret"), + ])), + env_keys: vec!["SECRET_TOKEN".to_string()], + description: Some("Test stdio".to_string()), + timeout: Some(42), + socket: None, + bundled: Some(true), + }; + + assert!(goose_extension_to_config(extension).is_err()); + } + #[test] fn goose_mcp_streamable_http_extension_converts_to_config_without_literal_envs() { let extension = GooseExtension::Mcp { From d9c0bfaacf9eab752198fdc77ce142a49ae5273d Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 3 Jun 2026 22:43:32 +1000 Subject: [PATCH 10/16] fixed the schema generation --- crates/goose/acp-schema.json | 5554 ++++++++++--------- crates/goose/src/bin/generate_acp_schema.rs | 99 + ui/sdk/src/generated/types.gen.ts | 1802 +++--- ui/sdk/src/generated/zod.gen.ts | 1860 +++---- 4 files changed, 4714 insertions(+), 4601 deletions(-) diff --git a/crates/goose/acp-schema.json b/crates/goose/acp-schema.json index 5f0fd53423da..f98cf2724909 100644 --- a/crates/goose/acp-schema.json +++ b/crates/goose/acp-schema.json @@ -1,51 +1,30 @@ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "GooseExtensions", "$defs": { - "AddExtensionRequest_unstable": { - "type": "object", + "AddConfigExtensionRequest_unstable": { + "description": "Persist a new extension to the user's global goose config.", "properties": { - "sessionId": { - "type": "string" + "enabled": { + "default": false, + "type": "boolean" }, - "config": { - "description": "Extension configuration (see ExtensionConfig variants: Stdio, StreamableHttp, Builtin, Platform).", - "default": null + "extension": { + "$ref": "#/$defs/GooseExtension" } }, "required": [ - "sessionId" + "extension" ], - "description": "Add an extension to an active session.", - "x-side": "agent", - "x-method": "_goose/unstable/session/extensions/add" - }, - "EmptyResponse": { "type": "object", - "description": "Empty success response for operations that return no data.", + "x-method": "_goose/unstable/config/extensions/add", "x-side": "agent" }, - "RemoveExtensionRequest_unstable": { - "type": "object", + "AddExtensionRequest_unstable": { + "description": "Add an extension to an active session.", "properties": { - "sessionId": { - "type": "string" + "config": { + "default": null, + "description": "Extension configuration (see ExtensionConfig variants: Stdio, StreamableHttp, Builtin, Platform)." }, - "name": { - "type": "string" - } - }, - "required": [ - "sessionId", - "name" - ], - "description": "Remove an extension from an active session.", - "x-side": "agent", - "x-method": "_goose/unstable/session/extensions/remove" - }, - "GetToolsRequest_unstable": { - "type": "object", - "properties": { "sessionId": { "type": "string" } @@ -53,3055 +32,928 @@ "required": [ "sessionId" ], - "description": "List all tools available in a session.", - "x-side": "agent", - "x-method": "_goose/unstable/tools/list" - }, - "GetToolsResponse_unstable": { "type": "object", - "properties": { - "tools": { - "type": "array", - "items": {}, - "description": "Array of tool info objects with `name`, `description`, `parameters`, and optional `permission`." - } - }, - "required": [ - "tools" - ], - "description": "Tools response.", - "x-side": "agent", - "x-method": "_goose/unstable/tools/list" + "x-method": "_goose/unstable/session/extensions/add", + "x-side": "agent" }, - "GooseToolCallRequest_unstable": { - "type": "object", + "ArchiveSessionRequest_unstable": { + "description": "Archive a session (soft delete).", "properties": { "sessionId": { "type": "string" - }, - "name": { - "type": "string" - }, - "arguments": { - "default": null } }, "required": [ - "sessionId", - "name" + "sessionId" ], - "description": "Call a tool from an extension.", - "x-side": "agent", - "x-method": "_goose/unstable/tools/call" - }, - "GooseToolCallResponse_unstable": { "type": "object", - "properties": { - "content": { - "type": "array", - "items": {}, - "default": [] - }, - "structuredContent": {}, - "isError": { - "type": "boolean" - }, - "_meta": {} - }, - "required": [ - "isError" - ], - "description": "Tool call response.", - "x-side": "agent", - "x-method": "_goose/unstable/tools/call" + "x-method": "_goose/unstable/session/archive", + "x-side": "agent" }, - "ReadResourceRequest_unstable": { - "type": "object", + "CreateSourceRequest_unstable": { + "description": "Create a new source in an explicit target scope (global or project-scoped).", "properties": { - "sessionId": { + "content": { "type": "string" }, - "uri": { + "description": { "type": "string" }, - "extensionName": { + "name": { "type": "string" + }, + "properties": { + "additionalProperties": {}, + "description": "Arbitrary key/value metadata.", + "type": "object" + }, + "target": { + "$ref": "#/$defs/SourceScope" + }, + "type": { + "$ref": "#/$defs/SourceType" } }, "required": [ - "sessionId", - "uri", - "extensionName" + "type", + "name", + "description", + "content", + "target" ], - "description": "Read a resource from an extension.", - "x-side": "agent", - "x-method": "_goose/unstable/resources/read" - }, - "ReadResourceResponse_unstable": { "type": "object", - "properties": { - "result": { - "description": "The resource result from the extension (MCP ReadResourceResult).", - "default": null - } - }, - "description": "Resource read response.", - "x-side": "agent", - "x-method": "_goose/unstable/resources/read" + "x-method": "_goose/unstable/sources/create", + "x-side": "agent" }, - "UpdateWorkingDirRequest_unstable": { - "type": "object", + "CreateSourceResponse_unstable": { "properties": { - "sessionId": { - "type": "string" - }, - "workingDir": { - "type": "string" + "source": { + "$ref": "#/$defs/SourceEntry" } }, "required": [ - "sessionId", - "workingDir" + "source" ], - "description": "Update the working directory for a session.", - "x-side": "agent", - "x-method": "_goose/unstable/session/working-dir/update" - }, - "SetSessionSystemPromptRequest_unstable": { "type": "object", + "x-method": "_goose/unstable/sources/create", + "x-side": "agent" + }, + "CustomProviderConfigDto": { "properties": { - "sessionId": { + "apiKeyEnv": { + "type": [ + "string", + "null" + ] + }, + "apiKeySet": { + "type": "boolean" + }, + "apiUrl": { "type": "string" }, - "mode": { - "$ref": "#/$defs/SessionSystemPromptMode", - "default": "append" + "basePath": { + "type": [ + "string", + "null" + ] }, - "key": { + "catalogProviderId": { "type": [ "string", "null" ] }, - "text": { + "displayName": { "type": "string" - } - }, - "required": [ - "sessionId", - "text" - ], - "description": "Set, append, or clear system prompt text for a session.\n\n`mode: \"set\"` replaces Goose's base system prompt. `mode: \"append\"` adds an\ninstruction under \"Additional Instructions\". Reusing a key replaces the\nprevious value for that mode/key; sending empty text clears it.", - "x-side": "agent", - "x-method": "_goose/unstable/session/system-prompt/set" - }, - "SessionSystemPromptMode": { - "oneOf": [ - { - "type": "string", - "const": "set", - "description": "Replace Goose's base system prompt with the provided text." }, - { - "type": "string", - "const": "append", - "description": "Append the provided text under Goose's \"Additional Instructions\" section." - } - ], - "description": "How a session system prompt update should be applied." - }, - "DeleteSessionRequest": { - "type": "object", - "properties": { - "sessionId": { + "engine": { "type": "string" - } - }, - "required": [ - "sessionId" - ], - "description": "Delete a session.", - "x-side": "agent", - "x-method": "session/delete" - }, - "GetConfigExtensionsRequest_unstable": { - "type": "object", - "description": "List configured extensions and any warnings.", - "x-side": "agent", - "x-method": "_goose/unstable/config/extensions/list" - }, - "GetConfigExtensionsResponse_unstable": { - "type": "object", - "properties": { - "extensions": { - "type": "array", - "items": { - "$ref": "#/$defs/GooseExtensionEntry" - } }, - "warnings": { - "type": "array", + "headers": { + "additionalProperties": { + "type": "string" + }, + "default": {}, + "type": "object" + }, + "models": { + "default": [], "items": { "type": "string" }, - "default": [] + "type": "array" + }, + "preservesThinking": { + "type": "boolean" + }, + "providerId": { + "type": "string" + }, + "requiresAuth": { + "type": "boolean" + }, + "supportsStreaming": { + "type": [ + "boolean", + "null" + ] } }, "required": [ - "extensions" + "providerId", + "engine", + "displayName", + "apiUrl", + "requiresAuth", + "apiKeySet", + "preservesThinking" ], - "description": "List configured extensions and any warnings.", - "x-side": "agent", - "x-method": "_goose/unstable/config/extensions/list" + "type": "object" }, - "GooseExtensionEntry": { - "type": "object", + "CustomProviderCreateRequest_unstable": { + "description": "Create a custom provider backed by Goose's declarative provider store.", "properties": { - "extension": { - "$ref": "#/$defs/GooseExtension" + "apiKey": { + "type": [ + "string", + "null" + ] }, - "enabled": { - "type": "boolean" + "apiUrl": { + "type": "string" }, - "configKey": { + "basePath": { "type": [ "string", "null" ] - } - }, - "required": [ - "extension", - "enabled" - ] - }, - "GooseExtension": { - "oneOf": [ - { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "display_name": { - "type": [ - "string", - "null" - ] - }, - "timeout": { - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0 - }, - "bundled": { - "type": [ - "boolean", - "null" - ] - }, - "type": { - "type": "string", - "const": "builtin" - } - }, - "required": [ - "type", - "name" - ] }, - { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "display_name": { - "type": [ - "string", - "null" - ] - }, - "bundled": { - "type": [ - "boolean", - "null" - ] - }, - "type": { - "type": "string", - "const": "platform" - } - }, - "required": [ - "type", - "name" + "catalogProviderId": { + "type": [ + "string", + "null" ] }, - { - "type": "object", - "properties": { - "server": { - "$ref": "#/$defs/McpServer" - }, - "envKeys": { - "type": "array", - "items": { - "type": "string" - } - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "timeout": { - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0 - }, - "socket": { - "type": [ - "string", - "null" - ] - }, - "bundled": { - "type": [ - "boolean", - "null" - ] - }, - "type": { - "type": "string", - "const": "mcp" - } - }, - "required": [ - "type", - "server" - ] + "displayName": { + "type": "string" }, - { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "code": { - "type": "string" - }, - "timeout": { - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0 - }, - "dependencies": { - "type": "array", - "items": { - "type": "string" - } - }, - "type": { - "type": "string", - "const": "inline_python" - } - }, - "required": [ - "type", - "name", - "code" - ] + "engine": { + "type": "string" }, - { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "tools": { - "type": "array", - "items": {} - }, - "instructions": { - "type": [ - "string", - "null" - ] - }, - "bundled": { - "type": [ - "boolean", - "null" - ] - }, - "type": { - "type": "string", - "const": "frontend" - } - }, - "required": [ - "type", - "name" - ] - } - ] - }, - "McpServer": { - "anyOf": [ - { - "$ref": "#/$defs/McpServerHttp", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "http" - } + "headers": { + "additionalProperties": { + "type": "string" }, - "required": [ - "type" - ], - "description": "HTTP transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.http` is `true`." + "default": {}, + "type": "object" }, - { - "$ref": "#/$defs/McpServerSse", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "sse" - } + "models": { + "default": [], + "items": { + "type": "string" }, - "required": [ - "type" - ], - "description": "SSE transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`." + "type": "array" }, - { - "$ref": "#/$defs/McpServerStdio", - "description": "Stdio transport configuration\n\nAll Agents MUST support this transport." - } - ], - "description": "Configuration for connecting to an MCP (Model Context Protocol) server.\n\nMCP servers provide tools and context that the agent can use when\nprocessing prompts.\n\nSee protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)" - }, - "HttpHeader": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "The name of the HTTP header." + "preservesThinking": { + "type": [ + "boolean", + "null" + ] }, - "value": { - "type": "string", - "description": "The value to set for the HTTP header." + "requiresAuth": { + "type": "boolean" }, - "_meta": { + "supportsStreaming": { "type": [ - "object", + "boolean", "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + ] } }, "required": [ - "name", - "value" + "engine", + "displayName", + "apiUrl", + "requiresAuth" ], - "description": "An HTTP header to set when making requests to the MCP server." - }, - "McpServerHttp": { "type": "object", + "x-method": "_goose/unstable/providers/custom/create", + "x-side": "agent" + }, + "CustomProviderCreateResponse_unstable": { "properties": { - "name": { - "type": "string", - "description": "Human-readable name identifying this MCP server." + "providerId": { + "type": "string" }, - "url": { - "type": "string", - "description": "URL to the MCP server." + "refresh": { + "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" }, - "headers": { - "type": "array", - "items": { - "$ref": "#/$defs/HttpHeader" - }, - "description": "HTTP headers to set when making requests to the MCP server." - }, - "_meta": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + "status": { + "$ref": "#/$defs/ProviderConfigStatusDto" } }, "required": [ - "name", - "url", - "headers" + "providerId", + "status", + "refresh" ], - "description": "HTTP transport configuration for MCP." + "type": "object", + "x-method": "_goose/unstable/providers/custom/create", + "x-side": "agent" }, - "McpServerSse": { + "CustomProviderDeleteRequest_unstable": { + "description": "Delete a custom provider from Goose's declarative provider store.", + "properties": { + "providerId": { + "type": "string" + } + }, + "required": [ + "providerId" + ], "type": "object", + "x-method": "_goose/unstable/providers/custom/delete", + "x-side": "agent" + }, + "CustomProviderDeleteResponse_unstable": { "properties": { - "name": { - "type": "string", - "description": "Human-readable name identifying this MCP server." + "providerId": { + "type": "string" }, - "url": { - "type": "string", - "description": "URL to the MCP server." + "refresh": { + "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" + } + }, + "required": [ + "providerId", + "refresh" + ], + "type": "object", + "x-method": "_goose/unstable/providers/custom/delete", + "x-side": "agent" + }, + "CustomProviderReadRequest_unstable": { + "description": "Read a declarative provider config. Custom configs are editable; bundled configs are read-only.", + "properties": { + "providerId": { + "type": "string" + } + }, + "required": [ + "providerId" + ], + "type": "object", + "x-method": "_goose/unstable/providers/custom/read", + "x-side": "agent" + }, + "CustomProviderReadResponse_unstable": { + "properties": { + "editable": { + "type": "boolean" }, - "headers": { - "type": "array", - "items": { - "$ref": "#/$defs/HttpHeader" - }, - "description": "HTTP headers to set when making requests to the MCP server." + "provider": { + "$ref": "#/$defs/CustomProviderConfigDto" }, - "_meta": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + "status": { + "$ref": "#/$defs/ProviderConfigStatusDto" } }, "required": [ - "name", - "url", - "headers" + "provider", + "editable", + "status" ], - "description": "SSE transport configuration for MCP." - }, - "McpServerStdio": { "type": "object", + "x-method": "_goose/unstable/providers/custom/read", + "x-side": "agent" + }, + "CustomProviderUpdateRequest_unstable": { + "description": "Update a custom provider backed by Goose's declarative provider store.", "properties": { - "name": { - "type": "string", - "description": "Human-readable name identifying this MCP server." + "apiKey": { + "type": [ + "string", + "null" + ] }, - "command": { - "type": "string", - "description": "Path to the MCP server executable." + "apiUrl": { + "type": "string" }, - "args": { - "type": "array", - "items": { + "basePath": { + "type": [ + "string", + "null" + ] + }, + "catalogProviderId": { + "type": [ + "string", + "null" + ] + }, + "displayName": { + "type": "string" + }, + "engine": { + "type": "string" + }, + "headers": { + "additionalProperties": { "type": "string" }, - "description": "Command-line arguments to pass to the MCP server." + "default": {}, + "type": "object" }, - "env": { - "type": "array", + "models": { + "default": [], "items": { - "$ref": "#/$defs/EnvVariable" + "type": "string" }, - "description": "Environment variables to set when launching the MCP server." + "type": "array" }, - "_meta": { + "preservesThinking": { "type": [ - "object", + "boolean", "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" - } - }, - "required": [ - "name", - "command", - "args", - "env" - ], - "description": "Stdio transport configuration for MCP." - }, - "EnvVariable": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "The name of the environment variable." + ] }, - "value": { - "type": "string", - "description": "The value to set for the environment variable." + "providerId": { + "type": "string" }, - "_meta": { + "requiresAuth": { + "type": "boolean" + }, + "supportsStreaming": { "type": [ - "object", + "boolean", "null" - ], - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + ] } }, "required": [ - "name", - "value" + "providerId", + "engine", + "displayName", + "apiUrl", + "requiresAuth" ], - "description": "An environment variable to set when launching an MCP server." - }, - "GetAvailableExtensionsRequest_unstable": { "type": "object", - "description": "List Goose-owned extension definitions available to configure or enable.", - "x-side": "agent", - "x-method": "_goose/unstable/extensions/available" + "x-method": "_goose/unstable/providers/custom/update", + "x-side": "agent" }, - "GetAvailableExtensionsResponse_unstable": { - "type": "object", + "CustomProviderUpdateResponse_unstable": { "properties": { - "extensions": { - "type": "array", - "items": { - "$ref": "#/$defs/GooseExtension" - } + "providerId": { + "type": "string" + }, + "refresh": { + "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" + }, + "status": { + "$ref": "#/$defs/ProviderConfigStatusDto" } }, "required": [ - "extensions" + "providerId", + "status", + "refresh" ], - "x-side": "agent", - "x-method": "_goose/unstable/extensions/available" + "type": "object", + "x-method": "_goose/unstable/providers/custom/update", + "x-side": "agent" }, - "AddConfigExtensionRequest_unstable": { + "DefaultsReadRequest_unstable": { + "description": "Read Goose default provider and model configuration.", "type": "object", + "x-method": "_goose/unstable/defaults/read", + "x-side": "agent" + }, + "DefaultsReadResponse_unstable": { "properties": { - "extension": { - "$ref": "#/$defs/GooseExtension" + "modelId": { + "type": [ + "string", + "null" + ] }, - "enabled": { - "type": "boolean", - "default": false + "providerId": { + "type": [ + "string", + "null" + ] } }, - "required": [ - "extension" - ], - "description": "Persist a new extension to the user's global goose config.", - "x-side": "agent", - "x-method": "_goose/unstable/config/extensions/add" - }, - "RemoveConfigExtensionRequest_unstable": { "type": "object", + "x-side": "agent" + }, + "DefaultsSaveRequest_unstable": { + "description": "Save Goose default provider and model configuration.", "properties": { - "configKey": { + "modelId": { + "type": [ + "string", + "null" + ] + }, + "providerId": { "type": "string" } }, "required": [ - "configKey" + "providerId" ], - "description": "Remove a persisted extension from the user's global goose config.", - "x-side": "agent", - "x-method": "_goose/unstable/config/extensions/remove" - }, - "SetConfigExtensionEnabledRequest_unstable": { "type": "object", + "x-method": "_goose/unstable/defaults/save", + "x-side": "agent" + }, + "DeleteSessionRequest": { + "description": "Delete a session.", "properties": { - "configKey": { + "sessionId": { "type": "string" - }, - "enabled": { - "type": "boolean" } }, "required": [ - "configKey", - "enabled" + "sessionId" ], - "description": "Set the `enabled` flag for a persisted extension in the user's global goose config.", - "x-side": "agent", - "x-method": "_goose/unstable/config/extensions/set-enabled" - }, - "GetSessionExtensionsRequest_unstable": { "type": "object", + "x-method": "session/delete", + "x-side": "agent" + }, + "DeleteSourceRequest_unstable": { + "description": "Delete a source and its on-disk directory by absolute path.", "properties": { - "sessionId": { + "path": { "type": "string" + }, + "type": { + "$ref": "#/$defs/SourceType" } }, "required": [ - "sessionId" + "type", + "path" ], - "x-side": "agent", - "x-method": "_goose/unstable/session/extensions/list" - }, - "GetSessionExtensionsResponse_unstable": { "type": "object", - "properties": { - "extensions": { - "type": "array", - "items": {} - } - }, - "required": [ - "extensions" - ], - "x-side": "agent", - "x-method": "_goose/unstable/session/extensions/list" + "x-method": "_goose/unstable/sources/delete", + "x-side": "agent" }, - "ListProvidersRequest_unstable": { + "DictationConfigRequest_unstable": { + "description": "Get the configuration status of all dictation providers.", "type": "object", - "properties": { - "providerIds": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Only return entries for these providers. Empty means all.", - "default": [] - } - }, - "description": "List providers with setup metadata and the current model inventory snapshot.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/list" + "x-method": "_goose/unstable/dictation/config", + "x-side": "agent" }, - "ListProvidersResponse_unstable": { - "type": "object", + "DictationConfigResponse_unstable": { + "description": "Dictation config response — map of provider name to status.", "properties": { - "entries": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderInventoryEntryDto" - } + "providers": { + "additionalProperties": { + "$ref": "#/$defs/DictationProviderStatusEntry" + }, + "type": "object" } }, "required": [ - "entries" + "providers" ], - "description": "Provider list response.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/list" - }, - "ProviderInventoryEntryDto": { "type": "object", + "x-method": "_goose/unstable/dictation/config", + "x-side": "agent" + }, + "DictationDownloadProgress": { "properties": { - "providerId": { - "type": "string", - "description": "Provider identifier." - }, - "providerName": { - "type": "string", - "description": "Human-readable provider name." - }, - "description": { - "type": "string", - "description": "Description of the provider's capabilities." - }, - "defaultModel": { - "type": "string", - "description": "The default/recommended model for this provider." - }, - "configured": { - "type": "boolean", - "description": "Whether Goose has enough configuration to use this provider." - }, - "providerType": { - "type": "string", - "description": "Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`." - }, - "category": { - "$ref": "#/$defs/ProviderSetupCategoryDto", - "description": "Whether this inventory entry represents an agent provider or a model provider." - }, - "configKeys": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderConfigKey" - }, - "description": "Required configuration keys and setup metadata." - }, - "setupSteps": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Step-by-step setup instructions, when present." - }, - "supportsRefresh": { - "type": "boolean", - "description": "Whether this provider supports background inventory refresh." - }, - "refreshing": { - "type": "boolean", - "description": "Whether a refresh is currently in flight." - }, - "models": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderInventoryModelDto" - }, - "description": "The list of available models." - }, - "lastUpdatedAt": { - "type": [ - "string", - "null" - ], - "description": "When this entry was last successfully refreshed (ISO 8601)." + "bytesDownloaded": { + "minimum": 0, + "type": "integer" }, - "lastRefreshAttemptAt": { + "error": { "type": [ "string", "null" - ], - "description": "When a refresh was most recently attempted (ISO 8601)." + ] }, - "lastRefreshError": { - "type": [ - "string", - "null" - ], - "description": "The last refresh failure message, if any." + "progressPercent": { + "format": "float", + "type": "number" }, - "stale": { - "type": "boolean", - "description": "Whether we believe this data may be outdated." + "status": { + "description": "serde lowercase of DownloadStatus: \"downloading\" | \"completed\" | \"failed\" | \"cancelled\"", + "type": "string" }, - "modelSelectionHint": { - "type": [ - "string", - "null" - ], - "description": "Guidance message shown when this provider manages its own model selection externally." + "totalBytes": { + "minimum": 0, + "type": "integer" } }, "required": [ - "providerId", - "providerName", - "description", - "defaultModel", - "configured", - "providerType", - "category", - "configKeys", - "setupSteps", - "supportsRefresh", - "refreshing", - "models", - "stale" + "bytesDownloaded", + "totalBytes", + "progressPercent", + "status" ], - "description": "Provider inventory entry." - }, - "ProviderSetupCategoryDto": { - "type": "string", - "enum": [ - "agent", - "model" - ] + "type": "object" }, - "ProviderConfigKey": { - "type": "object", + "DictationLocalModelStatus": { "properties": { - "name": { + "description": { "type": "string" }, - "required": { + "downloadInProgress": { "type": "boolean" }, - "secret": { + "downloaded": { "type": "boolean" }, - "default": { - "type": [ - "string", - "null" - ], - "default": null - }, - "oauthFlow": { - "type": "boolean", - "default": false - }, - "deviceCodeFlow": { - "type": "boolean", - "default": false - }, - "primary": { - "type": "boolean", - "default": false - } - }, - "required": [ - "name", - "required", - "secret" - ] - }, - "ProviderInventoryModelDto": { - "type": "object", - "properties": { "id": { - "type": "string", - "description": "Model identifier as the provider knows it." - }, - "name": { - "type": "string", - "description": "Human-readable display name." + "type": "string" }, - "family": { - "type": [ - "string", - "null" - ], - "description": "Model family for grouping in UI." + "label": { + "type": "string" }, - "contextLimit": { - "type": [ - "integer", - "null" - ], - "format": "uint", + "sizeMb": { "minimum": 0, - "description": "Context window size in tokens." - }, - "reasoning": { - "type": [ - "boolean", - "null" - ], - "description": "Whether the model supports reasoning/extended thinking." - }, - "recommended": { - "type": "boolean", - "description": "Whether this model should appear in the compact recommended picker.", - "default": false + "type": "integer" } }, "required": [ "id", - "name" + "label", + "description", + "sizeMb", + "downloaded", + "downloadInProgress" ], - "description": "A single model in provider inventory." + "type": "object" }, - "ProviderSupportedModelsListRequest_unstable": { - "type": "object", + "DictationModelCancelRequest_unstable": { + "description": "Cancel an in-flight download.", "properties": { - "providerId": { + "modelId": { "type": "string" } }, "required": [ - "providerId" + "modelId" ], - "description": "List the raw model identifiers returned by a provider's live supported-models API.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/supported-models/list" - }, - "ProviderSupportedModelsListResponse_unstable": { "type": "object", + "x-method": "_goose/unstable/dictation/models/cancel", + "x-side": "agent" + }, + "DictationModelDeleteRequest_unstable": { + "description": "Delete a downloaded local Whisper model from disk.", "properties": { - "providerId": { + "modelId": { "type": "string" - }, - "models": { - "type": "array", - "items": { - "type": "string" - } } }, "required": [ - "providerId", - "models" + "modelId" ], - "x-side": "agent", - "x-method": "_goose/unstable/providers/supported-models/list" - }, - "ProviderCatalogListRequest_unstable": { "type": "object", - "properties": { - "format": { - "type": [ - "string", - "null" - ] - } - }, - "description": "List custom-provider catalog entries. Omit `format` to list all formats.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/catalog/list" + "x-method": "_goose/unstable/dictation/models/delete", + "x-side": "agent" }, - "ProviderCatalogListResponse_unstable": { - "type": "object", + "DictationModelDownloadProgressRequest_unstable": { + "description": "Poll the progress of an in-flight download.", "properties": { - "providers": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderTemplateCatalogEntryDto" - } + "modelId": { + "type": "string" } }, "required": [ - "providers" + "modelId" ], - "x-side": "agent", - "x-method": "_goose/unstable/providers/catalog/list" - }, - "ProviderTemplateCatalogEntryDto": { "type": "object", + "x-method": "_goose/unstable/dictation/models/download/progress", + "x-side": "agent" + }, + "DictationModelDownloadProgressResponse_unstable": { "properties": { - "providerId": { - "type": "string" - }, - "name": { - "type": "string" - }, - "format": { - "type": "string" - }, - "apiUrl": { + "progress": { + "anyOf": [ + { + "$ref": "#/$defs/DictationDownloadProgress" + }, + { + "type": "null" + } + ], + "description": "None when no download is active for this model id." + } + }, + "type": "object", + "x-method": "_goose/unstable/dictation/models/download/progress", + "x-side": "agent" + }, + "DictationModelDownloadRequest_unstable": { + "description": "Kick off a background download of a local Whisper model.", + "properties": { + "modelId": { + "type": "string" + } + }, + "required": [ + "modelId" + ], + "type": "object", + "x-method": "_goose/unstable/dictation/models/download", + "x-side": "agent" + }, + "DictationModelOption": { + "properties": { + "description": { "type": "string" }, - "modelCount": { - "type": "integer", - "minimum": 0 - }, - "docUrl": { + "id": { "type": "string" }, - "envVar": { + "label": { "type": "string" } }, "required": [ - "providerId", - "name", - "format", - "apiUrl", - "modelCount", - "docUrl", - "envVar" - ] + "id", + "label", + "description" + ], + "type": "object" }, - "ProviderSetupCatalogListRequest_unstable": { + "DictationModelSelectRequest_unstable": { + "description": "Persist the user's model selection for a given provider.", + "properties": { + "modelId": { + "type": "string" + }, + "provider": { + "type": "string" + } + }, + "required": [ + "provider", + "modelId" + ], "type": "object", - "description": "List provider setup catalog entries", - "x-side": "agent", - "x-method": "_goose/unstable/providers/setup/catalog/list" + "x-method": "_goose/unstable/dictation/models/select", + "x-side": "agent" }, - "ProviderSetupCatalogListResponse_unstable": { + "DictationModelsListRequest_unstable": { + "description": "List available local Whisper models with their download status.", "type": "object", + "x-method": "_goose/unstable/dictation/models/list", + "x-side": "agent" + }, + "DictationModelsListResponse_unstable": { "properties": { - "providers": { - "type": "array", + "models": { "items": { - "$ref": "#/$defs/ProviderSetupCatalogEntryDto" - } + "$ref": "#/$defs/DictationLocalModelStatus" + }, + "type": "array" } }, "required": [ - "providers" + "models" ], - "x-side": "agent", - "x-method": "_goose/unstable/providers/setup/catalog/list" - }, - "ProviderSetupCatalogEntryDto": { "type": "object", + "x-method": "_goose/unstable/dictation/models/list", + "x-side": "agent" + }, + "DictationProviderStatusEntry": { + "description": "Per-provider configuration status.", "properties": { - "providerId": { - "type": "string" - }, - "name": { - "type": "string" - }, - "category": { - "$ref": "#/$defs/ProviderSetupCategoryDto" + "availableModels": { + "default": [], + "items": { + "$ref": "#/$defs/DictationModelOption" + }, + "type": "array" }, - "description": { - "type": "string" + "configKey": { + "type": [ + "string", + "null" + ] }, - "setupMethod": { - "$ref": "#/$defs/ProviderSetupMethodDto" + "configured": { + "type": "boolean" }, - "nativeConnectQuery": { + "defaultModel": { "type": [ "string", "null" ] }, - "fields": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderSetupFieldDto" - }, - "default": [] + "description": { + "type": "string" }, - "binaryName": { + "host": { "type": [ "string", "null" ] }, - "docUrl": { + "modelConfigKey": { "type": [ "string", "null" ] }, - "group": { - "$ref": "#/$defs/ProviderSetupGroupDto" - }, - "showOnlyWhenInstalled": { - "type": "boolean" - }, - "aliases": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - }, - "supportsInstall": { - "type": "boolean" - }, - "supportsAuth": { - "type": "boolean" - }, - "supportsAuthStatus": { - "type": "boolean" - } - }, - "required": [ - "providerId", - "name", - "category", - "description", - "setupMethod", - "group", - "showOnlyWhenInstalled", - "supportsInstall", - "supportsAuth", - "supportsAuthStatus" - ] - }, - "ProviderSetupMethodDto": { - "type": "string", - "enum": [ - "none", - "single_api_key", - "config_fields", - "host_with_oauth_fallback", - "oauth_browser", - "oauth_device_code", - "cloud_credentials", - "local", - "cli_auth" - ] - }, - "ProviderSetupFieldDto": { - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "label": { - "type": "string" - }, - "secret": { - "type": "boolean" - }, - "required": { - "type": "boolean" - }, - "placeholder": { + "selectedModel": { "type": [ "string", "null" ] }, - "defaultValue": { + "settingsPath": { "type": [ "string", "null" ] + }, + "usesProviderConfig": { + "type": "boolean" } }, "required": [ - "key", - "label", - "secret", - "required" - ] - }, - "ProviderSetupGroupDto": { - "type": "string", - "enum": [ - "default", - "additional" - ] + "configured", + "description", + "usesProviderConfig" + ], + "type": "object" }, - "ProviderCatalogTemplateRequest_unstable": { - "type": "object", + "DictationSecretDeleteRequest_unstable": { + "description": "Remove a dictation provider secret value.", "properties": { - "providerId": { + "provider": { "type": "string" } }, "required": [ - "providerId" + "provider" ], - "description": "Return the editable template for one catalog provider.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/catalog/template" - }, - "ProviderCatalogTemplateResponse_unstable": { "type": "object", + "x-method": "_goose/unstable/dictation/secret/delete", + "x-side": "agent" + }, + "DictationSecretSaveRequest_unstable": { + "description": "Set a dictation provider secret value.", "properties": { - "template": { - "$ref": "#/$defs/ProviderTemplateDto" + "provider": { + "type": "string" + }, + "value": { + "type": "string" } }, "required": [ - "template" + "provider", + "value" ], - "x-side": "agent", - "x-method": "_goose/unstable/providers/catalog/template" - }, - "ProviderTemplateDto": { "type": "object", + "x-method": "_goose/unstable/dictation/secret/save", + "x-side": "agent" + }, + "DictationTranscribeRequest_unstable": { + "description": "Transcribe audio via a dictation provider.", "properties": { - "providerId": { - "type": "string" - }, - "name": { - "type": "string" - }, - "format": { + "audio": { + "description": "Base64-encoded audio data", "type": "string" }, - "apiUrl": { + "mimeType": { + "description": "MIME type (e.g. \"audio/wav\", \"audio/webm\")", "type": "string" }, - "models": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderTemplateModelDto" - } - }, - "supportsStreaming": { - "type": "boolean" - }, - "envVar": { - "type": "string" - }, - "docUrl": { + "provider": { + "description": "Provider to use: \"openai\", \"groq\", \"elevenlabs\", or \"local\"", "type": "string" } }, "required": [ - "providerId", - "name", - "format", - "apiUrl", - "models", - "supportsStreaming", - "envVar", - "docUrl" - ] - }, - "ProviderTemplateModelDto": { + "audio", + "mimeType", + "provider" + ], "type": "object", + "x-method": "_goose/unstable/dictation/transcribe", + "x-side": "agent" + }, + "DictationTranscribeResponse_unstable": { + "description": "Transcription result.", "properties": { - "id": { - "type": "string" - }, - "name": { + "text": { "type": "string" - }, - "contextLimit": { - "type": "integer", - "minimum": 0 - }, - "capabilities": { - "$ref": "#/$defs/ProviderTemplateCapabilitiesDto" - }, - "deprecated": { - "type": "boolean" } }, "required": [ - "id", - "name", - "contextLimit", - "capabilities", - "deprecated" - ] - }, - "ProviderTemplateCapabilitiesDto": { + "text" + ], "type": "object", - "properties": { - "toolCall": { - "type": "boolean" - }, - "reasoning": { - "type": "boolean" - }, - "attachment": { - "type": "boolean" - }, - "temperature": { - "type": "boolean" - } - }, - "required": [ - "toolCall", - "reasoning", - "attachment", - "temperature" - ] + "x-method": "_goose/unstable/dictation/transcribe", + "x-side": "agent" }, - "CustomProviderCreateRequest_unstable": { + "EmptyResponse": { + "description": "Empty success response for operations that return no data.", "type": "object", + "x-side": "agent" + }, + "EnvVariable": { + "description": "An environment variable to set when launching an MCP server.", "properties": { - "engine": { - "type": "string" - }, - "displayName": { - "type": "string" - }, - "apiUrl": { - "type": "string" - }, - "apiKey": { - "type": [ - "string", - "null" - ] - }, - "models": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - }, - "supportsStreaming": { - "type": [ - "boolean", - "null" - ] - }, - "headers": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "default": {} - }, - "requiresAuth": { - "type": "boolean" - }, - "catalogProviderId": { + "_meta": { + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": [ - "string", + "object", "null" ] }, - "basePath": { - "type": [ - "string", - "null" - ] + "name": { + "description": "The name of the environment variable.", + "type": "string" }, - "preservesThinking": { - "type": [ - "boolean", - "null" - ] + "value": { + "description": "The value to set for the environment variable.", + "type": "string" } }, "required": [ - "engine", - "displayName", - "apiUrl", - "requiresAuth" + "name", + "value" ], - "description": "Create a custom provider backed by Goose's declarative provider store.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/custom/create" + "type": "object" }, - "CustomProviderCreateResponse_unstable": { - "type": "object", + "ExportSessionRequest_unstable": { + "description": "Export a session as a JSON string.", "properties": { - "providerId": { + "sessionId": { "type": "string" - }, - "status": { - "$ref": "#/$defs/ProviderConfigStatusDto" - }, - "refresh": { - "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" } }, "required": [ - "providerId", - "status", - "refresh" + "sessionId" ], - "x-side": "agent", - "x-method": "_goose/unstable/providers/custom/create" - }, - "ProviderConfigStatusDto": { "type": "object", + "x-method": "_goose/unstable/session/export", + "x-side": "agent" + }, + "ExportSessionResponse_unstable": { + "description": "Export session response — raw JSON of the goose session with `conversation`.", "properties": { - "providerId": { + "data": { "type": "string" - }, - "isConfigured": { - "type": "boolean" } }, "required": [ - "providerId", - "isConfigured" - ] - }, - "RefreshProviderInventoryResponse_unstable": { + "data" + ], "type": "object", + "x-method": "_goose/unstable/session/export", + "x-side": "agent" + }, + "ExportSourceRequest_unstable": { + "description": "Export a source at an absolute path as a portable JSON payload.", "properties": { - "started": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Which providers will be refreshed." + "path": { + "type": "string" }, - "skipped": { - "type": "array", - "items": { - "$ref": "#/$defs/RefreshProviderInventorySkipDto" - }, - "description": "Which providers were skipped and why.", - "default": [] + "type": { + "$ref": "#/$defs/SourceType" } }, "required": [ - "started" + "type", + "path" ], - "description": "Refresh acknowledgement.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/inventory/refresh" - }, - "RefreshProviderInventorySkipDto": { "type": "object", + "x-method": "_goose/unstable/sources/export", + "x-side": "agent" + }, + "ExportSourceResponse_unstable": { "properties": { - "providerId": { + "filename": { "type": "string" }, - "reason": { - "$ref": "#/$defs/RefreshProviderInventorySkipReasonDto" - } - }, - "required": [ - "providerId", - "reason" - ] - }, - "RefreshProviderInventorySkipReasonDto": { - "type": "string", - "enum": [ - "unknown_provider", - "not_configured", - "does_not_support_refresh", - "already_refreshing" - ] - }, - "CustomProviderReadRequest_unstable": { - "type": "object", - "properties": { - "providerId": { + "json": { "type": "string" } }, "required": [ - "providerId" + "json", + "filename" ], - "description": "Read a declarative provider config. Custom configs are editable; bundled configs are read-only.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/custom/read" - }, - "CustomProviderReadResponse_unstable": { "type": "object", - "properties": { - "provider": { - "$ref": "#/$defs/CustomProviderConfigDto" - }, - "editable": { - "type": "boolean" - }, - "status": { - "$ref": "#/$defs/ProviderConfigStatusDto" - } - }, - "required": [ - "provider", - "editable", - "status" - ], - "x-side": "agent", - "x-method": "_goose/unstable/providers/custom/read" + "x-method": "_goose/unstable/sources/export", + "x-side": "agent" }, - "CustomProviderConfigDto": { - "type": "object", + "ExtRequest": { "properties": { - "providerId": { - "type": "string" - }, - "engine": { - "type": "string" - }, - "displayName": { + "id": { "type": "string" }, - "apiUrl": { - "type": "string" - }, - "models": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - }, - "supportsStreaming": { - "type": [ - "boolean", - "null" - ] - }, - "headers": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "default": {} - }, - "requiresAuth": { - "type": "boolean" - }, - "catalogProviderId": { - "type": [ - "string", - "null" - ] - }, - "basePath": { - "type": [ - "string", - "null" - ] - }, - "apiKeyEnv": { - "type": [ - "string", - "null" - ] - }, - "apiKeySet": { - "type": "boolean" - }, - "preservesThinking": { - "type": "boolean" - } - }, - "required": [ - "providerId", - "engine", - "displayName", - "apiUrl", - "requiresAuth", - "apiKeySet", - "preservesThinking" - ] - }, - "CustomProviderUpdateRequest_unstable": { - "type": "object", - "properties": { - "providerId": { - "type": "string" - }, - "engine": { - "type": "string" - }, - "displayName": { - "type": "string" - }, - "apiUrl": { - "type": "string" - }, - "apiKey": { - "type": [ - "string", - "null" - ] - }, - "models": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - }, - "supportsStreaming": { - "type": [ - "boolean", - "null" - ] - }, - "headers": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "default": {} - }, - "requiresAuth": { - "type": "boolean" - }, - "catalogProviderId": { - "type": [ - "string", - "null" - ] - }, - "basePath": { - "type": [ - "string", - "null" - ] - }, - "preservesThinking": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "providerId", - "engine", - "displayName", - "apiUrl", - "requiresAuth" - ], - "description": "Update a custom provider backed by Goose's declarative provider store.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/custom/update" - }, - "CustomProviderUpdateResponse_unstable": { - "type": "object", - "properties": { - "providerId": { - "type": "string" - }, - "status": { - "$ref": "#/$defs/ProviderConfigStatusDto" - }, - "refresh": { - "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" - } - }, - "required": [ - "providerId", - "status", - "refresh" - ], - "x-side": "agent", - "x-method": "_goose/unstable/providers/custom/update" - }, - "CustomProviderDeleteRequest_unstable": { - "type": "object", - "properties": { - "providerId": { - "type": "string" - } - }, - "required": [ - "providerId" - ], - "description": "Delete a custom provider from Goose's declarative provider store.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/custom/delete" - }, - "CustomProviderDeleteResponse_unstable": { - "type": "object", - "properties": { - "providerId": { - "type": "string" - }, - "refresh": { - "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" - } - }, - "required": [ - "providerId", - "refresh" - ], - "x-side": "agent", - "x-method": "_goose/unstable/providers/custom/delete" - }, - "RefreshProviderInventoryRequest_unstable": { - "type": "object", - "properties": { - "providerIds": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Which providers to refresh. Empty means all known providers.", - "default": [] - } - }, - "description": "Trigger a background refresh of provider inventories.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/inventory/refresh" - }, - "ProviderConfigReadRequest_unstable": { - "type": "object", - "properties": { - "providerId": { - "type": "string" - } - }, - "required": [ - "providerId" - ], - "description": "Read saved configuration field values for one provider.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/config/read" - }, - "ProviderConfigReadResponse_unstable": { - "type": "object", - "properties": { - "fields": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderConfigFieldValueDto" - } - } - }, - "required": [ - "fields" - ], - "x-side": "agent", - "x-method": "_goose/unstable/providers/config/read" - }, - "ProviderConfigFieldValueDto": { - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": [ - "string", - "null" - ], - "default": null - }, - "isSet": { - "type": "boolean" - }, - "isSecret": { - "type": "boolean" - }, - "required": { - "type": "boolean" - } - }, - "required": [ - "key", - "isSet", - "isSecret", - "required" - ] - }, - "ProviderConfigStatusRequest_unstable": { - "type": "object", - "properties": { - "providerIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - } - }, - "description": "Return provider configured statuses. Empty provider_ids means all providers.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/config/status" - }, - "ProviderConfigStatusResponse_unstable": { - "type": "object", - "properties": { - "statuses": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderConfigStatusDto" - } - } - }, - "required": [ - "statuses" - ], - "x-side": "agent", - "x-method": "_goose/unstable/providers/config/status" - }, - "ProviderConfigSaveRequest_unstable": { - "type": "object", - "properties": { - "providerId": { - "type": "string" - }, - "fields": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderConfigFieldUpdate" - } - } - }, - "required": [ - "providerId", - "fields" - ], - "description": "Save provider configuration fields and start an inventory refresh when supported.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/config/save" - }, - "ProviderConfigFieldUpdate": { - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "key", - "value" - ] - }, - "ProviderConfigChangeResponse_unstable": { - "type": "object", - "properties": { - "status": { - "$ref": "#/$defs/ProviderConfigStatusDto" - }, - "refresh": { - "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" - } - }, - "required": [ - "status", - "refresh" - ], - "x-side": "agent" - }, - "ProviderConfigDeleteRequest_unstable": { - "type": "object", - "properties": { - "providerId": { - "type": "string" - } - }, - "required": [ - "providerId" - ], - "description": "Delete provider configuration fields and start an inventory refresh when supported.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/config/delete" - }, - "ProviderConfigAuthenticateRequest_unstable": { - "type": "object", - "properties": { - "providerId": { - "type": "string" - } - }, - "required": [ - "providerId" - ], - "description": "Run a provider-owned native authentication flow and start an inventory refresh when supported.", - "x-side": "agent", - "x-method": "_goose/unstable/providers/config/authenticate" - }, - "PreferencesReadRequest_unstable": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/$defs/PreferenceKey" - }, - "default": [] - } - }, - "description": "Read allowlisted user preferences. Empty `keys` means all supported preferences.", - "x-side": "agent", - "x-method": "_goose/unstable/preferences/read" - }, - "PreferenceKey": { - "type": "string", - "enum": [ - "autoCompactThreshold", - "voiceAutoSubmitPhrases", - "voiceDictationProvider", - "voiceDictationPreferredMic" - ] - }, - "PreferencesReadResponse_unstable": { - "type": "object", - "properties": { - "values": { - "type": "array", - "items": { - "$ref": "#/$defs/PreferenceValue" - } - } - }, - "required": [ - "values" - ], - "x-side": "agent", - "x-method": "_goose/unstable/preferences/read" - }, - "PreferenceValue": { - "type": "object", - "properties": { - "key": { - "$ref": "#/$defs/PreferenceKey" - }, - "value": { - "default": null - } - }, - "required": [ - "key" - ] - }, - "PreferencesSaveRequest_unstable": { - "type": "object", - "properties": { - "values": { - "type": "array", - "items": { - "$ref": "#/$defs/PreferenceValue" - }, - "default": [] - } - }, - "description": "Save allowlisted user preferences.", - "x-side": "agent", - "x-method": "_goose/unstable/preferences/save" - }, - "PreferencesRemoveRequest_unstable": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/$defs/PreferenceKey" - }, - "default": [] - } - }, - "description": "Remove allowlisted user preferences.", - "x-side": "agent", - "x-method": "_goose/unstable/preferences/remove" - }, - "DefaultsReadRequest_unstable": { - "type": "object", - "description": "Read Goose default provider and model configuration.", - "x-side": "agent", - "x-method": "_goose/unstable/defaults/read" - }, - "DefaultsReadResponse_unstable": { - "type": "object", - "properties": { - "providerId": { - "type": [ - "string", - "null" - ] - }, - "modelId": { - "type": [ - "string", - "null" - ] - } - }, - "x-side": "agent" - }, - "DefaultsSaveRequest_unstable": { - "type": "object", - "properties": { - "providerId": { - "type": "string" - }, - "modelId": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "providerId" - ], - "description": "Save Goose default provider and model configuration.", - "x-side": "agent", - "x-method": "_goose/unstable/defaults/save" - }, - "OnboardingImportScanRequest_unstable": { - "type": "object", - "properties": { - "sources": { - "type": "array", - "items": { - "$ref": "#/$defs/OnboardingImportSourceKind" - }, - "description": "Empty means all supported import sources.", - "default": [] - } - }, - "description": "Scan for existing Goose and compatible app data that onboarding can import.", - "x-side": "agent", - "x-method": "_goose/unstable/onboarding/import/scan" - }, - "OnboardingImportSourceKind": { - "type": "string", - "enum": [ - "goose_config", - "claude_desktop" - ], - "description": "Sources that onboarding knows how to discover and import." - }, - "OnboardingImportScanResponse_unstable": { - "type": "object", - "properties": { - "candidates": { - "type": "array", - "items": { - "$ref": "#/$defs/OnboardingImportCandidate" - } - } - }, - "required": [ - "candidates" - ], - "x-side": "agent", - "x-method": "_goose/unstable/onboarding/import/scan" - }, - "OnboardingImportCandidate": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "sourceKind": { - "$ref": "#/$defs/OnboardingImportSourceKind" - }, - "displayName": { - "type": "string" - }, - "path": { - "type": "string" - }, - "counts": { - "$ref": "#/$defs/OnboardingImportCounts" - }, - "warnings": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - } - }, - "required": [ - "id", - "sourceKind", - "displayName", - "path", - "counts" - ] - }, - "OnboardingImportCounts": { - "type": "object", - "properties": { - "providers": { - "type": "integer", - "minimum": 0 - }, - "extensions": { - "type": "integer", - "minimum": 0 - }, - "sessions": { - "type": "integer", - "minimum": 0 - }, - "skills": { - "type": "integer", - "minimum": 0 - }, - "projects": { - "type": "integer", - "minimum": 0 - }, - "preferences": { - "type": "integer", - "minimum": 0 - } - }, - "required": [ - "providers", - "extensions", - "sessions", - "skills", - "projects", - "preferences" - ] - }, - "OnboardingImportApplyRequest_unstable": { - "type": "object", - "properties": { - "candidateIds": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - }, - "enableImportedExtensions": { - "type": "boolean", - "default": false - } - }, - "description": "Import selected onboarding candidates.", - "x-side": "agent", - "x-method": "_goose/unstable/onboarding/import/apply" - }, - "OnboardingImportApplyResponse_unstable": { - "type": "object", - "properties": { - "imported": { - "$ref": "#/$defs/OnboardingImportCounts" - }, - "skipped": { - "$ref": "#/$defs/OnboardingImportCounts" - }, - "warnings": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - }, - "providerDefaults": { - "anyOf": [ - { - "$ref": "#/$defs/DefaultsReadResponse_unstable" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "imported", - "skipped" - ], - "x-side": "agent", - "x-method": "_goose/unstable/onboarding/import/apply" - }, - "ExportSessionRequest_unstable": { - "type": "object", - "properties": { - "sessionId": { - "type": "string" - } - }, - "required": [ - "sessionId" - ], - "description": "Export a session as a JSON string.", - "x-side": "agent", - "x-method": "_goose/unstable/session/export" - }, - "ExportSessionResponse_unstable": { - "type": "object", - "properties": { - "data": { - "type": "string" - } - }, - "required": [ - "data" - ], - "description": "Export session response — raw JSON of the goose session with `conversation`.", - "x-side": "agent", - "x-method": "_goose/unstable/session/export" - }, - "ImportSessionRequest_unstable": { - "type": "object", - "properties": { - "data": { - "type": "string" - } - }, - "required": [ - "data" - ], - "description": "Import a session from a JSON string.", - "x-side": "agent", - "x-method": "_goose/unstable/session/import" - }, - "ImportSessionResponse_unstable": { - "type": "object", - "properties": { - "sessionId": { - "type": "string" - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "updatedAt": { - "type": [ - "string", - "null" - ] - }, - "messageCount": { - "type": "integer", - "minimum": 0 - } - }, - "required": [ - "sessionId", - "messageCount" - ], - "description": "Import session response — metadata about the newly created session.", - "x-side": "agent", - "x-method": "_goose/unstable/session/import" - }, - "UpdateSessionProjectRequest_unstable": { - "type": "object", - "properties": { - "sessionId": { - "type": "string" - }, - "projectId": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "sessionId" - ], - "description": "Update the project association for a session.", - "x-side": "agent", - "x-method": "_goose/unstable/session/project/update" - }, - "RenameSessionRequest_unstable": { - "type": "object", - "properties": { - "sessionId": { - "type": "string" - }, - "title": { - "type": "string" - } - }, - "required": [ - "sessionId", - "title" - ], - "description": "Rename a session.", - "x-side": "agent", - "x-method": "_goose/unstable/session/rename" - }, - "ArchiveSessionRequest_unstable": { - "type": "object", - "properties": { - "sessionId": { - "type": "string" - } - }, - "required": [ - "sessionId" - ], - "description": "Archive a session (soft delete).", - "x-side": "agent", - "x-method": "_goose/unstable/session/archive" - }, - "UnarchiveSessionRequest_unstable": { - "type": "object", - "properties": { - "sessionId": { - "type": "string" - } - }, - "required": [ - "sessionId" - ], - "description": "Unarchive a previously archived session.", - "x-side": "agent", - "x-method": "_goose/unstable/session/unarchive" - }, - "CreateSourceRequest_unstable": { - "type": "object", - "properties": { - "type": { - "$ref": "#/$defs/SourceType" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "content": { - "type": "string" - }, - "target": { - "$ref": "#/$defs/SourceScope" - }, - "properties": { - "type": "object", - "additionalProperties": {}, - "description": "Arbitrary key/value metadata." - } - }, - "required": [ - "type", - "name", - "description", - "content", - "target" - ], - "description": "Create a new source in an explicit target scope (global or project-scoped).", - "x-side": "agent", - "x-method": "_goose/unstable/sources/create" - }, - "SourceType": { - "type": "string", - "enum": [ - "skill", - "builtinSkill", - "recipe", - "subrecipe", - "agent", - "project" - ], - "description": "The type of source entity." - }, - "SourceScope": { - "oneOf": [ - { - "type": "object", - "properties": { - "scope": { - "type": "string", - "const": "global" - } - }, - "required": [ - "scope" - ] - }, - { - "type": "object", - "properties": { - "projectDir": { - "type": "string" - }, - "scope": { - "type": "string", - "const": "projectDir" - } - }, - "required": [ - "scope", - "projectDir" - ] - }, - { - "type": "object", - "properties": { - "projectId": { - "type": "string" - }, - "scope": { - "type": "string", - "const": "projectId" - } - }, - "required": [ - "scope", - "projectId" - ] - } - ], - "description": "Target scope for creating or importing sources." - }, - "CreateSourceResponse_unstable": { - "type": "object", - "properties": { - "source": { - "$ref": "#/$defs/SourceEntry" - } - }, - "required": [ - "source" - ], - "x-side": "agent", - "x-method": "_goose/unstable/sources/create" - }, - "SourceEntry": { - "type": "object", - "properties": { - "type": { - "$ref": "#/$defs/SourceType" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "content": { - "type": "string" - }, - "path": { - "type": "string", - "description": "Stable on-disk path identifying this source. Pass it back to\nupdate/delete/export to operate on this entry. Skills use the directory\ncontaining `SKILL.md`; projects use the project file path; built-in\nskills use `builtin://skills/` synthetic paths." - }, - "global": { - "type": "boolean", - "description": "True when the source lives in the user's global sources directory; false\nwhen it lives inside a specific project." - }, - "writable": { - "type": "boolean", - "description": "True when this source can be modified through source CRUD methods.\nClient-provided bundled sources are returned as read-only.", - "default": false - }, - "supportingFiles": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Paths (absolute) of additional files that live alongside the source.\nOnly skills currently populate this; empty for other source types." - }, - "properties": { - "type": "object", - "additionalProperties": {}, - "description": "Arbitrary key/value pairs for type-specific metadata (e.g. icon, color,\npreferredProvider for projects). Stored in the frontmatter." - } - }, - "required": [ - "type", - "name", - "description", - "content", - "path", - "global" - ], - "description": "A source discovered by Goose. Filesystem sources use an on-disk path;\nbuilt-in sources use a stable synthetic path. Sources may be either\n`global` (shared across all projects) or project-specific." - }, - "ListSourcesRequest_unstable": { - "type": "object", - "properties": { - "type": { - "anyOf": [ - { - "$ref": "#/$defs/SourceType" - }, - { - "type": "null" - } - ] - }, - "projectDir": { - "type": [ - "string", - "null" - ] - }, - "includeProjectSources": { - "type": "boolean", - "description": "When true, also scan the working directories of all known projects for\nproject-scoped sources (e.g. skills stored under `{workingDir}/.agents/skills/`).", - "default": false - } - }, - "description": "List discovered sources.\n\nIf `type` is omitted or `skill`, this lists filesystem/plugin skills only.\nBoth global and project-scoped skills are included when `project_dir` is\nset. If `type` is `builtinSkill`, this lists shipped read-only built-in\nskills.", - "x-side": "agent", - "x-method": "_goose/unstable/sources/list" - }, - "ListSourcesResponse_unstable": { - "type": "object", - "properties": { - "sources": { - "type": "array", - "items": { - "$ref": "#/$defs/SourceEntry" - } - } - }, - "required": [ - "sources" - ], - "x-side": "agent", - "x-method": "_goose/unstable/sources/list" - }, - "UpdateSourceRequest_unstable": { - "type": "object", - "properties": { - "type": { - "$ref": "#/$defs/SourceType" - }, - "path": { - "type": "string" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "content": { - "type": "string" - }, - "properties": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "When `Some`, replaces all stored properties on the source. When\n`None` (or omitted), the source's existing properties are\npreserved. Callers that don't model the full property bag (e.g.\nthe skills editor, which only edits name/description/content)\nshould omit this so per-skill metadata isn't silently erased." - } - }, - "required": [ - "type", - "path", - "name", - "description", - "content" - ], - "description": "Update an existing source's name, description, and content by absolute path.", - "x-side": "agent", - "x-method": "_goose/unstable/sources/update" - }, - "UpdateSourceResponse_unstable": { - "type": "object", - "properties": { - "source": { - "$ref": "#/$defs/SourceEntry" - } - }, - "required": [ - "source" - ], - "x-side": "agent", - "x-method": "_goose/unstable/sources/update" - }, - "DeleteSourceRequest_unstable": { - "type": "object", - "properties": { - "type": { - "$ref": "#/$defs/SourceType" - }, - "path": { - "type": "string" - } - }, - "required": [ - "type", - "path" - ], - "description": "Delete a source and its on-disk directory by absolute path.", - "x-side": "agent", - "x-method": "_goose/unstable/sources/delete" - }, - "ExportSourceRequest_unstable": { - "type": "object", - "properties": { - "type": { - "$ref": "#/$defs/SourceType" - }, - "path": { - "type": "string" - } - }, - "required": [ - "type", - "path" - ], - "description": "Export a source at an absolute path as a portable JSON payload.", - "x-side": "agent", - "x-method": "_goose/unstable/sources/export" - }, - "ExportSourceResponse_unstable": { - "type": "object", - "properties": { - "json": { - "type": "string" - }, - "filename": { - "type": "string" - } - }, - "required": [ - "json", - "filename" - ], - "x-side": "agent", - "x-method": "_goose/unstable/sources/export" - }, - "ImportSourcesRequest_unstable": { - "type": "object", - "properties": { - "data": { - "type": "string" - }, - "target": { - "$ref": "#/$defs/SourceScope" - } - }, - "required": [ - "data", - "target" - ], - "description": "Import a source from a JSON export payload produced by `_goose/unstable/sources/export`.\nThe imported source is written into the explicit target scope; on name\ncollisions a `-imported` suffix is appended.", - "x-side": "agent", - "x-method": "_goose/unstable/sources/import" - }, - "ImportSourcesResponse_unstable": { - "type": "object", - "properties": { - "sources": { - "type": "array", - "items": { - "$ref": "#/$defs/SourceEntry" - } - } - }, - "required": [ - "sources" - ], - "x-side": "agent", - "x-method": "_goose/unstable/sources/import" - }, - "DictationTranscribeRequest_unstable": { - "type": "object", - "properties": { - "audio": { - "type": "string", - "description": "Base64-encoded audio data" - }, - "mimeType": { - "type": "string", - "description": "MIME type (e.g. \"audio/wav\", \"audio/webm\")" - }, - "provider": { - "type": "string", - "description": "Provider to use: \"openai\", \"groq\", \"elevenlabs\", or \"local\"" - } - }, - "required": [ - "audio", - "mimeType", - "provider" - ], - "description": "Transcribe audio via a dictation provider.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/transcribe" - }, - "DictationTranscribeResponse_unstable": { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "description": "Transcription result.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/transcribe" - }, - "DictationConfigRequest_unstable": { - "type": "object", - "description": "Get the configuration status of all dictation providers.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/config" - }, - "DictationConfigResponse_unstable": { - "type": "object", - "properties": { - "providers": { - "type": "object", - "additionalProperties": { - "$ref": "#/$defs/DictationProviderStatusEntry" - } - } - }, - "required": [ - "providers" - ], - "description": "Dictation config response — map of provider name to status.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/config" - }, - "DictationProviderStatusEntry": { - "type": "object", - "properties": { - "configured": { - "type": "boolean" - }, - "host": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": "string" - }, - "usesProviderConfig": { - "type": "boolean" - }, - "settingsPath": { - "type": [ - "string", - "null" - ] - }, - "configKey": { - "type": [ - "string", - "null" - ] - }, - "modelConfigKey": { - "type": [ - "string", - "null" - ] - }, - "defaultModel": { - "type": [ - "string", - "null" - ] - }, - "selectedModel": { - "type": [ - "string", - "null" - ] - }, - "availableModels": { - "type": "array", - "items": { - "$ref": "#/$defs/DictationModelOption" - }, - "default": [] - } - }, - "required": [ - "configured", - "description", - "usesProviderConfig" - ], - "description": "Per-provider configuration status." - }, - "DictationModelOption": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "label": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": [ - "id", - "label", - "description" - ] - }, - "DictationSecretSaveRequest_unstable": { - "type": "object", - "properties": { - "provider": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "provider", - "value" - ], - "description": "Set a dictation provider secret value.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/secret/save" - }, - "DictationSecretDeleteRequest_unstable": { - "type": "object", - "properties": { - "provider": { - "type": "string" - } - }, - "required": [ - "provider" - ], - "description": "Remove a dictation provider secret value.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/secret/delete" - }, - "DictationModelsListRequest_unstable": { - "type": "object", - "description": "List available local Whisper models with their download status.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/models/list" - }, - "DictationModelsListResponse_unstable": { - "type": "object", - "properties": { - "models": { - "type": "array", - "items": { - "$ref": "#/$defs/DictationLocalModelStatus" - } - } - }, - "required": [ - "models" - ], - "x-side": "agent", - "x-method": "_goose/unstable/dictation/models/list" - }, - "DictationLocalModelStatus": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "label": { - "type": "string" - }, - "description": { - "type": "string" - }, - "sizeMb": { - "type": "integer", - "minimum": 0 - }, - "downloaded": { - "type": "boolean" - }, - "downloadInProgress": { - "type": "boolean" - } - }, - "required": [ - "id", - "label", - "description", - "sizeMb", - "downloaded", - "downloadInProgress" - ] - }, - "DictationModelDownloadRequest_unstable": { - "type": "object", - "properties": { - "modelId": { - "type": "string" - } - }, - "required": [ - "modelId" - ], - "description": "Kick off a background download of a local Whisper model.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/models/download" - }, - "DictationModelDownloadProgressRequest_unstable": { - "type": "object", - "properties": { - "modelId": { - "type": "string" - } - }, - "required": [ - "modelId" - ], - "description": "Poll the progress of an in-flight download.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/models/download/progress" - }, - "DictationModelDownloadProgressResponse_unstable": { - "type": "object", - "properties": { - "progress": { - "anyOf": [ - { - "$ref": "#/$defs/DictationDownloadProgress" - }, - { - "type": "null" - } - ], - "description": "None when no download is active for this model id." - } - }, - "x-side": "agent", - "x-method": "_goose/unstable/dictation/models/download/progress" - }, - "DictationDownloadProgress": { - "type": "object", - "properties": { - "bytesDownloaded": { - "type": "integer", - "minimum": 0 - }, - "totalBytes": { - "type": "integer", - "minimum": 0 - }, - "progressPercent": { - "type": "number", - "format": "float" - }, - "status": { - "type": "string", - "description": "serde lowercase of DownloadStatus: \"downloading\" | \"completed\" | \"failed\" | \"cancelled\"" - }, - "error": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "bytesDownloaded", - "totalBytes", - "progressPercent", - "status" - ] - }, - "DictationModelCancelRequest_unstable": { - "type": "object", - "properties": { - "modelId": { - "type": "string" - } - }, - "required": [ - "modelId" - ], - "description": "Cancel an in-flight download.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/models/cancel" - }, - "DictationModelDeleteRequest_unstable": { - "type": "object", - "properties": { - "modelId": { - "type": "string" - } - }, - "required": [ - "modelId" - ], - "description": "Delete a downloaded local Whisper model from disk.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/models/delete" - }, - "DictationModelSelectRequest_unstable": { - "type": "object", - "properties": { - "provider": { - "type": "string" - }, - "modelId": { - "type": "string" - } - }, - "required": [ - "provider", - "modelId" - ], - "description": "Persist the user's model selection for a given provider.", - "x-side": "agent", - "x-method": "_goose/unstable/dictation/models/select" - }, - "ExtRequest": { - "properties": { - "id": { - "type": "string" - }, - "method": { + "method": { "type": "string" }, "params": { @@ -3949,44 +1801,2201 @@ } }, "required": [ - "id" + "id" + ], + "title": "Success", + "type": "object" + }, + { + "properties": { + "error": { + "properties": { + "code": { + "type": "integer" + }, + "data": {}, + "message": { + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" + }, + "id": { + "type": "string" + } + }, + "required": [ + "id", + "error" + ], + "title": "Error", + "type": "object" + } + ], + "x-docs-ignore": true + }, + "GetAvailableExtensionsRequest_unstable": { + "description": "List Goose-owned extension definitions available to configure or enable.", + "type": "object", + "x-method": "_goose/unstable/extensions/available", + "x-side": "agent" + }, + "GetAvailableExtensionsResponse_unstable": { + "properties": { + "extensions": { + "items": { + "$ref": "#/$defs/GooseExtension" + }, + "type": "array" + } + }, + "required": [ + "extensions" + ], + "type": "object", + "x-method": "_goose/unstable/extensions/available", + "x-side": "agent" + }, + "GetConfigExtensionsRequest_unstable": { + "description": "List configured extensions and any warnings.", + "type": "object", + "x-method": "_goose/unstable/config/extensions/list", + "x-side": "agent" + }, + "GetConfigExtensionsResponse_unstable": { + "description": "List configured extensions and any warnings.", + "properties": { + "extensions": { + "items": { + "$ref": "#/$defs/GooseExtensionEntry" + }, + "type": "array" + }, + "warnings": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "extensions" + ], + "type": "object", + "x-method": "_goose/unstable/config/extensions/list", + "x-side": "agent" + }, + "GetSessionExtensionsRequest_unstable": { + "properties": { + "sessionId": { + "type": "string" + } + }, + "required": [ + "sessionId" + ], + "type": "object", + "x-method": "_goose/unstable/session/extensions/list", + "x-side": "agent" + }, + "GetSessionExtensionsResponse_unstable": { + "properties": { + "extensions": { + "items": {}, + "type": "array" + } + }, + "required": [ + "extensions" + ], + "type": "object", + "x-method": "_goose/unstable/session/extensions/list", + "x-side": "agent" + }, + "GetToolsRequest_unstable": { + "description": "List all tools available in a session.", + "properties": { + "sessionId": { + "type": "string" + } + }, + "required": [ + "sessionId" + ], + "type": "object", + "x-method": "_goose/unstable/tools/list", + "x-side": "agent" + }, + "GetToolsResponse_unstable": { + "description": "Tools response.", + "properties": { + "tools": { + "description": "Array of tool info objects with `name`, `description`, `parameters`, and optional `permission`.", + "items": {}, + "type": "array" + } + }, + "required": [ + "tools" + ], + "type": "object", + "x-method": "_goose/unstable/tools/list", + "x-side": "agent" + }, + "GooseExtension": { + "oneOf": [ + { + "properties": { + "bundled": { + "type": [ + "boolean", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "timeout": { + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "type": { + "const": "builtin", + "type": "string" + } + }, + "required": [ + "type", + "name" + ], + "type": "object" + }, + { + "properties": { + "bundled": { + "type": [ + "boolean", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "type": { + "const": "platform", + "type": "string" + } + }, + "required": [ + "type", + "name" + ], + "type": "object" + }, + { + "properties": { + "bundled": { + "type": [ + "boolean", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "envKeys": { + "items": { + "type": "string" + }, + "type": "array" + }, + "server": { + "$ref": "#/$defs/McpServer" + }, + "socket": { + "type": [ + "string", + "null" + ] + }, + "timeout": { + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "type": { + "const": "mcp", + "type": "string" + } + }, + "required": [ + "type", + "server" + ], + "type": "object" + }, + { + "properties": { + "code": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "timeout": { + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "type": { + "const": "inline_python", + "type": "string" + } + }, + "required": [ + "type", + "name", + "code" + ], + "type": "object" + }, + { + "properties": { + "bundled": { + "type": [ + "boolean", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "instructions": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "tools": { + "items": {}, + "type": "array" + }, + "type": { + "const": "frontend", + "type": "string" + } + }, + "required": [ + "type", + "name" + ], + "type": "object" + } + ] + }, + "GooseExtensionEntry": { + "properties": { + "configKey": { + "type": [ + "string", + "null" + ] + }, + "enabled": { + "type": "boolean" + }, + "extension": { + "$ref": "#/$defs/GooseExtension" + } + }, + "required": [ + "extension", + "enabled" + ], + "type": "object" + }, + "GooseToolCallRequest_unstable": { + "description": "Call a tool from an extension.", + "properties": { + "arguments": { + "default": null + }, + "name": { + "type": "string" + }, + "sessionId": { + "type": "string" + } + }, + "required": [ + "sessionId", + "name" + ], + "type": "object", + "x-method": "_goose/unstable/tools/call", + "x-side": "agent" + }, + "GooseToolCallResponse_unstable": { + "description": "Tool call response.", + "properties": { + "_meta": {}, + "content": { + "default": [], + "items": {}, + "type": "array" + }, + "isError": { + "type": "boolean" + }, + "structuredContent": {} + }, + "required": [ + "isError" + ], + "type": "object", + "x-method": "_goose/unstable/tools/call", + "x-side": "agent" + }, + "HttpHeader": { + "description": "An HTTP header to set when making requests to the MCP server.", + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": [ + "object", + "null" + ] + }, + "name": { + "description": "The name of the HTTP header.", + "type": "string" + }, + "value": { + "description": "The value to set for the HTTP header.", + "type": "string" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "ImportSessionRequest_unstable": { + "description": "Import a session from a JSON string.", + "properties": { + "data": { + "type": "string" + } + }, + "required": [ + "data" + ], + "type": "object", + "x-method": "_goose/unstable/session/import", + "x-side": "agent" + }, + "ImportSessionResponse_unstable": { + "description": "Import session response — metadata about the newly created session.", + "properties": { + "messageCount": { + "minimum": 0, + "type": "integer" + }, + "sessionId": { + "type": "string" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "updatedAt": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "sessionId", + "messageCount" + ], + "type": "object", + "x-method": "_goose/unstable/session/import", + "x-side": "agent" + }, + "ImportSourcesRequest_unstable": { + "description": "Import a source from a JSON export payload produced by `_goose/unstable/sources/export`.\nThe imported source is written into the explicit target scope; on name\ncollisions a `-imported` suffix is appended.", + "properties": { + "data": { + "type": "string" + }, + "target": { + "$ref": "#/$defs/SourceScope" + } + }, + "required": [ + "data", + "target" + ], + "type": "object", + "x-method": "_goose/unstable/sources/import", + "x-side": "agent" + }, + "ImportSourcesResponse_unstable": { + "properties": { + "sources": { + "items": { + "$ref": "#/$defs/SourceEntry" + }, + "type": "array" + } + }, + "required": [ + "sources" + ], + "type": "object", + "x-method": "_goose/unstable/sources/import", + "x-side": "agent" + }, + "ListProvidersRequest_unstable": { + "description": "List providers with setup metadata and the current model inventory snapshot.", + "properties": { + "providerIds": { + "default": [], + "description": "Only return entries for these providers. Empty means all.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "x-method": "_goose/unstable/providers/list", + "x-side": "agent" + }, + "ListProvidersResponse_unstable": { + "description": "Provider list response.", + "properties": { + "entries": { + "items": { + "$ref": "#/$defs/ProviderInventoryEntryDto" + }, + "type": "array" + } + }, + "required": [ + "entries" + ], + "type": "object", + "x-method": "_goose/unstable/providers/list", + "x-side": "agent" + }, + "ListSourcesRequest_unstable": { + "description": "List discovered sources.\n\nIf `type` is omitted or `skill`, this lists filesystem/plugin skills only.\nBoth global and project-scoped skills are included when `project_dir` is\nset. If `type` is `builtinSkill`, this lists shipped read-only built-in\nskills.", + "properties": { + "includeProjectSources": { + "default": false, + "description": "When true, also scan the working directories of all known projects for\nproject-scoped sources (e.g. skills stored under `{workingDir}/.agents/skills/`).", + "type": "boolean" + }, + "projectDir": { + "type": [ + "string", + "null" + ] + }, + "type": { + "anyOf": [ + { + "$ref": "#/$defs/SourceType" + }, + { + "type": "null" + } + ] + } + }, + "type": "object", + "x-method": "_goose/unstable/sources/list", + "x-side": "agent" + }, + "ListSourcesResponse_unstable": { + "properties": { + "sources": { + "items": { + "$ref": "#/$defs/SourceEntry" + }, + "type": "array" + } + }, + "required": [ + "sources" + ], + "type": "object", + "x-method": "_goose/unstable/sources/list", + "x-side": "agent" + }, + "McpServer": { + "anyOf": [ + { + "$ref": "#/$defs/McpServerHttp", + "description": "HTTP transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.http` is `true`.", + "properties": { + "type": { + "const": "http", + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + { + "$ref": "#/$defs/McpServerSse", + "description": "SSE transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`.", + "properties": { + "type": { + "const": "sse", + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + { + "$ref": "#/$defs/McpServerStdio", + "description": "Stdio transport configuration\n\nAll Agents MUST support this transport." + } + ], + "description": "Configuration for connecting to an MCP (Model Context Protocol) server.\n\nMCP servers provide tools and context that the agent can use when\nprocessing prompts.\n\nSee protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)" + }, + "McpServerHttp": { + "description": "HTTP transport configuration for MCP.", + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": [ + "object", + "null" + ] + }, + "headers": { + "description": "HTTP headers to set when making requests to the MCP server.", + "items": { + "$ref": "#/$defs/HttpHeader" + }, + "type": "array" + }, + "name": { + "description": "Human-readable name identifying this MCP server.", + "type": "string" + }, + "type": { + "const": "http", + "type": "string" + }, + "url": { + "description": "URL to the MCP server.", + "type": "string" + } + }, + "required": [ + "type", + "name", + "url", + "headers" + ], + "type": "object" + }, + "McpServerSse": { + "description": "SSE transport configuration for MCP.", + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": [ + "object", + "null" + ] + }, + "headers": { + "description": "HTTP headers to set when making requests to the MCP server.", + "items": { + "$ref": "#/$defs/HttpHeader" + }, + "type": "array" + }, + "name": { + "description": "Human-readable name identifying this MCP server.", + "type": "string" + }, + "type": { + "const": "sse", + "type": "string" + }, + "url": { + "description": "URL to the MCP server.", + "type": "string" + } + }, + "required": [ + "type", + "name", + "url", + "headers" + ], + "type": "object" + }, + "McpServerStdio": { + "description": "Stdio transport configuration for MCP.", + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": [ + "object", + "null" + ] + }, + "args": { + "description": "Command-line arguments to pass to the MCP server.", + "items": { + "type": "string" + }, + "type": "array" + }, + "command": { + "description": "Path to the MCP server executable.", + "type": "string" + }, + "env": { + "description": "Environment variables to set when launching the MCP server.", + "items": { + "$ref": "#/$defs/EnvVariable" + }, + "type": "array" + }, + "name": { + "description": "Human-readable name identifying this MCP server.", + "type": "string" + } + }, + "required": [ + "name", + "command", + "args", + "env" + ], + "type": "object" + }, + "OnboardingImportApplyRequest_unstable": { + "description": "Import selected onboarding candidates.", + "properties": { + "candidateIds": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + }, + "enableImportedExtensions": { + "default": false, + "type": "boolean" + } + }, + "type": "object", + "x-method": "_goose/unstable/onboarding/import/apply", + "x-side": "agent" + }, + "OnboardingImportApplyResponse_unstable": { + "properties": { + "imported": { + "$ref": "#/$defs/OnboardingImportCounts" + }, + "providerDefaults": { + "anyOf": [ + { + "$ref": "#/$defs/DefaultsReadResponse_unstable" + }, + { + "type": "null" + } + ] + }, + "skipped": { + "$ref": "#/$defs/OnboardingImportCounts" + }, + "warnings": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "imported", + "skipped" + ], + "type": "object", + "x-method": "_goose/unstable/onboarding/import/apply", + "x-side": "agent" + }, + "OnboardingImportCandidate": { + "properties": { + "counts": { + "$ref": "#/$defs/OnboardingImportCounts" + }, + "displayName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sourceKind": { + "$ref": "#/$defs/OnboardingImportSourceKind" + }, + "warnings": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "id", + "sourceKind", + "displayName", + "path", + "counts" + ], + "type": "object" + }, + "OnboardingImportCounts": { + "properties": { + "extensions": { + "minimum": 0, + "type": "integer" + }, + "preferences": { + "minimum": 0, + "type": "integer" + }, + "projects": { + "minimum": 0, + "type": "integer" + }, + "providers": { + "minimum": 0, + "type": "integer" + }, + "sessions": { + "minimum": 0, + "type": "integer" + }, + "skills": { + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "providers", + "extensions", + "sessions", + "skills", + "projects", + "preferences" + ], + "type": "object" + }, + "OnboardingImportScanRequest_unstable": { + "description": "Scan for existing Goose and compatible app data that onboarding can import.", + "properties": { + "sources": { + "default": [], + "description": "Empty means all supported import sources.", + "items": { + "$ref": "#/$defs/OnboardingImportSourceKind" + }, + "type": "array" + } + }, + "type": "object", + "x-method": "_goose/unstable/onboarding/import/scan", + "x-side": "agent" + }, + "OnboardingImportScanResponse_unstable": { + "properties": { + "candidates": { + "items": { + "$ref": "#/$defs/OnboardingImportCandidate" + }, + "type": "array" + } + }, + "required": [ + "candidates" + ], + "type": "object", + "x-method": "_goose/unstable/onboarding/import/scan", + "x-side": "agent" + }, + "OnboardingImportSourceKind": { + "description": "Sources that onboarding knows how to discover and import.", + "enum": [ + "goose_config", + "claude_desktop" + ], + "type": "string" + }, + "PreferenceKey": { + "enum": [ + "autoCompactThreshold", + "voiceAutoSubmitPhrases", + "voiceDictationProvider", + "voiceDictationPreferredMic" + ], + "type": "string" + }, + "PreferenceValue": { + "properties": { + "key": { + "$ref": "#/$defs/PreferenceKey" + }, + "value": { + "default": null + } + }, + "required": [ + "key" + ], + "type": "object" + }, + "PreferencesReadRequest_unstable": { + "description": "Read allowlisted user preferences. Empty `keys` means all supported preferences.", + "properties": { + "keys": { + "default": [], + "items": { + "$ref": "#/$defs/PreferenceKey" + }, + "type": "array" + } + }, + "type": "object", + "x-method": "_goose/unstable/preferences/read", + "x-side": "agent" + }, + "PreferencesReadResponse_unstable": { + "properties": { + "values": { + "items": { + "$ref": "#/$defs/PreferenceValue" + }, + "type": "array" + } + }, + "required": [ + "values" + ], + "type": "object", + "x-method": "_goose/unstable/preferences/read", + "x-side": "agent" + }, + "PreferencesRemoveRequest_unstable": { + "description": "Remove allowlisted user preferences.", + "properties": { + "keys": { + "default": [], + "items": { + "$ref": "#/$defs/PreferenceKey" + }, + "type": "array" + } + }, + "type": "object", + "x-method": "_goose/unstable/preferences/remove", + "x-side": "agent" + }, + "PreferencesSaveRequest_unstable": { + "description": "Save allowlisted user preferences.", + "properties": { + "values": { + "default": [], + "items": { + "$ref": "#/$defs/PreferenceValue" + }, + "type": "array" + } + }, + "type": "object", + "x-method": "_goose/unstable/preferences/save", + "x-side": "agent" + }, + "ProviderCatalogListRequest_unstable": { + "description": "List custom-provider catalog entries. Omit `format` to list all formats.", + "properties": { + "format": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object", + "x-method": "_goose/unstable/providers/catalog/list", + "x-side": "agent" + }, + "ProviderCatalogListResponse_unstable": { + "properties": { + "providers": { + "items": { + "$ref": "#/$defs/ProviderTemplateCatalogEntryDto" + }, + "type": "array" + } + }, + "required": [ + "providers" + ], + "type": "object", + "x-method": "_goose/unstable/providers/catalog/list", + "x-side": "agent" + }, + "ProviderCatalogTemplateRequest_unstable": { + "description": "Return the editable template for one catalog provider.", + "properties": { + "providerId": { + "type": "string" + } + }, + "required": [ + "providerId" + ], + "type": "object", + "x-method": "_goose/unstable/providers/catalog/template", + "x-side": "agent" + }, + "ProviderCatalogTemplateResponse_unstable": { + "properties": { + "template": { + "$ref": "#/$defs/ProviderTemplateDto" + } + }, + "required": [ + "template" + ], + "type": "object", + "x-method": "_goose/unstable/providers/catalog/template", + "x-side": "agent" + }, + "ProviderConfigAuthenticateRequest_unstable": { + "description": "Run a provider-owned native authentication flow and start an inventory refresh when supported.", + "properties": { + "providerId": { + "type": "string" + } + }, + "required": [ + "providerId" + ], + "type": "object", + "x-method": "_goose/unstable/providers/config/authenticate", + "x-side": "agent" + }, + "ProviderConfigChangeResponse_unstable": { + "properties": { + "refresh": { + "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" + }, + "status": { + "$ref": "#/$defs/ProviderConfigStatusDto" + } + }, + "required": [ + "status", + "refresh" + ], + "type": "object", + "x-side": "agent" + }, + "ProviderConfigDeleteRequest_unstable": { + "description": "Delete provider configuration fields and start an inventory refresh when supported.", + "properties": { + "providerId": { + "type": "string" + } + }, + "required": [ + "providerId" + ], + "type": "object", + "x-method": "_goose/unstable/providers/config/delete", + "x-side": "agent" + }, + "ProviderConfigFieldUpdate": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "key", + "value" + ], + "type": "object" + }, + "ProviderConfigFieldValueDto": { + "properties": { + "isSecret": { + "type": "boolean" + }, + "isSet": { + "type": "boolean" + }, + "key": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "value": { + "default": null, + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "key", + "isSet", + "isSecret", + "required" + ], + "type": "object" + }, + "ProviderConfigKey": { + "properties": { + "default": { + "default": null, + "type": [ + "string", + "null" + ] + }, + "deviceCodeFlow": { + "default": false, + "type": "boolean" + }, + "name": { + "type": "string" + }, + "oauthFlow": { + "default": false, + "type": "boolean" + }, + "primary": { + "default": false, + "type": "boolean" + }, + "required": { + "type": "boolean" + }, + "secret": { + "type": "boolean" + } + }, + "required": [ + "name", + "required", + "secret" + ], + "type": "object" + }, + "ProviderConfigReadRequest_unstable": { + "description": "Read saved configuration field values for one provider.", + "properties": { + "providerId": { + "type": "string" + } + }, + "required": [ + "providerId" + ], + "type": "object", + "x-method": "_goose/unstable/providers/config/read", + "x-side": "agent" + }, + "ProviderConfigReadResponse_unstable": { + "properties": { + "fields": { + "items": { + "$ref": "#/$defs/ProviderConfigFieldValueDto" + }, + "type": "array" + } + }, + "required": [ + "fields" + ], + "type": "object", + "x-method": "_goose/unstable/providers/config/read", + "x-side": "agent" + }, + "ProviderConfigSaveRequest_unstable": { + "description": "Save provider configuration fields and start an inventory refresh when supported.", + "properties": { + "fields": { + "items": { + "$ref": "#/$defs/ProviderConfigFieldUpdate" + }, + "type": "array" + }, + "providerId": { + "type": "string" + } + }, + "required": [ + "providerId", + "fields" + ], + "type": "object", + "x-method": "_goose/unstable/providers/config/save", + "x-side": "agent" + }, + "ProviderConfigStatusDto": { + "properties": { + "isConfigured": { + "type": "boolean" + }, + "providerId": { + "type": "string" + } + }, + "required": [ + "providerId", + "isConfigured" + ], + "type": "object" + }, + "ProviderConfigStatusRequest_unstable": { + "description": "Return provider configured statuses. Empty provider_ids means all providers.", + "properties": { + "providerIds": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "x-method": "_goose/unstable/providers/config/status", + "x-side": "agent" + }, + "ProviderConfigStatusResponse_unstable": { + "properties": { + "statuses": { + "items": { + "$ref": "#/$defs/ProviderConfigStatusDto" + }, + "type": "array" + } + }, + "required": [ + "statuses" + ], + "type": "object", + "x-method": "_goose/unstable/providers/config/status", + "x-side": "agent" + }, + "ProviderInventoryEntryDto": { + "description": "Provider inventory entry.", + "properties": { + "category": { + "$ref": "#/$defs/ProviderSetupCategoryDto", + "description": "Whether this inventory entry represents an agent provider or a model provider." + }, + "configKeys": { + "description": "Required configuration keys and setup metadata.", + "items": { + "$ref": "#/$defs/ProviderConfigKey" + }, + "type": "array" + }, + "configured": { + "description": "Whether Goose has enough configuration to use this provider.", + "type": "boolean" + }, + "defaultModel": { + "description": "The default/recommended model for this provider.", + "type": "string" + }, + "description": { + "description": "Description of the provider's capabilities.", + "type": "string" + }, + "lastRefreshAttemptAt": { + "description": "When a refresh was most recently attempted (ISO 8601).", + "type": [ + "string", + "null" + ] + }, + "lastRefreshError": { + "description": "The last refresh failure message, if any.", + "type": [ + "string", + "null" + ] + }, + "lastUpdatedAt": { + "description": "When this entry was last successfully refreshed (ISO 8601).", + "type": [ + "string", + "null" + ] + }, + "modelSelectionHint": { + "description": "Guidance message shown when this provider manages its own model selection externally.", + "type": [ + "string", + "null" + ] + }, + "models": { + "description": "The list of available models.", + "items": { + "$ref": "#/$defs/ProviderInventoryModelDto" + }, + "type": "array" + }, + "providerId": { + "description": "Provider identifier.", + "type": "string" + }, + "providerName": { + "description": "Human-readable provider name.", + "type": "string" + }, + "providerType": { + "description": "Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`.", + "type": "string" + }, + "refreshing": { + "description": "Whether a refresh is currently in flight.", + "type": "boolean" + }, + "setupSteps": { + "description": "Step-by-step setup instructions, when present.", + "items": { + "type": "string" + }, + "type": "array" + }, + "stale": { + "description": "Whether we believe this data may be outdated.", + "type": "boolean" + }, + "supportsRefresh": { + "description": "Whether this provider supports background inventory refresh.", + "type": "boolean" + } + }, + "required": [ + "providerId", + "providerName", + "description", + "defaultModel", + "configured", + "providerType", + "category", + "configKeys", + "setupSteps", + "supportsRefresh", + "refreshing", + "models", + "stale" + ], + "type": "object" + }, + "ProviderInventoryModelDto": { + "description": "A single model in provider inventory.", + "properties": { + "contextLimit": { + "description": "Context window size in tokens.", + "format": "uint", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "family": { + "description": "Model family for grouping in UI.", + "type": [ + "string", + "null" + ] + }, + "id": { + "description": "Model identifier as the provider knows it.", + "type": "string" + }, + "name": { + "description": "Human-readable display name.", + "type": "string" + }, + "reasoning": { + "description": "Whether the model supports reasoning/extended thinking.", + "type": [ + "boolean", + "null" + ] + }, + "recommended": { + "default": false, + "description": "Whether this model should appear in the compact recommended picker.", + "type": "boolean" + } + }, + "required": [ + "id", + "name" + ], + "type": "object" + }, + "ProviderSetupCatalogEntryDto": { + "properties": { + "aliases": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + }, + "binaryName": { + "type": [ + "string", + "null" + ] + }, + "category": { + "$ref": "#/$defs/ProviderSetupCategoryDto" + }, + "description": { + "type": "string" + }, + "docUrl": { + "type": [ + "string", + "null" + ] + }, + "fields": { + "default": [], + "items": { + "$ref": "#/$defs/ProviderSetupFieldDto" + }, + "type": "array" + }, + "group": { + "$ref": "#/$defs/ProviderSetupGroupDto" + }, + "name": { + "type": "string" + }, + "nativeConnectQuery": { + "type": [ + "string", + "null" + ] + }, + "providerId": { + "type": "string" + }, + "setupMethod": { + "$ref": "#/$defs/ProviderSetupMethodDto" + }, + "showOnlyWhenInstalled": { + "type": "boolean" + }, + "supportsAuth": { + "type": "boolean" + }, + "supportsAuthStatus": { + "type": "boolean" + }, + "supportsInstall": { + "type": "boolean" + } + }, + "required": [ + "providerId", + "name", + "category", + "description", + "setupMethod", + "group", + "showOnlyWhenInstalled", + "supportsInstall", + "supportsAuth", + "supportsAuthStatus" + ], + "type": "object" + }, + "ProviderSetupCatalogListRequest_unstable": { + "description": "List provider setup catalog entries", + "type": "object", + "x-method": "_goose/unstable/providers/setup/catalog/list", + "x-side": "agent" + }, + "ProviderSetupCatalogListResponse_unstable": { + "properties": { + "providers": { + "items": { + "$ref": "#/$defs/ProviderSetupCatalogEntryDto" + }, + "type": "array" + } + }, + "required": [ + "providers" + ], + "type": "object", + "x-method": "_goose/unstable/providers/setup/catalog/list", + "x-side": "agent" + }, + "ProviderSetupCategoryDto": { + "enum": [ + "agent", + "model" + ], + "type": "string" + }, + "ProviderSetupFieldDto": { + "properties": { + "defaultValue": { + "type": [ + "string", + "null" + ] + }, + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "placeholder": { + "type": [ + "string", + "null" + ] + }, + "required": { + "type": "boolean" + }, + "secret": { + "type": "boolean" + } + }, + "required": [ + "key", + "label", + "secret", + "required" + ], + "type": "object" + }, + "ProviderSetupGroupDto": { + "enum": [ + "default", + "additional" + ], + "type": "string" + }, + "ProviderSetupMethodDto": { + "enum": [ + "none", + "single_api_key", + "config_fields", + "host_with_oauth_fallback", + "oauth_browser", + "oauth_device_code", + "cloud_credentials", + "local", + "cli_auth" + ], + "type": "string" + }, + "ProviderSupportedModelsListRequest_unstable": { + "description": "List the raw model identifiers returned by a provider's live supported-models API.", + "properties": { + "providerId": { + "type": "string" + } + }, + "required": [ + "providerId" + ], + "type": "object", + "x-method": "_goose/unstable/providers/supported-models/list", + "x-side": "agent" + }, + "ProviderSupportedModelsListResponse_unstable": { + "properties": { + "models": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providerId": { + "type": "string" + } + }, + "required": [ + "providerId", + "models" + ], + "type": "object", + "x-method": "_goose/unstable/providers/supported-models/list", + "x-side": "agent" + }, + "ProviderTemplateCapabilitiesDto": { + "properties": { + "attachment": { + "type": "boolean" + }, + "reasoning": { + "type": "boolean" + }, + "temperature": { + "type": "boolean" + }, + "toolCall": { + "type": "boolean" + } + }, + "required": [ + "toolCall", + "reasoning", + "attachment", + "temperature" + ], + "type": "object" + }, + "ProviderTemplateCatalogEntryDto": { + "properties": { + "apiUrl": { + "type": "string" + }, + "docUrl": { + "type": "string" + }, + "envVar": { + "type": "string" + }, + "format": { + "type": "string" + }, + "modelCount": { + "minimum": 0, + "type": "integer" + }, + "name": { + "type": "string" + }, + "providerId": { + "type": "string" + } + }, + "required": [ + "providerId", + "name", + "format", + "apiUrl", + "modelCount", + "docUrl", + "envVar" + ], + "type": "object" + }, + "ProviderTemplateDto": { + "properties": { + "apiUrl": { + "type": "string" + }, + "docUrl": { + "type": "string" + }, + "envVar": { + "type": "string" + }, + "format": { + "type": "string" + }, + "models": { + "items": { + "$ref": "#/$defs/ProviderTemplateModelDto" + }, + "type": "array" + }, + "name": { + "type": "string" + }, + "providerId": { + "type": "string" + }, + "supportsStreaming": { + "type": "boolean" + } + }, + "required": [ + "providerId", + "name", + "format", + "apiUrl", + "models", + "supportsStreaming", + "envVar", + "docUrl" + ], + "type": "object" + }, + "ProviderTemplateModelDto": { + "properties": { + "capabilities": { + "$ref": "#/$defs/ProviderTemplateCapabilitiesDto" + }, + "contextLimit": { + "minimum": 0, + "type": "integer" + }, + "deprecated": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "contextLimit", + "capabilities", + "deprecated" + ], + "type": "object" + }, + "ReadResourceRequest_unstable": { + "description": "Read a resource from an extension.", + "properties": { + "extensionName": { + "type": "string" + }, + "sessionId": { + "type": "string" + }, + "uri": { + "type": "string" + } + }, + "required": [ + "sessionId", + "uri", + "extensionName" + ], + "type": "object", + "x-method": "_goose/unstable/resources/read", + "x-side": "agent" + }, + "ReadResourceResponse_unstable": { + "description": "Resource read response.", + "properties": { + "result": { + "default": null, + "description": "The resource result from the extension (MCP ReadResourceResult)." + } + }, + "type": "object", + "x-method": "_goose/unstable/resources/read", + "x-side": "agent" + }, + "RefreshProviderInventoryRequest_unstable": { + "description": "Trigger a background refresh of provider inventories.", + "properties": { + "providerIds": { + "default": [], + "description": "Which providers to refresh. Empty means all known providers.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "x-method": "_goose/unstable/providers/inventory/refresh", + "x-side": "agent" + }, + "RefreshProviderInventoryResponse_unstable": { + "description": "Refresh acknowledgement.", + "properties": { + "skipped": { + "default": [], + "description": "Which providers were skipped and why.", + "items": { + "$ref": "#/$defs/RefreshProviderInventorySkipDto" + }, + "type": "array" + }, + "started": { + "description": "Which providers will be refreshed.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "started" + ], + "type": "object", + "x-method": "_goose/unstable/providers/inventory/refresh", + "x-side": "agent" + }, + "RefreshProviderInventorySkipDto": { + "properties": { + "providerId": { + "type": "string" + }, + "reason": { + "$ref": "#/$defs/RefreshProviderInventorySkipReasonDto" + } + }, + "required": [ + "providerId", + "reason" + ], + "type": "object" + }, + "RefreshProviderInventorySkipReasonDto": { + "enum": [ + "unknown_provider", + "not_configured", + "does_not_support_refresh", + "already_refreshing" + ], + "type": "string" + }, + "RemoveConfigExtensionRequest_unstable": { + "description": "Remove a persisted extension from the user's global goose config.", + "properties": { + "configKey": { + "type": "string" + } + }, + "required": [ + "configKey" + ], + "type": "object", + "x-method": "_goose/unstable/config/extensions/remove", + "x-side": "agent" + }, + "RemoveExtensionRequest_unstable": { + "description": "Remove an extension from an active session.", + "properties": { + "name": { + "type": "string" + }, + "sessionId": { + "type": "string" + } + }, + "required": [ + "sessionId", + "name" + ], + "type": "object", + "x-method": "_goose/unstable/session/extensions/remove", + "x-side": "agent" + }, + "RenameSessionRequest_unstable": { + "description": "Rename a session.", + "properties": { + "sessionId": { + "type": "string" + }, + "title": { + "type": "string" + } + }, + "required": [ + "sessionId", + "title" + ], + "type": "object", + "x-method": "_goose/unstable/session/rename", + "x-side": "agent" + }, + "SessionSystemPromptMode": { + "description": "How a session system prompt update should be applied.", + "oneOf": [ + { + "const": "set", + "description": "Replace Goose's base system prompt with the provided text.", + "type": "string" + }, + { + "const": "append", + "description": "Append the provided text under Goose's \"Additional Instructions\" section.", + "type": "string" + } + ] + }, + "SetConfigExtensionEnabledRequest_unstable": { + "description": "Set the `enabled` flag for a persisted extension in the user's global goose config.", + "properties": { + "configKey": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + }, + "required": [ + "configKey", + "enabled" + ], + "type": "object", + "x-method": "_goose/unstable/config/extensions/set-enabled", + "x-side": "agent" + }, + "SetSessionSystemPromptRequest_unstable": { + "description": "Set, append, or clear system prompt text for a session.\n\n`mode: \"set\"` replaces Goose's base system prompt. `mode: \"append\"` adds an\ninstruction under \"Additional Instructions\". Reusing a key replaces the\nprevious value for that mode/key; sending empty text clears it.", + "properties": { + "key": { + "type": [ + "string", + "null" + ] + }, + "mode": { + "$ref": "#/$defs/SessionSystemPromptMode", + "default": "append" + }, + "sessionId": { + "type": "string" + }, + "text": { + "type": "string" + } + }, + "required": [ + "sessionId", + "text" + ], + "type": "object", + "x-method": "_goose/unstable/session/system-prompt/set", + "x-side": "agent" + }, + "SourceEntry": { + "description": "A source discovered by Goose. Filesystem sources use an on-disk path;\nbuilt-in sources use a stable synthetic path. Sources may be either\n`global` (shared across all projects) or project-specific.", + "properties": { + "content": { + "type": "string" + }, + "description": { + "type": "string" + }, + "global": { + "description": "True when the source lives in the user's global sources directory; false\nwhen it lives inside a specific project.", + "type": "boolean" + }, + "name": { + "type": "string" + }, + "path": { + "description": "Stable on-disk path identifying this source. Pass it back to\nupdate/delete/export to operate on this entry. Skills use the directory\ncontaining `SKILL.md`; projects use the project file path; built-in\nskills use `builtin://skills/` synthetic paths.", + "type": "string" + }, + "properties": { + "additionalProperties": {}, + "description": "Arbitrary key/value pairs for type-specific metadata (e.g. icon, color,\npreferredProvider for projects). Stored in the frontmatter.", + "type": "object" + }, + "supportingFiles": { + "description": "Paths (absolute) of additional files that live alongside the source.\nOnly skills currently populate this; empty for other source types.", + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "$ref": "#/$defs/SourceType" + }, + "writable": { + "default": false, + "description": "True when this source can be modified through source CRUD methods.\nClient-provided bundled sources are returned as read-only.", + "type": "boolean" + } + }, + "required": [ + "type", + "name", + "description", + "content", + "path", + "global" + ], + "type": "object" + }, + "SourceScope": { + "description": "Target scope for creating or importing sources.", + "oneOf": [ + { + "properties": { + "scope": { + "const": "global", + "type": "string" + } + }, + "required": [ + "scope" ], - "title": "Success", "type": "object" }, { "properties": { - "error": { - "type": "object", - "properties": { - "code": { - "type": "integer" - }, - "message": { - "type": "string" - }, - "data": {} - }, - "required": [ - "code", - "message" - ] + "projectDir": { + "type": "string" }, - "id": { + "scope": { + "const": "projectDir", "type": "string" } }, "required": [ - "id", - "error" + "scope", + "projectDir" + ], + "type": "object" + }, + { + "properties": { + "projectId": { + "type": "string" + }, + "scope": { + "const": "projectId", + "type": "string" + } + }, + "required": [ + "scope", + "projectId" ], - "title": "Error", "type": "object" } + ] + }, + "SourceType": { + "description": "The type of source entity.", + "enum": [ + "skill", + "builtinSkill", + "recipe", + "subrecipe", + "agent", + "project" ], - "x-docs-ignore": true + "type": "string" + }, + "UnarchiveSessionRequest_unstable": { + "description": "Unarchive a previously archived session.", + "properties": { + "sessionId": { + "type": "string" + } + }, + "required": [ + "sessionId" + ], + "type": "object", + "x-method": "_goose/unstable/session/unarchive", + "x-side": "agent" + }, + "UpdateSessionProjectRequest_unstable": { + "description": "Update the project association for a session.", + "properties": { + "projectId": { + "type": [ + "string", + "null" + ] + }, + "sessionId": { + "type": "string" + } + }, + "required": [ + "sessionId" + ], + "type": "object", + "x-method": "_goose/unstable/session/project/update", + "x-side": "agent" + }, + "UpdateSourceRequest_unstable": { + "description": "Update an existing source's name, description, and content by absolute path.", + "properties": { + "content": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "type": "string" + }, + "properties": { + "additionalProperties": {}, + "description": "When `Some`, replaces all stored properties on the source. When\n`None` (or omitted), the source's existing properties are\npreserved. Callers that don't model the full property bag (e.g.\nthe skills editor, which only edits name/description/content)\nshould omit this so per-skill metadata isn't silently erased.", + "type": [ + "object", + "null" + ] + }, + "type": { + "$ref": "#/$defs/SourceType" + } + }, + "required": [ + "type", + "path", + "name", + "description", + "content" + ], + "type": "object", + "x-method": "_goose/unstable/sources/update", + "x-side": "agent" + }, + "UpdateSourceResponse_unstable": { + "properties": { + "source": { + "$ref": "#/$defs/SourceEntry" + } + }, + "required": [ + "source" + ], + "type": "object", + "x-method": "_goose/unstable/sources/update", + "x-side": "agent" + }, + "UpdateWorkingDirRequest_unstable": { + "description": "Update the working directory for a session.", + "properties": { + "sessionId": { + "type": "string" + }, + "workingDir": { + "type": "string" + } + }, + "required": [ + "sessionId", + "workingDir" + ], + "type": "object", + "x-method": "_goose/unstable/session/working-dir/update", + "x-side": "agent" } }, + "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "allOf": [ @@ -4006,5 +4015,6 @@ "description": "Extension response (agent → client)", "title": "Response" } - ] + ], + "title": "GooseExtensions" } diff --git a/crates/goose/src/bin/generate_acp_schema.rs b/crates/goose/src/bin/generate_acp_schema.rs index 905dacb1a13a..c7f785c96bf0 100644 --- a/crates/goose/src/bin/generate_acp_schema.rs +++ b/crates/goose/src/bin/generate_acp_schema.rs @@ -72,6 +72,8 @@ fn main() { strip_integer_formats(def); } + add_mcp_server_transport_discriminants(&mut defs); + // Annotate $defs entries with x-method/x-side. Only set x-method for types // used by exactly one method (shared types like EmptyResponse skip x-method). for (name, methods_list) in &type_methods { @@ -263,6 +265,42 @@ fn rewrite_unstable_schema_refs(value: &mut Value, unstable_type_names: &BTreeSe } } +fn add_mcp_server_transport_discriminants(defs: &mut Map) { + add_object_discriminant(defs, "McpServerHttp", "http"); + add_object_discriminant(defs, "McpServerSse", "sse"); +} + +fn add_object_discriminant(defs: &mut Map, def_name: &str, tag: &str) { + let def = defs + .get_mut(def_name) + .unwrap_or_else(|| panic!("missing {def_name} schema definition")); + let obj = def + .as_object_mut() + .unwrap_or_else(|| panic!("{def_name} schema definition must be an object")); + + let properties = obj + .entry("properties") + .or_insert_with(|| json!({})) + .as_object_mut() + .unwrap_or_else(|| panic!("{def_name}.properties must be an object")); + properties.insert( + "type".into(), + json!({ + "type": "string", + "const": tag, + }), + ); + + let required = obj + .entry("required") + .or_insert_with(|| json!([])) + .as_array_mut() + .unwrap_or_else(|| panic!("{def_name}.required must be an array")); + if !required.iter().any(|item| item.as_str() == Some("type")) { + required.insert(0, json!("type")); + } +} + /// Recursively strip `"format"` from integer-typed schemas. /// /// schemars emits `"format": "uint64"` / `"int64"` etc. for Rust integer types. @@ -314,3 +352,64 @@ fn replace_true_schemas(value: &mut Value) { _ => {} } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn adds_http_and_sse_discriminants_without_tagging_stdio() { + let mut defs = Map::from_iter([ + ( + "McpServerHttp".into(), + json!({ + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "required": ["name"] + }), + ), + ( + "McpServerSse".into(), + json!({ + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "required": ["name"] + }), + ), + ( + "McpServerStdio".into(), + json!({ + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "required": ["name"] + }), + ), + ]); + + add_mcp_server_transport_discriminants(&mut defs); + + assert_eq!( + defs["McpServerHttp"]["properties"]["type"], + json!({ "type": "string", "const": "http" }) + ); + assert_eq!( + defs["McpServerSse"]["properties"]["type"], + json!({ "type": "string", "const": "sse" }) + ); + assert_eq!(defs["McpServerStdio"]["properties"].get("type"), None); + assert!(defs["McpServerHttp"]["required"] + .as_array() + .unwrap() + .contains(&json!("type"))); + assert!(defs["McpServerSse"]["required"] + .as_array() + .unwrap() + .contains(&json!("type"))); + } +} diff --git a/ui/sdk/src/generated/types.gen.ts b/ui/sdk/src/generated/types.gen.ts index dda422f17524..95d23e4523bf 100644 --- a/ui/sdk/src/generated/types.gen.ts +++ b/ui/sdk/src/generated/types.gen.ts @@ -1,113 +1,166 @@ // This file is auto-generated by @hey-api/openapi-ts +/** + * Persist a new extension to the user's global goose config. + */ +export type AddConfigExtensionRequest_unstable = { + enabled?: boolean; + extension: GooseExtension; +}; + /** * Add an extension to an active session. */ export type AddExtensionRequest_unstable = { - sessionId: string; /** * Extension configuration (see ExtensionConfig variants: Stdio, StreamableHttp, Builtin, Platform). */ config?: unknown; + sessionId: string; }; /** - * Empty success response for operations that return no data. + * Archive a session (soft delete). */ -export type EmptyResponse = { - [key: string]: unknown; +export type ArchiveSessionRequest_unstable = { + sessionId: string; }; /** - * Remove an extension from an active session. + * Create a new source in an explicit target scope (global or project-scoped). */ -export type RemoveExtensionRequest_unstable = { - sessionId: string; +export type CreateSourceRequest_unstable = { + content: string; + description: string; name: string; + /** + * Arbitrary key/value metadata. + */ + properties?: { + [key: string]: unknown; + }; + target: SourceScope; + type: SourceType; }; -/** - * List all tools available in a session. - */ -export type GetToolsRequest_unstable = { - sessionId: string; +export type CreateSourceResponse_unstable = { + source: SourceEntry; }; -/** - * Tools response. - */ -export type GetToolsResponse_unstable = { - /** - * Array of tool info objects with `name`, `description`, `parameters`, and optional `permission`. - */ - tools: Array; +export type CustomProviderConfigDto = { + apiKeyEnv?: string | null; + apiKeySet: boolean; + apiUrl: string; + basePath?: string | null; + catalogProviderId?: string | null; + displayName: string; + engine: string; + headers?: { + [key: string]: string; + }; + models?: Array; + preservesThinking: boolean; + providerId: string; + requiresAuth: boolean; + supportsStreaming?: boolean | null; }; /** - * Call a tool from an extension. + * Create a custom provider backed by Goose's declarative provider store. */ -export type GooseToolCallRequest_unstable = { - sessionId: string; - name: string; - arguments?: unknown; +export type CustomProviderCreateRequest_unstable = { + apiKey?: string | null; + apiUrl: string; + basePath?: string | null; + catalogProviderId?: string | null; + displayName: string; + engine: string; + headers?: { + [key: string]: string; + }; + models?: Array; + preservesThinking?: boolean | null; + requiresAuth: boolean; + supportsStreaming?: boolean | null; }; -/** - * Tool call response. - */ -export type GooseToolCallResponse_unstable = { - content?: Array; - structuredContent?: unknown; - isError: boolean; - _meta?: unknown; +export type CustomProviderCreateResponse_unstable = { + providerId: string; + refresh: RefreshProviderInventoryResponse_unstable; + status: ProviderConfigStatusDto; }; /** - * Read a resource from an extension. + * Delete a custom provider from Goose's declarative provider store. */ -export type ReadResourceRequest_unstable = { - sessionId: string; - uri: string; - extensionName: string; +export type CustomProviderDeleteRequest_unstable = { + providerId: string; +}; + +export type CustomProviderDeleteResponse_unstable = { + providerId: string; + refresh: RefreshProviderInventoryResponse_unstable; }; /** - * Resource read response. + * Read a declarative provider config. Custom configs are editable; bundled configs are read-only. */ -export type ReadResourceResponse_unstable = { - /** - * The resource result from the extension (MCP ReadResourceResult). - */ - result?: unknown; +export type CustomProviderReadRequest_unstable = { + providerId: string; +}; + +export type CustomProviderReadResponse_unstable = { + editable: boolean; + provider: CustomProviderConfigDto; + status: ProviderConfigStatusDto; }; /** - * Update the working directory for a session. + * Update a custom provider backed by Goose's declarative provider store. */ -export type UpdateWorkingDirRequest_unstable = { - sessionId: string; - workingDir: string; +export type CustomProviderUpdateRequest_unstable = { + apiKey?: string | null; + apiUrl: string; + basePath?: string | null; + catalogProviderId?: string | null; + displayName: string; + engine: string; + headers?: { + [key: string]: string; + }; + models?: Array; + preservesThinking?: boolean | null; + providerId: string; + requiresAuth: boolean; + supportsStreaming?: boolean | null; +}; + +export type CustomProviderUpdateResponse_unstable = { + providerId: string; + refresh: RefreshProviderInventoryResponse_unstable; + status: ProviderConfigStatusDto; }; /** - * Set, append, or clear system prompt text for a session. - * - * `mode: "set"` replaces Goose's base system prompt. `mode: "append"` adds an - * instruction under "Additional Instructions". Reusing a key replaces the - * previous value for that mode/key; sending empty text clears it. + * Read Goose default provider and model configuration. */ -export type SetSessionSystemPromptRequest_unstable = { - sessionId: string; - mode?: SessionSystemPromptMode; - key?: string | null; - text: string; +export type DefaultsReadRequest_unstable = { + [key: string]: unknown; +}; + +export type DefaultsReadResponse_unstable = { + modelId?: string | null; + providerId?: string | null; }; /** - * How a session system prompt update should be applied. + * Save Goose default provider and model configuration. */ -export type SessionSystemPromptMode = 'set' | 'append'; +export type DefaultsSaveRequest_unstable = { + modelId?: string | null; + providerId: string; +}; /** * Delete a session. @@ -117,173 +170,176 @@ export type DeleteSessionRequest = { }; /** - * List configured extensions and any warnings. + * Delete a source and its on-disk directory by absolute path. */ -export type GetConfigExtensionsRequest_unstable = { +export type DeleteSourceRequest_unstable = { + path: string; + type: SourceType; +}; + +/** + * Get the configuration status of all dictation providers. + */ +export type DictationConfigRequest_unstable = { [key: string]: unknown; }; /** - * List configured extensions and any warnings. + * Dictation config response — map of provider name to status. */ -export type GetConfigExtensionsResponse_unstable = { - extensions: Array; - warnings?: Array; +export type DictationConfigResponse_unstable = { + providers: { + [key: string]: DictationProviderStatusEntry; + }; }; -export type GooseExtensionEntry = { - extension: GooseExtension; - enabled: boolean; - configKey?: string | null; +export type DictationDownloadProgress = { + bytesDownloaded: number; + error?: string | null; + progressPercent: number; + /** + * serde lowercase of DownloadStatus: "downloading" | "completed" | "failed" | "cancelled" + */ + status: string; + totalBytes: number; }; -export type GooseExtension = { - name: string; - description?: string | null; - display_name?: string | null; - timeout?: number | null; - bundled?: boolean | null; - type: 'builtin'; -} | { - name: string; - description?: string | null; - display_name?: string | null; - bundled?: boolean | null; - type: 'platform'; -} | { - server: McpServer; - envKeys?: Array; - description?: string | null; - timeout?: number | null; - socket?: string | null; - bundled?: boolean | null; - type: 'mcp'; -} | { - name: string; - description?: string | null; - code: string; - timeout?: number | null; - dependencies?: Array; - type: 'inline_python'; -} | { - name: string; - description?: string | null; - tools?: Array; - instructions?: string | null; - bundled?: boolean | null; - type: 'frontend'; +export type DictationLocalModelStatus = { + description: string; + downloadInProgress: boolean; + downloaded: boolean; + id: string; + label: string; + sizeMb: number; }; /** - * Configuration for connecting to an MCP (Model Context Protocol) server. - * - * MCP servers provide tools and context that the agent can use when - * processing prompts. - * - * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) + * Cancel an in-flight download. */ -export type McpServer = McpServerHttp | McpServerSse | McpServerStdio; +export type DictationModelCancelRequest_unstable = { + modelId: string; +}; /** - * An HTTP header to set when making requests to the MCP server. + * Delete a downloaded local Whisper model from disk. */ -export type HttpHeader = { - /** - * The name of the HTTP header. - */ - name: string; +export type DictationModelDeleteRequest_unstable = { + modelId: string; +}; + +/** + * Poll the progress of an in-flight download. + */ +export type DictationModelDownloadProgressRequest_unstable = { + modelId: string; +}; + +export type DictationModelDownloadProgressResponse_unstable = { /** - * The value to set for the HTTP header. + * None when no download is active for this model id. */ + progress?: DictationDownloadProgress | null; +}; + +/** + * Kick off a background download of a local Whisper model. + */ +export type DictationModelDownloadRequest_unstable = { + modelId: string; +}; + +export type DictationModelOption = { + description: string; + id: string; + label: string; +}; + +/** + * Persist the user's model selection for a given provider. + */ +export type DictationModelSelectRequest_unstable = { + modelId: string; + provider: string; +}; + +/** + * List available local Whisper models with their download status. + */ +export type DictationModelsListRequest_unstable = { + [key: string]: unknown; +}; + +export type DictationModelsListResponse_unstable = { + models: Array; +}; + +/** + * Per-provider configuration status. + */ +export type DictationProviderStatusEntry = { + availableModels?: Array; + configKey?: string | null; + configured: boolean; + defaultModel?: string | null; + description: string; + host?: string | null; + modelConfigKey?: string | null; + selectedModel?: string | null; + settingsPath?: string | null; + usesProviderConfig: boolean; +}; + +/** + * Remove a dictation provider secret value. + */ +export type DictationSecretDeleteRequest_unstable = { + provider: string; +}; + +/** + * Set a dictation provider secret value. + */ +export type DictationSecretSaveRequest_unstable = { + provider: string; value: string; - /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - */ - _meta?: { - [key: string]: unknown; - } | null; }; /** - * HTTP transport configuration for MCP. + * Transcribe audio via a dictation provider. */ -export type McpServerHttp = { - /** - * Human-readable name identifying this MCP server. - */ - name: string; +export type DictationTranscribeRequest_unstable = { /** - * URL to the MCP server. + * Base64-encoded audio data */ - url: string; + audio: string; /** - * HTTP headers to set when making requests to the MCP server. + * MIME type (e.g. "audio/wav", "audio/webm") */ - headers: Array; + mimeType: string; /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + * Provider to use: "openai", "groq", "elevenlabs", or "local" */ - _meta?: { - [key: string]: unknown; - } | null; + provider: string; }; /** - * SSE transport configuration for MCP. + * Transcription result. */ -export type McpServerSse = { - /** - * Human-readable name identifying this MCP server. - */ - name: string; - /** - * URL to the MCP server. - */ - url: string; - /** - * HTTP headers to set when making requests to the MCP server. - */ - headers: Array; - /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - */ - _meta?: { - [key: string]: unknown; - } | null; +export type DictationTranscribeResponse_unstable = { + text: string; }; /** - * Stdio transport configuration for MCP. + * Empty success response for operations that return no data. */ -export type McpServerStdio = { - /** - * Human-readable name identifying this MCP server. - */ - name: string; - /** - * Path to the MCP server executable. - */ - command: string; - /** - * Command-line arguments to pass to the MCP server. - */ - args: Array; - /** - * Environment variables to set when launching the MCP server. - */ - env: Array; +export type EmptyResponse = { + [key: string]: unknown; +}; + +/** + * An environment variable to set when launching an MCP server. + */ +export type EnvVariable = { /** * The _meta property is reserved by ACP to allow clients and agents to attach additional * metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -294,12 +350,6 @@ export type McpServerStdio = { _meta?: { [key: string]: unknown; } | null; -}; - -/** - * An environment variable to set when launching an MCP server. - */ -export type EnvVariable = { /** * The name of the environment variable. */ @@ -308,495 +358,419 @@ export type EnvVariable = { * The value to set for the environment variable. */ value: string; - /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - */ - _meta?: { - [key: string]: unknown; - } | null; }; /** - * List Goose-owned extension definitions available to configure or enable. + * Export a session as a JSON string. */ -export type GetAvailableExtensionsRequest_unstable = { - [key: string]: unknown; -}; - -export type GetAvailableExtensionsResponse_unstable = { - extensions: Array; +export type ExportSessionRequest_unstable = { + sessionId: string; }; /** - * Persist a new extension to the user's global goose config. + * Export session response — raw JSON of the goose session with `conversation`. */ -export type AddConfigExtensionRequest_unstable = { - extension: GooseExtension; - enabled?: boolean; +export type ExportSessionResponse_unstable = { + data: string; }; /** - * Remove a persisted extension from the user's global goose config. + * Export a source at an absolute path as a portable JSON payload. */ -export type RemoveConfigExtensionRequest_unstable = { - configKey: string; +export type ExportSourceRequest_unstable = { + path: string; + type: SourceType; }; -/** - * Set the `enabled` flag for a persisted extension in the user's global goose config. - */ -export type SetConfigExtensionEnabledRequest_unstable = { - configKey: string; - enabled: boolean; +export type ExportSourceResponse_unstable = { + filename: string; + json: string; }; -export type GetSessionExtensionsRequest_unstable = { - sessionId: string; +export type ExtRequest = { + id: string; + method: string; + params?: AddExtensionRequest_unstable | RemoveExtensionRequest_unstable | GetToolsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | DeleteSessionRequest | GetConfigExtensionsRequest_unstable | GetAvailableExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | SetConfigExtensionEnabledRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | { + [key: string]: unknown; + } | null; }; -export type GetSessionExtensionsResponse_unstable = { - extensions: Array; +export type ExtResponse = { + id: string; + result?: EmptyResponse | GetToolsResponse_unstable | GooseToolCallResponse_unstable | ReadResourceResponse_unstable | GetConfigExtensionsResponse_unstable | GetAvailableExtensionsResponse_unstable | GetSessionExtensionsResponse_unstable | ListProvidersResponse_unstable | ProviderSupportedModelsListResponse_unstable | ProviderCatalogListResponse_unstable | ProviderSetupCatalogListResponse_unstable | ProviderCatalogTemplateResponse_unstable | CustomProviderCreateResponse_unstable | CustomProviderReadResponse_unstable | CustomProviderUpdateResponse_unstable | CustomProviderDeleteResponse_unstable | RefreshProviderInventoryResponse_unstable | ProviderConfigReadResponse_unstable | ProviderConfigStatusResponse_unstable | ProviderConfigChangeResponse_unstable | PreferencesReadResponse_unstable | DefaultsReadResponse_unstable | OnboardingImportScanResponse_unstable | OnboardingImportApplyResponse_unstable | ExportSessionResponse_unstable | ImportSessionResponse_unstable | CreateSourceResponse_unstable | ListSourcesResponse_unstable | UpdateSourceResponse_unstable | ExportSourceResponse_unstable | ImportSourcesResponse_unstable | DictationTranscribeResponse_unstable | DictationConfigResponse_unstable | DictationModelsListResponse_unstable | DictationModelDownloadProgressResponse_unstable | unknown; +} | { + error: { + code: number; + data?: unknown; + message: string; + }; + id: string; }; /** - * List providers with setup metadata and the current model inventory snapshot. + * List Goose-owned extension definitions available to configure or enable. */ -export type ListProvidersRequest_unstable = { - /** - * Only return entries for these providers. Empty means all. - */ - providerIds?: Array; +export type GetAvailableExtensionsRequest_unstable = { + [key: string]: unknown; +}; + +export type GetAvailableExtensionsResponse_unstable = { + extensions: Array; }; /** - * Provider list response. + * List configured extensions and any warnings. */ -export type ListProvidersResponse_unstable = { - entries: Array; +export type GetConfigExtensionsRequest_unstable = { + [key: string]: unknown; }; /** - * Provider inventory entry. + * List configured extensions and any warnings. */ -export type ProviderInventoryEntryDto = { - /** - * Provider identifier. - */ - providerId: string; - /** - * Human-readable provider name. - */ - providerName: string; - /** - * Description of the provider's capabilities. - */ - description: string; - /** - * The default/recommended model for this provider. - */ - defaultModel: string; - /** - * Whether Goose has enough configuration to use this provider. - */ - configured: boolean; - /** - * Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`. - */ - providerType: string; - /** - * Whether this inventory entry represents an agent provider or a model provider. - */ - category: ProviderSetupCategoryDto; - /** - * Required configuration keys and setup metadata. - */ - configKeys: Array; - /** - * Step-by-step setup instructions, when present. - */ - setupSteps: Array; - /** - * Whether this provider supports background inventory refresh. - */ - supportsRefresh: boolean; - /** - * Whether a refresh is currently in flight. - */ - refreshing: boolean; - /** - * The list of available models. - */ - models: Array; - /** - * When this entry was last successfully refreshed (ISO 8601). - */ - lastUpdatedAt?: string | null; - /** - * When a refresh was most recently attempted (ISO 8601). - */ - lastRefreshAttemptAt?: string | null; - /** - * The last refresh failure message, if any. - */ - lastRefreshError?: string | null; - /** - * Whether we believe this data may be outdated. - */ - stale: boolean; +export type GetConfigExtensionsResponse_unstable = { + extensions: Array; + warnings?: Array; +}; + +export type GetSessionExtensionsRequest_unstable = { + sessionId: string; +}; + +export type GetSessionExtensionsResponse_unstable = { + extensions: Array; +}; + +/** + * List all tools available in a session. + */ +export type GetToolsRequest_unstable = { + sessionId: string; +}; + +/** + * Tools response. + */ +export type GetToolsResponse_unstable = { /** - * Guidance message shown when this provider manages its own model selection externally. + * Array of tool info objects with `name`, `description`, `parameters`, and optional `permission`. */ - modelSelectionHint?: string | null; + tools: Array; }; -export type ProviderSetupCategoryDto = 'agent' | 'model'; +export type GooseExtension = { + bundled?: boolean | null; + description?: string | null; + display_name?: string | null; + name: string; + timeout?: number | null; + type: 'builtin'; +} | { + bundled?: boolean | null; + description?: string | null; + display_name?: string | null; + name: string; + type: 'platform'; +} | { + bundled?: boolean | null; + description?: string | null; + envKeys?: Array; + server: McpServer; + socket?: string | null; + timeout?: number | null; + type: 'mcp'; +} | { + code: string; + dependencies?: Array; + description?: string | null; + name: string; + timeout?: number | null; + type: 'inline_python'; +} | { + bundled?: boolean | null; + description?: string | null; + instructions?: string | null; + name: string; + tools?: Array; + type: 'frontend'; +}; -export type ProviderConfigKey = { +export type GooseExtensionEntry = { + configKey?: string | null; + enabled: boolean; + extension: GooseExtension; +}; + +/** + * Call a tool from an extension. + */ +export type GooseToolCallRequest_unstable = { + arguments?: unknown; name: string; - required: boolean; - secret: boolean; - default?: string | null; - oauthFlow?: boolean; - deviceCodeFlow?: boolean; - primary?: boolean; + sessionId: string; }; /** - * A single model in provider inventory. + * Tool call response. */ -export type ProviderInventoryModelDto = { +export type GooseToolCallResponse_unstable = { + _meta?: unknown; + content?: Array; + isError: boolean; + structuredContent?: unknown; +}; + +/** + * An HTTP header to set when making requests to the MCP server. + */ +export type HttpHeader = { /** - * Model identifier as the provider knows it. + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) */ - id: string; + _meta?: { + [key: string]: unknown; + } | null; /** - * Human-readable display name. + * The name of the HTTP header. */ name: string; /** - * Model family for grouping in UI. - */ - family?: string | null; - /** - * Context window size in tokens. - */ - contextLimit?: number | null; - /** - * Whether the model supports reasoning/extended thinking. - */ - reasoning?: boolean | null; - /** - * Whether this model should appear in the compact recommended picker. + * The value to set for the HTTP header. */ - recommended?: boolean; + value: string; }; /** - * List the raw model identifiers returned by a provider's live supported-models API. + * Import a session from a JSON string. */ -export type ProviderSupportedModelsListRequest_unstable = { - providerId: string; +export type ImportSessionRequest_unstable = { + data: string; }; -export type ProviderSupportedModelsListResponse_unstable = { - providerId: string; - models: Array; +/** + * Import session response — metadata about the newly created session. + */ +export type ImportSessionResponse_unstable = { + messageCount: number; + sessionId: string; + title?: string | null; + updatedAt?: string | null; }; /** - * List custom-provider catalog entries. Omit `format` to list all formats. + * Import a source from a JSON export payload produced by `_goose/unstable/sources/export`. + * The imported source is written into the explicit target scope; on name + * collisions a `-imported` suffix is appended. */ -export type ProviderCatalogListRequest_unstable = { - format?: string | null; +export type ImportSourcesRequest_unstable = { + data: string; + target: SourceScope; }; -export type ProviderCatalogListResponse_unstable = { - providers: Array; +export type ImportSourcesResponse_unstable = { + sources: Array; }; -export type ProviderTemplateCatalogEntryDto = { - providerId: string; - name: string; - format: string; - apiUrl: string; - modelCount: number; - docUrl: string; - envVar: string; +/** + * List providers with setup metadata and the current model inventory snapshot. + */ +export type ListProvidersRequest_unstable = { + /** + * Only return entries for these providers. Empty means all. + */ + providerIds?: Array; }; /** - * List provider setup catalog entries + * Provider list response. */ -export type ProviderSetupCatalogListRequest_unstable = { - [key: string]: unknown; +export type ListProvidersResponse_unstable = { + entries: Array; }; -export type ProviderSetupCatalogListResponse_unstable = { - providers: Array; -}; - -export type ProviderSetupCatalogEntryDto = { - providerId: string; - name: string; - category: ProviderSetupCategoryDto; - description: string; - setupMethod: ProviderSetupMethodDto; - nativeConnectQuery?: string | null; - fields?: Array; - binaryName?: string | null; - docUrl?: string | null; - group: ProviderSetupGroupDto; - showOnlyWhenInstalled: boolean; - aliases?: Array; - supportsInstall: boolean; - supportsAuth: boolean; - supportsAuthStatus: boolean; -}; - -export type ProviderSetupMethodDto = 'none' | 'single_api_key' | 'config_fields' | 'host_with_oauth_fallback' | 'oauth_browser' | 'oauth_device_code' | 'cloud_credentials' | 'local' | 'cli_auth'; - -export type ProviderSetupFieldDto = { - key: string; - label: string; - secret: boolean; - required: boolean; - placeholder?: string | null; - defaultValue?: string | null; -}; - -export type ProviderSetupGroupDto = 'default' | 'additional'; - /** - * Return the editable template for one catalog provider. + * List discovered sources. + * + * If `type` is omitted or `skill`, this lists filesystem/plugin skills only. + * Both global and project-scoped skills are included when `project_dir` is + * set. If `type` is `builtinSkill`, this lists shipped read-only built-in + * skills. */ -export type ProviderCatalogTemplateRequest_unstable = { - providerId: string; -}; - -export type ProviderCatalogTemplateResponse_unstable = { - template: ProviderTemplateDto; -}; - -export type ProviderTemplateDto = { - providerId: string; - name: string; - format: string; - apiUrl: string; - models: Array; - supportsStreaming: boolean; - envVar: string; - docUrl: string; -}; - -export type ProviderTemplateModelDto = { - id: string; - name: string; - contextLimit: number; - capabilities: ProviderTemplateCapabilitiesDto; - deprecated: boolean; +export type ListSourcesRequest_unstable = { + /** + * When true, also scan the working directories of all known projects for + * project-scoped sources (e.g. skills stored under `{workingDir}/.agents/skills/`). + */ + includeProjectSources?: boolean; + projectDir?: string | null; + type?: SourceType | null; }; -export type ProviderTemplateCapabilitiesDto = { - toolCall: boolean; - reasoning: boolean; - attachment: boolean; - temperature: boolean; +export type ListSourcesResponse_unstable = { + sources: Array; }; /** - * Create a custom provider backed by Goose's declarative provider store. + * Configuration for connecting to an MCP (Model Context Protocol) server. + * + * MCP servers provide tools and context that the agent can use when + * processing prompts. + * + * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) */ -export type CustomProviderCreateRequest_unstable = { - engine: string; - displayName: string; - apiUrl: string; - apiKey?: string | null; - models?: Array; - supportsStreaming?: boolean | null; - headers?: { - [key: string]: string; - }; - requiresAuth: boolean; - catalogProviderId?: string | null; - basePath?: string | null; - preservesThinking?: boolean | null; -}; - -export type CustomProviderCreateResponse_unstable = { - providerId: string; - status: ProviderConfigStatusDto; - refresh: RefreshProviderInventoryResponse_unstable; -}; - -export type ProviderConfigStatusDto = { - providerId: string; - isConfigured: boolean; -}; +export type McpServer = McpServerHttp | McpServerSse | McpServerStdio; /** - * Refresh acknowledgement. + * HTTP transport configuration for MCP. */ -export type RefreshProviderInventoryResponse_unstable = { +export type McpServerHttp = { /** - * Which providers will be refreshed. + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) */ - started: Array; + _meta?: { + [key: string]: unknown; + } | null; /** - * Which providers were skipped and why. + * HTTP headers to set when making requests to the MCP server. */ - skipped?: Array; -}; - -export type RefreshProviderInventorySkipDto = { - providerId: string; - reason: RefreshProviderInventorySkipReasonDto; -}; - -export type RefreshProviderInventorySkipReasonDto = 'unknown_provider' | 'not_configured' | 'does_not_support_refresh' | 'already_refreshing'; - -/** - * Read a declarative provider config. Custom configs are editable; bundled configs are read-only. - */ -export type CustomProviderReadRequest_unstable = { - providerId: string; -}; - -export type CustomProviderReadResponse_unstable = { - provider: CustomProviderConfigDto; - editable: boolean; - status: ProviderConfigStatusDto; -}; - -export type CustomProviderConfigDto = { - providerId: string; - engine: string; - displayName: string; - apiUrl: string; - models?: Array; - supportsStreaming?: boolean | null; - headers?: { - [key: string]: string; - }; - requiresAuth: boolean; - catalogProviderId?: string | null; - basePath?: string | null; - apiKeyEnv?: string | null; - apiKeySet: boolean; - preservesThinking: boolean; -}; - -/** - * Update a custom provider backed by Goose's declarative provider store. - */ -export type CustomProviderUpdateRequest_unstable = { - providerId: string; - engine: string; - displayName: string; - apiUrl: string; - apiKey?: string | null; - models?: Array; - supportsStreaming?: boolean | null; - headers?: { - [key: string]: string; - }; - requiresAuth: boolean; - catalogProviderId?: string | null; - basePath?: string | null; - preservesThinking?: boolean | null; -}; - -export type CustomProviderUpdateResponse_unstable = { - providerId: string; - status: ProviderConfigStatusDto; - refresh: RefreshProviderInventoryResponse_unstable; + headers: Array; + /** + * Human-readable name identifying this MCP server. + */ + name: string; + type: 'http'; + /** + * URL to the MCP server. + */ + url: string; }; /** - * Delete a custom provider from Goose's declarative provider store. + * SSE transport configuration for MCP. */ -export type CustomProviderDeleteRequest_unstable = { - providerId: string; -}; - -export type CustomProviderDeleteResponse_unstable = { - providerId: string; - refresh: RefreshProviderInventoryResponse_unstable; +export type McpServerSse = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * HTTP headers to set when making requests to the MCP server. + */ + headers: Array; + /** + * Human-readable name identifying this MCP server. + */ + name: string; + type: 'sse'; + /** + * URL to the MCP server. + */ + url: string; }; /** - * Trigger a background refresh of provider inventories. + * Stdio transport configuration for MCP. */ -export type RefreshProviderInventoryRequest_unstable = { +export type McpServerStdio = { /** - * Which providers to refresh. Empty means all known providers. + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * Command-line arguments to pass to the MCP server. + */ + args: Array; + /** + * Path to the MCP server executable. + */ + command: string; + /** + * Environment variables to set when launching the MCP server. + */ + env: Array; + /** + * Human-readable name identifying this MCP server. */ - providerIds?: Array; + name: string; }; /** - * Read saved configuration field values for one provider. + * Import selected onboarding candidates. */ -export type ProviderConfigReadRequest_unstable = { - providerId: string; -}; - -export type ProviderConfigReadResponse_unstable = { - fields: Array; +export type OnboardingImportApplyRequest_unstable = { + candidateIds?: Array; + enableImportedExtensions?: boolean; }; -export type ProviderConfigFieldValueDto = { - key: string; - value?: string | null; - isSet: boolean; - isSecret: boolean; - required: boolean; +export type OnboardingImportApplyResponse_unstable = { + imported: OnboardingImportCounts; + providerDefaults?: DefaultsReadResponse_unstable | null; + skipped: OnboardingImportCounts; + warnings?: Array; }; -/** - * Return provider configured statuses. Empty provider_ids means all providers. - */ -export type ProviderConfigStatusRequest_unstable = { - providerIds?: Array; +export type OnboardingImportCandidate = { + counts: OnboardingImportCounts; + displayName: string; + id: string; + path: string; + sourceKind: OnboardingImportSourceKind; + warnings?: Array; }; -export type ProviderConfigStatusResponse_unstable = { - statuses: Array; +export type OnboardingImportCounts = { + extensions: number; + preferences: number; + projects: number; + providers: number; + sessions: number; + skills: number; }; /** - * Save provider configuration fields and start an inventory refresh when supported. + * Scan for existing Goose and compatible app data that onboarding can import. */ -export type ProviderConfigSaveRequest_unstable = { - providerId: string; - fields: Array; -}; - -export type ProviderConfigFieldUpdate = { - key: string; - value: string; +export type OnboardingImportScanRequest_unstable = { + /** + * Empty means all supported import sources. + */ + sources?: Array; }; -export type ProviderConfigChangeResponse_unstable = { - status: ProviderConfigStatusDto; - refresh: RefreshProviderInventoryResponse_unstable; +export type OnboardingImportScanResponse_unstable = { + candidates: Array; }; /** - * Delete provider configuration fields and start an inventory refresh when supported. + * Sources that onboarding knows how to discover and import. */ -export type ProviderConfigDeleteRequest_unstable = { - providerId: string; -}; +export type OnboardingImportSourceKind = 'goose_config' | 'claude_desktop'; -/** - * Run a provider-owned native authentication flow and start an inventory refresh when supported. - */ -export type ProviderConfigAuthenticateRequest_unstable = { - providerId: string; +export type PreferenceKey = 'autoCompactThreshold' | 'voiceAutoSubmitPhrases' | 'voiceDictationProvider' | 'voiceDictationPreferredMic'; + +export type PreferenceValue = { + key: PreferenceKey; + value?: unknown; }; /** @@ -806,24 +780,10 @@ export type PreferencesReadRequest_unstable = { keys?: Array; }; -export type PreferenceKey = 'autoCompactThreshold' | 'voiceAutoSubmitPhrases' | 'voiceDictationProvider' | 'voiceDictationPreferredMic'; - export type PreferencesReadResponse_unstable = { values: Array; }; -export type PreferenceValue = { - key: PreferenceKey; - value?: unknown; -}; - -/** - * Save allowlisted user preferences. - */ -export type PreferencesSaveRequest_unstable = { - values?: Array; -}; - /** * Remove allowlisted user preferences. */ @@ -832,468 +792,510 @@ export type PreferencesRemoveRequest_unstable = { }; /** - * Read Goose default provider and model configuration. - */ -export type DefaultsReadRequest_unstable = { - [key: string]: unknown; -}; - -export type DefaultsReadResponse_unstable = { - providerId?: string | null; - modelId?: string | null; -}; - -/** - * Save Goose default provider and model configuration. - */ -export type DefaultsSaveRequest_unstable = { - providerId: string; - modelId?: string | null; -}; - -/** - * Scan for existing Goose and compatible app data that onboarding can import. + * Save allowlisted user preferences. */ -export type OnboardingImportScanRequest_unstable = { - /** - * Empty means all supported import sources. - */ - sources?: Array; +export type PreferencesSaveRequest_unstable = { + values?: Array; }; /** - * Sources that onboarding knows how to discover and import. + * List custom-provider catalog entries. Omit `format` to list all formats. */ -export type OnboardingImportSourceKind = 'goose_config' | 'claude_desktop'; - -export type OnboardingImportScanResponse_unstable = { - candidates: Array; -}; - -export type OnboardingImportCandidate = { - id: string; - sourceKind: OnboardingImportSourceKind; - displayName: string; - path: string; - counts: OnboardingImportCounts; - warnings?: Array; +export type ProviderCatalogListRequest_unstable = { + format?: string | null; }; -export type OnboardingImportCounts = { - providers: number; - extensions: number; - sessions: number; - skills: number; - projects: number; - preferences: number; +export type ProviderCatalogListResponse_unstable = { + providers: Array; }; /** - * Import selected onboarding candidates. + * Return the editable template for one catalog provider. */ -export type OnboardingImportApplyRequest_unstable = { - candidateIds?: Array; - enableImportedExtensions?: boolean; +export type ProviderCatalogTemplateRequest_unstable = { + providerId: string; }; -export type OnboardingImportApplyResponse_unstable = { - imported: OnboardingImportCounts; - skipped: OnboardingImportCounts; - warnings?: Array; - providerDefaults?: DefaultsReadResponse_unstable | null; +export type ProviderCatalogTemplateResponse_unstable = { + template: ProviderTemplateDto; }; /** - * Export a session as a JSON string. + * Run a provider-owned native authentication flow and start an inventory refresh when supported. */ -export type ExportSessionRequest_unstable = { - sessionId: string; +export type ProviderConfigAuthenticateRequest_unstable = { + providerId: string; }; -/** - * Export session response — raw JSON of the goose session with `conversation`. - */ -export type ExportSessionResponse_unstable = { - data: string; +export type ProviderConfigChangeResponse_unstable = { + refresh: RefreshProviderInventoryResponse_unstable; + status: ProviderConfigStatusDto; }; /** - * Import a session from a JSON string. + * Delete provider configuration fields and start an inventory refresh when supported. */ -export type ImportSessionRequest_unstable = { - data: string; +export type ProviderConfigDeleteRequest_unstable = { + providerId: string; }; -/** - * Import session response — metadata about the newly created session. - */ -export type ImportSessionResponse_unstable = { - sessionId: string; - title?: string | null; - updatedAt?: string | null; - messageCount: number; +export type ProviderConfigFieldUpdate = { + key: string; + value: string; }; -/** - * Update the project association for a session. - */ -export type UpdateSessionProjectRequest_unstable = { - sessionId: string; - projectId?: string | null; +export type ProviderConfigFieldValueDto = { + isSecret: boolean; + isSet: boolean; + key: string; + required: boolean; + value?: string | null; }; -/** - * Rename a session. - */ -export type RenameSessionRequest_unstable = { - sessionId: string; - title: string; +export type ProviderConfigKey = { + default?: string | null; + deviceCodeFlow?: boolean; + name: string; + oauthFlow?: boolean; + primary?: boolean; + required: boolean; + secret: boolean; }; /** - * Archive a session (soft delete). + * Read saved configuration field values for one provider. */ -export type ArchiveSessionRequest_unstable = { - sessionId: string; +export type ProviderConfigReadRequest_unstable = { + providerId: string; }; -/** - * Unarchive a previously archived session. - */ -export type UnarchiveSessionRequest_unstable = { - sessionId: string; +export type ProviderConfigReadResponse_unstable = { + fields: Array; }; /** - * Create a new source in an explicit target scope (global or project-scoped). + * Save provider configuration fields and start an inventory refresh when supported. */ -export type CreateSourceRequest_unstable = { - type: SourceType; - name: string; - description: string; - content: string; - target: SourceScope; - /** - * Arbitrary key/value metadata. - */ - properties?: { - [key: string]: unknown; - }; +export type ProviderConfigSaveRequest_unstable = { + fields: Array; + providerId: string; }; -/** - * The type of source entity. - */ -export type SourceType = 'skill' | 'builtinSkill' | 'recipe' | 'subrecipe' | 'agent' | 'project'; +export type ProviderConfigStatusDto = { + isConfigured: boolean; + providerId: string; +}; /** - * Target scope for creating or importing sources. + * Return provider configured statuses. Empty provider_ids means all providers. */ -export type SourceScope = { - scope: 'global'; -} | { - projectDir: string; - scope: 'projectDir'; -} | { - projectId: string; - scope: 'projectId'; +export type ProviderConfigStatusRequest_unstable = { + providerIds?: Array; }; -export type CreateSourceResponse_unstable = { - source: SourceEntry; +export type ProviderConfigStatusResponse_unstable = { + statuses: Array; }; /** - * A source discovered by Goose. Filesystem sources use an on-disk path; - * built-in sources use a stable synthetic path. Sources may be either - * `global` (shared across all projects) or project-specific. + * Provider inventory entry. */ -export type SourceEntry = { - type: SourceType; - name: string; +export type ProviderInventoryEntryDto = { + /** + * Whether this inventory entry represents an agent provider or a model provider. + */ + category: ProviderSetupCategoryDto; + /** + * Required configuration keys and setup metadata. + */ + configKeys: Array; + /** + * Whether Goose has enough configuration to use this provider. + */ + configured: boolean; + /** + * The default/recommended model for this provider. + */ + defaultModel: string; + /** + * Description of the provider's capabilities. + */ description: string; - content: string; /** - * Stable on-disk path identifying this source. Pass it back to - * update/delete/export to operate on this entry. Skills use the directory - * containing `SKILL.md`; projects use the project file path; built-in - * skills use `builtin://skills/` synthetic paths. + * When a refresh was most recently attempted (ISO 8601). */ - path: string; + lastRefreshAttemptAt?: string | null; /** - * True when the source lives in the user's global sources directory; false - * when it lives inside a specific project. + * The last refresh failure message, if any. */ - global: boolean; + lastRefreshError?: string | null; /** - * True when this source can be modified through source CRUD methods. - * Client-provided bundled sources are returned as read-only. + * When this entry was last successfully refreshed (ISO 8601). */ - writable?: boolean; + lastUpdatedAt?: string | null; /** - * Paths (absolute) of additional files that live alongside the source. - * Only skills currently populate this; empty for other source types. + * Guidance message shown when this provider manages its own model selection externally. */ - supportingFiles?: Array; + modelSelectionHint?: string | null; /** - * Arbitrary key/value pairs for type-specific metadata (e.g. icon, color, - * preferredProvider for projects). Stored in the frontmatter. + * The list of available models. */ - properties?: { - [key: string]: unknown; - }; + models: Array; + /** + * Provider identifier. + */ + providerId: string; + /** + * Human-readable provider name. + */ + providerName: string; + /** + * Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`. + */ + providerType: string; + /** + * Whether a refresh is currently in flight. + */ + refreshing: boolean; + /** + * Step-by-step setup instructions, when present. + */ + setupSteps: Array; + /** + * Whether we believe this data may be outdated. + */ + stale: boolean; + /** + * Whether this provider supports background inventory refresh. + */ + supportsRefresh: boolean; }; /** - * List discovered sources. - * - * If `type` is omitted or `skill`, this lists filesystem/plugin skills only. - * Both global and project-scoped skills are included when `project_dir` is - * set. If `type` is `builtinSkill`, this lists shipped read-only built-in - * skills. + * A single model in provider inventory. */ -export type ListSourcesRequest_unstable = { - type?: SourceType | null; - projectDir?: string | null; +export type ProviderInventoryModelDto = { /** - * When true, also scan the working directories of all known projects for - * project-scoped sources (e.g. skills stored under `{workingDir}/.agents/skills/`). + * Context window size in tokens. */ - includeProjectSources?: boolean; + contextLimit?: number | null; + /** + * Model family for grouping in UI. + */ + family?: string | null; + /** + * Model identifier as the provider knows it. + */ + id: string; + /** + * Human-readable display name. + */ + name: string; + /** + * Whether the model supports reasoning/extended thinking. + */ + reasoning?: boolean | null; + /** + * Whether this model should appear in the compact recommended picker. + */ + recommended?: boolean; }; -export type ListSourcesResponse_unstable = { - sources: Array; +export type ProviderSetupCatalogEntryDto = { + aliases?: Array; + binaryName?: string | null; + category: ProviderSetupCategoryDto; + description: string; + docUrl?: string | null; + fields?: Array; + group: ProviderSetupGroupDto; + name: string; + nativeConnectQuery?: string | null; + providerId: string; + setupMethod: ProviderSetupMethodDto; + showOnlyWhenInstalled: boolean; + supportsAuth: boolean; + supportsAuthStatus: boolean; + supportsInstall: boolean; }; /** - * Update an existing source's name, description, and content by absolute path. + * List provider setup catalog entries */ -export type UpdateSourceRequest_unstable = { - type: SourceType; - path: string; - name: string; - description: string; - content: string; - /** - * When `Some`, replaces all stored properties on the source. When - * `None` (or omitted), the source's existing properties are - * preserved. Callers that don't model the full property bag (e.g. - * the skills editor, which only edits name/description/content) - * should omit this so per-skill metadata isn't silently erased. - */ - properties?: { - [key: string]: unknown; - } | null; +export type ProviderSetupCatalogListRequest_unstable = { + [key: string]: unknown; }; -export type UpdateSourceResponse_unstable = { - source: SourceEntry; +export type ProviderSetupCatalogListResponse_unstable = { + providers: Array; }; -/** - * Delete a source and its on-disk directory by absolute path. - */ -export type DeleteSourceRequest_unstable = { - type: SourceType; - path: string; +export type ProviderSetupCategoryDto = 'agent' | 'model'; + +export type ProviderSetupFieldDto = { + defaultValue?: string | null; + key: string; + label: string; + placeholder?: string | null; + required: boolean; + secret: boolean; }; +export type ProviderSetupGroupDto = 'default' | 'additional'; + +export type ProviderSetupMethodDto = 'none' | 'single_api_key' | 'config_fields' | 'host_with_oauth_fallback' | 'oauth_browser' | 'oauth_device_code' | 'cloud_credentials' | 'local' | 'cli_auth'; + /** - * Export a source at an absolute path as a portable JSON payload. + * List the raw model identifiers returned by a provider's live supported-models API. */ -export type ExportSourceRequest_unstable = { - type: SourceType; - path: string; +export type ProviderSupportedModelsListRequest_unstable = { + providerId: string; }; -export type ExportSourceResponse_unstable = { - json: string; - filename: string; +export type ProviderSupportedModelsListResponse_unstable = { + models: Array; + providerId: string; +}; + +export type ProviderTemplateCapabilitiesDto = { + attachment: boolean; + reasoning: boolean; + temperature: boolean; + toolCall: boolean; +}; + +export type ProviderTemplateCatalogEntryDto = { + apiUrl: string; + docUrl: string; + envVar: string; + format: string; + modelCount: number; + name: string; + providerId: string; +}; + +export type ProviderTemplateDto = { + apiUrl: string; + docUrl: string; + envVar: string; + format: string; + models: Array; + name: string; + providerId: string; + supportsStreaming: boolean; +}; + +export type ProviderTemplateModelDto = { + capabilities: ProviderTemplateCapabilitiesDto; + contextLimit: number; + deprecated: boolean; + id: string; + name: string; +}; + +/** + * Read a resource from an extension. + */ +export type ReadResourceRequest_unstable = { + extensionName: string; + sessionId: string; + uri: string; }; /** - * Import a source from a JSON export payload produced by `_goose/unstable/sources/export`. - * The imported source is written into the explicit target scope; on name - * collisions a `-imported` suffix is appended. + * Resource read response. */ -export type ImportSourcesRequest_unstable = { - data: string; - target: SourceScope; -}; - -export type ImportSourcesResponse_unstable = { - sources: Array; +export type ReadResourceResponse_unstable = { + /** + * The resource result from the extension (MCP ReadResourceResult). + */ + result?: unknown; }; /** - * Transcribe audio via a dictation provider. + * Trigger a background refresh of provider inventories. */ -export type DictationTranscribeRequest_unstable = { +export type RefreshProviderInventoryRequest_unstable = { /** - * Base64-encoded audio data + * Which providers to refresh. Empty means all known providers. */ - audio: string; + providerIds?: Array; +}; + +/** + * Refresh acknowledgement. + */ +export type RefreshProviderInventoryResponse_unstable = { /** - * MIME type (e.g. "audio/wav", "audio/webm") + * Which providers were skipped and why. */ - mimeType: string; + skipped?: Array; /** - * Provider to use: "openai", "groq", "elevenlabs", or "local" + * Which providers will be refreshed. */ - provider: string; + started: Array; }; -/** - * Transcription result. - */ -export type DictationTranscribeResponse_unstable = { - text: string; +export type RefreshProviderInventorySkipDto = { + providerId: string; + reason: RefreshProviderInventorySkipReasonDto; }; -/** - * Get the configuration status of all dictation providers. - */ -export type DictationConfigRequest_unstable = { - [key: string]: unknown; -}; +export type RefreshProviderInventorySkipReasonDto = 'unknown_provider' | 'not_configured' | 'does_not_support_refresh' | 'already_refreshing'; /** - * Dictation config response — map of provider name to status. + * Remove a persisted extension from the user's global goose config. */ -export type DictationConfigResponse_unstable = { - providers: { - [key: string]: DictationProviderStatusEntry; - }; +export type RemoveConfigExtensionRequest_unstable = { + configKey: string; }; /** - * Per-provider configuration status. + * Remove an extension from an active session. */ -export type DictationProviderStatusEntry = { - configured: boolean; - host?: string | null; - description: string; - usesProviderConfig: boolean; - settingsPath?: string | null; - configKey?: string | null; - modelConfigKey?: string | null; - defaultModel?: string | null; - selectedModel?: string | null; - availableModels?: Array; -}; - -export type DictationModelOption = { - id: string; - label: string; - description: string; +export type RemoveExtensionRequest_unstable = { + name: string; + sessionId: string; }; /** - * Set a dictation provider secret value. + * Rename a session. */ -export type DictationSecretSaveRequest_unstable = { - provider: string; - value: string; +export type RenameSessionRequest_unstable = { + sessionId: string; + title: string; }; /** - * Remove a dictation provider secret value. + * How a session system prompt update should be applied. */ -export type DictationSecretDeleteRequest_unstable = { - provider: string; -}; +export type SessionSystemPromptMode = 'set' | 'append'; /** - * List available local Whisper models with their download status. + * Set the `enabled` flag for a persisted extension in the user's global goose config. */ -export type DictationModelsListRequest_unstable = { - [key: string]: unknown; -}; - -export type DictationModelsListResponse_unstable = { - models: Array; -}; - -export type DictationLocalModelStatus = { - id: string; - label: string; - description: string; - sizeMb: number; - downloaded: boolean; - downloadInProgress: boolean; +export type SetConfigExtensionEnabledRequest_unstable = { + configKey: string; + enabled: boolean; }; /** - * Kick off a background download of a local Whisper model. + * Set, append, or clear system prompt text for a session. + * + * `mode: "set"` replaces Goose's base system prompt. `mode: "append"` adds an + * instruction under "Additional Instructions". Reusing a key replaces the + * previous value for that mode/key; sending empty text clears it. */ -export type DictationModelDownloadRequest_unstable = { - modelId: string; +export type SetSessionSystemPromptRequest_unstable = { + key?: string | null; + mode?: SessionSystemPromptMode; + sessionId: string; + text: string; }; /** - * Poll the progress of an in-flight download. + * A source discovered by Goose. Filesystem sources use an on-disk path; + * built-in sources use a stable synthetic path. Sources may be either + * `global` (shared across all projects) or project-specific. */ -export type DictationModelDownloadProgressRequest_unstable = { - modelId: string; -}; - -export type DictationModelDownloadProgressResponse_unstable = { +export type SourceEntry = { + content: string; + description: string; /** - * None when no download is active for this model id. + * True when the source lives in the user's global sources directory; false + * when it lives inside a specific project. */ - progress?: DictationDownloadProgress | null; -}; - -export type DictationDownloadProgress = { - bytesDownloaded: number; - totalBytes: number; - progressPercent: number; + global: boolean; + name: string; /** - * serde lowercase of DownloadStatus: "downloading" | "completed" | "failed" | "cancelled" + * Stable on-disk path identifying this source. Pass it back to + * update/delete/export to operate on this entry. Skills use the directory + * containing `SKILL.md`; projects use the project file path; built-in + * skills use `builtin://skills/` synthetic paths. */ - status: string; - error?: string | null; + path: string; + /** + * Arbitrary key/value pairs for type-specific metadata (e.g. icon, color, + * preferredProvider for projects). Stored in the frontmatter. + */ + properties?: { + [key: string]: unknown; + }; + /** + * Paths (absolute) of additional files that live alongside the source. + * Only skills currently populate this; empty for other source types. + */ + supportingFiles?: Array; + type: SourceType; + /** + * True when this source can be modified through source CRUD methods. + * Client-provided bundled sources are returned as read-only. + */ + writable?: boolean; }; /** - * Cancel an in-flight download. + * Target scope for creating or importing sources. */ -export type DictationModelCancelRequest_unstable = { - modelId: string; +export type SourceScope = { + scope: 'global'; +} | { + projectDir: string; + scope: 'projectDir'; +} | { + projectId: string; + scope: 'projectId'; }; /** - * Delete a downloaded local Whisper model from disk. + * The type of source entity. */ -export type DictationModelDeleteRequest_unstable = { - modelId: string; +export type SourceType = 'skill' | 'builtinSkill' | 'recipe' | 'subrecipe' | 'agent' | 'project'; + +/** + * Unarchive a previously archived session. + */ +export type UnarchiveSessionRequest_unstable = { + sessionId: string; }; /** - * Persist the user's model selection for a given provider. + * Update the project association for a session. */ -export type DictationModelSelectRequest_unstable = { - provider: string; - modelId: string; +export type UpdateSessionProjectRequest_unstable = { + projectId?: string | null; + sessionId: string; }; -export type ExtRequest = { - id: string; - method: string; - params?: AddExtensionRequest_unstable | RemoveExtensionRequest_unstable | GetToolsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | DeleteSessionRequest | GetConfigExtensionsRequest_unstable | GetAvailableExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | SetConfigExtensionEnabledRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | { +/** + * Update an existing source's name, description, and content by absolute path. + */ +export type UpdateSourceRequest_unstable = { + content: string; + description: string; + name: string; + path: string; + /** + * When `Some`, replaces all stored properties on the source. When + * `None` (or omitted), the source's existing properties are + * preserved. Callers that don't model the full property bag (e.g. + * the skills editor, which only edits name/description/content) + * should omit this so per-skill metadata isn't silently erased. + */ + properties?: { [key: string]: unknown; } | null; + type: SourceType; }; -export type ExtResponse = { - id: string; - result?: EmptyResponse | GetToolsResponse_unstable | GooseToolCallResponse_unstable | ReadResourceResponse_unstable | GetConfigExtensionsResponse_unstable | GetAvailableExtensionsResponse_unstable | GetSessionExtensionsResponse_unstable | ListProvidersResponse_unstable | ProviderSupportedModelsListResponse_unstable | ProviderCatalogListResponse_unstable | ProviderSetupCatalogListResponse_unstable | ProviderCatalogTemplateResponse_unstable | CustomProviderCreateResponse_unstable | CustomProviderReadResponse_unstable | CustomProviderUpdateResponse_unstable | CustomProviderDeleteResponse_unstable | RefreshProviderInventoryResponse_unstable | ProviderConfigReadResponse_unstable | ProviderConfigStatusResponse_unstable | ProviderConfigChangeResponse_unstable | PreferencesReadResponse_unstable | DefaultsReadResponse_unstable | OnboardingImportScanResponse_unstable | OnboardingImportApplyResponse_unstable | ExportSessionResponse_unstable | ImportSessionResponse_unstable | CreateSourceResponse_unstable | ListSourcesResponse_unstable | UpdateSourceResponse_unstable | ExportSourceResponse_unstable | ImportSourcesResponse_unstable | DictationTranscribeResponse_unstable | DictationConfigResponse_unstable | DictationModelsListResponse_unstable | DictationModelDownloadProgressResponse_unstable | unknown; -} | { - error: { - code: number; - message: string; - data?: unknown; - }; - id: string; +export type UpdateSourceResponse_unstable = { + source: SourceEntry; +}; + +/** + * Update the working directory for a session. + */ +export type UpdateWorkingDirRequest_unstable = { + sessionId: string; + workingDir: string; }; diff --git a/ui/sdk/src/generated/zod.gen.ts b/ui/sdk/src/generated/zod.gen.ts index aad31ca1f8e5..9f0817213da5 100644 --- a/ui/sdk/src/generated/zod.gen.ts +++ b/ui/sdk/src/generated/zod.gen.ts @@ -6,335 +6,359 @@ import { z } from 'zod'; * Add an extension to an active session. */ export const zAddExtensionRequest_unstable = z.object({ - sessionId: z.string(), - config: z.unknown().optional().default(null) + config: z.unknown().optional().default(null), + sessionId: z.string() }); /** - * Empty success response for operations that return no data. + * Archive a session (soft delete). */ -export const zEmptyResponse = z.record(z.unknown()); +export const zArchiveSessionRequest_unstable = z.object({ + sessionId: z.string() +}); -/** - * Remove an extension from an active session. - */ -export const zRemoveExtensionRequest_unstable = z.object({ - sessionId: z.string(), - name: z.string() +export const zCustomProviderConfigDto = z.object({ + apiKeyEnv: z.union([ + z.string(), + z.null() + ]).optional(), + apiKeySet: z.boolean(), + apiUrl: z.string(), + basePath: z.union([ + z.string(), + z.null() + ]).optional(), + catalogProviderId: z.union([ + z.string(), + z.null() + ]).optional(), + displayName: z.string(), + engine: z.string(), + headers: z.record(z.string()).optional().default({}), + models: z.array(z.string()).optional().default([]), + preservesThinking: z.boolean(), + providerId: z.string(), + requiresAuth: z.boolean(), + supportsStreaming: z.union([ + z.boolean(), + z.null() + ]).optional() }); /** - * List all tools available in a session. + * Create a custom provider backed by Goose's declarative provider store. */ -export const zGetToolsRequest_unstable = z.object({ - sessionId: z.string() +export const zCustomProviderCreateRequest_unstable = z.object({ + apiKey: z.union([ + z.string(), + z.null() + ]).optional(), + apiUrl: z.string(), + basePath: z.union([ + z.string(), + z.null() + ]).optional(), + catalogProviderId: z.union([ + z.string(), + z.null() + ]).optional(), + displayName: z.string(), + engine: z.string(), + headers: z.record(z.string()).optional().default({}), + models: z.array(z.string()).optional().default([]), + preservesThinking: z.union([ + z.boolean(), + z.null() + ]).optional(), + requiresAuth: z.boolean(), + supportsStreaming: z.union([ + z.boolean(), + z.null() + ]).optional() }); /** - * Tools response. + * Delete a custom provider from Goose's declarative provider store. */ -export const zGetToolsResponse_unstable = z.object({ - tools: z.array(z.unknown()) +export const zCustomProviderDeleteRequest_unstable = z.object({ + providerId: z.string() }); /** - * Call a tool from an extension. + * Read a declarative provider config. Custom configs are editable; bundled configs are read-only. */ -export const zGooseToolCallRequest_unstable = z.object({ - sessionId: z.string(), - name: z.string(), - arguments: z.unknown().optional().default(null) +export const zCustomProviderReadRequest_unstable = z.object({ + providerId: z.string() }); /** - * Tool call response. + * Update a custom provider backed by Goose's declarative provider store. */ -export const zGooseToolCallResponse_unstable = z.object({ - content: z.array(z.unknown()).optional().default([]), - structuredContent: z.unknown().optional(), - isError: z.boolean(), - _meta: z.unknown().optional() +export const zCustomProviderUpdateRequest_unstable = z.object({ + apiKey: z.union([ + z.string(), + z.null() + ]).optional(), + apiUrl: z.string(), + basePath: z.union([ + z.string(), + z.null() + ]).optional(), + catalogProviderId: z.union([ + z.string(), + z.null() + ]).optional(), + displayName: z.string(), + engine: z.string(), + headers: z.record(z.string()).optional().default({}), + models: z.array(z.string()).optional().default([]), + preservesThinking: z.union([ + z.boolean(), + z.null() + ]).optional(), + providerId: z.string(), + requiresAuth: z.boolean(), + supportsStreaming: z.union([ + z.boolean(), + z.null() + ]).optional() }); /** - * Read a resource from an extension. + * Read Goose default provider and model configuration. */ -export const zReadResourceRequest_unstable = z.object({ - sessionId: z.string(), - uri: z.string(), - extensionName: z.string() +export const zDefaultsReadRequest_unstable = z.record(z.unknown()); + +export const zDefaultsReadResponse_unstable = z.object({ + modelId: z.union([ + z.string(), + z.null() + ]).optional(), + providerId: z.union([ + z.string(), + z.null() + ]).optional() }); /** - * Resource read response. + * Save Goose default provider and model configuration. */ -export const zReadResourceResponse_unstable = z.object({ - result: z.unknown().optional().default(null) +export const zDefaultsSaveRequest_unstable = z.object({ + modelId: z.union([ + z.string(), + z.null() + ]).optional(), + providerId: z.string() }); /** - * Update the working directory for a session. + * Delete a session. */ -export const zUpdateWorkingDirRequest_unstable = z.object({ - sessionId: z.string(), - workingDir: z.string() +export const zDeleteSessionRequest = z.object({ + sessionId: z.string() }); /** - * How a session system prompt update should be applied. + * Get the configuration status of all dictation providers. */ -export const zSessionSystemPromptMode = z.union([ - z.literal('set'), - z.literal('append') -]); +export const zDictationConfigRequest_unstable = z.record(z.unknown()); -/** - * Set, append, or clear system prompt text for a session. - * - * `mode: "set"` replaces Goose's base system prompt. `mode: "append"` adds an - * instruction under "Additional Instructions". Reusing a key replaces the - * previous value for that mode/key; sending empty text clears it. - */ -export const zSetSessionSystemPromptRequest_unstable = z.object({ - sessionId: z.string(), - mode: zSessionSystemPromptMode.optional().default('append'), - key: z.union([ +export const zDictationDownloadProgress = z.object({ + bytesDownloaded: z.number().int().gte(0), + error: z.union([ z.string(), z.null() ]).optional(), - text: z.string() + progressPercent: z.number(), + status: z.string(), + totalBytes: z.number().int().gte(0) }); -/** - * Delete a session. - */ -export const zDeleteSessionRequest = z.object({ - sessionId: z.string() +export const zDictationLocalModelStatus = z.object({ + description: z.string(), + downloadInProgress: z.boolean(), + downloaded: z.boolean(), + id: z.string(), + label: z.string(), + sizeMb: z.number().int().gte(0) }); /** - * List configured extensions and any warnings. + * Cancel an in-flight download. */ -export const zGetConfigExtensionsRequest_unstable = z.record(z.unknown()); +export const zDictationModelCancelRequest_unstable = z.object({ + modelId: z.string() +}); /** - * An HTTP header to set when making requests to the MCP server. + * Delete a downloaded local Whisper model from disk. */ -export const zHttpHeader = z.object({ - name: z.string(), - value: z.string(), - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional() +export const zDictationModelDeleteRequest_unstable = z.object({ + modelId: z.string() }); /** - * HTTP transport configuration for MCP. + * Poll the progress of an in-flight download. */ -export const zMcpServerHttp = z.object({ - name: z.string(), - url: z.string(), - headers: z.array(zHttpHeader), - _meta: z.union([ - z.record(z.unknown()), +export const zDictationModelDownloadProgressRequest_unstable = z.object({ + modelId: z.string() +}); + +export const zDictationModelDownloadProgressResponse_unstable = z.object({ + progress: z.union([ + zDictationDownloadProgress, z.null() ]).optional() }); /** - * SSE transport configuration for MCP. + * Kick off a background download of a local Whisper model. */ -export const zMcpServerSse = z.object({ - name: z.string(), - url: z.string(), - headers: z.array(zHttpHeader), - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional() +export const zDictationModelDownloadRequest_unstable = z.object({ + modelId: z.string() +}); + +export const zDictationModelOption = z.object({ + description: z.string(), + id: z.string(), + label: z.string() }); /** - * An environment variable to set when launching an MCP server. + * Persist the user's model selection for a given provider. */ -export const zEnvVariable = z.object({ - name: z.string(), - value: z.string(), - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional() +export const zDictationModelSelectRequest_unstable = z.object({ + modelId: z.string(), + provider: z.string() }); /** - * Stdio transport configuration for MCP. + * List available local Whisper models with their download status. */ -export const zMcpServerStdio = z.object({ - name: z.string(), - command: z.string(), - args: z.array(z.string()), - env: z.array(zEnvVariable), - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional() +export const zDictationModelsListRequest_unstable = z.record(z.unknown()); + +export const zDictationModelsListResponse_unstable = z.object({ + models: z.array(zDictationLocalModelStatus) }); /** - * Configuration for connecting to an MCP (Model Context Protocol) server. - * - * MCP servers provide tools and context that the agent can use when - * processing prompts. - * - * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) + * Per-provider configuration status. */ -export const zMcpServer = z.union([ - zMcpServerHttp, - zMcpServerSse, - zMcpServerStdio -]); - -export const zGooseExtension = z.union([ - z.object({ - name: z.string(), - description: z.union([ - z.string(), - z.null() - ]).optional(), - display_name: z.union([ - z.string(), - z.null() - ]).optional(), - timeout: z.union([ - z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), - z.null() - ]).optional(), - bundled: z.union([ - z.boolean(), - z.null() - ]).optional(), - type: z.literal('builtin') - }), - z.object({ - name: z.string(), - description: z.union([ - z.string(), - z.null() - ]).optional(), - display_name: z.union([ - z.string(), - z.null() - ]).optional(), - bundled: z.union([ - z.boolean(), - z.null() - ]).optional(), - type: z.literal('platform') - }), - z.object({ - server: zMcpServer, - envKeys: z.array(z.string()).optional(), - description: z.union([ - z.string(), - z.null() - ]).optional(), - timeout: z.union([ - z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), - z.null() - ]).optional(), - socket: z.union([ - z.string(), - z.null() - ]).optional(), - bundled: z.union([ - z.boolean(), - z.null() - ]).optional(), - type: z.literal('mcp') - }), - z.object({ - name: z.string(), - description: z.union([ - z.string(), - z.null() - ]).optional(), - code: z.string(), - timeout: z.union([ - z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), - z.null() - ]).optional(), - dependencies: z.array(z.string()).optional(), - type: z.literal('inline_python') - }), - z.object({ - name: z.string(), - description: z.union([ - z.string(), - z.null() - ]).optional(), - tools: z.array(z.unknown()).optional(), - instructions: z.union([ - z.string(), - z.null() - ]).optional(), - bundled: z.union([ - z.boolean(), - z.null() - ]).optional(), - type: z.literal('frontend') - }) -]); - -export const zGooseExtensionEntry = z.object({ - extension: zGooseExtension, - enabled: z.boolean(), +export const zDictationProviderStatusEntry = z.object({ + availableModels: z.array(zDictationModelOption).optional().default([]), configKey: z.union([ z.string(), z.null() - ]).optional() + ]).optional(), + configured: z.boolean(), + defaultModel: z.union([ + z.string(), + z.null() + ]).optional(), + description: z.string(), + host: z.union([ + z.string(), + z.null() + ]).optional(), + modelConfigKey: z.union([ + z.string(), + z.null() + ]).optional(), + selectedModel: z.union([ + z.string(), + z.null() + ]).optional(), + settingsPath: z.union([ + z.string(), + z.null() + ]).optional(), + usesProviderConfig: z.boolean() }); /** - * List configured extensions and any warnings. + * Dictation config response — map of provider name to status. */ -export const zGetConfigExtensionsResponse_unstable = z.object({ - extensions: z.array(zGooseExtensionEntry), - warnings: z.array(z.string()).optional().default([]) +export const zDictationConfigResponse_unstable = z.object({ + providers: z.record(zDictationProviderStatusEntry) }); /** - * List Goose-owned extension definitions available to configure or enable. + * Remove a dictation provider secret value. */ -export const zGetAvailableExtensionsRequest_unstable = z.record(z.unknown()); +export const zDictationSecretDeleteRequest_unstable = z.object({ + provider: z.string() +}); -export const zGetAvailableExtensionsResponse_unstable = z.object({ - extensions: z.array(zGooseExtension) +/** + * Set a dictation provider secret value. + */ +export const zDictationSecretSaveRequest_unstable = z.object({ + provider: z.string(), + value: z.string() }); /** - * Persist a new extension to the user's global goose config. + * Transcribe audio via a dictation provider. */ -export const zAddConfigExtensionRequest_unstable = z.object({ - extension: zGooseExtension, - enabled: z.boolean().optional().default(false) +export const zDictationTranscribeRequest_unstable = z.object({ + audio: z.string(), + mimeType: z.string(), + provider: z.string() }); /** - * Remove a persisted extension from the user's global goose config. + * Transcription result. */ -export const zRemoveConfigExtensionRequest_unstable = z.object({ - configKey: z.string() +export const zDictationTranscribeResponse_unstable = z.object({ + text: z.string() }); /** - * Set the `enabled` flag for a persisted extension in the user's global goose config. + * Empty success response for operations that return no data. */ -export const zSetConfigExtensionEnabledRequest_unstable = z.object({ - configKey: z.string(), - enabled: z.boolean() +export const zEmptyResponse = z.record(z.unknown()); + +/** + * An environment variable to set when launching an MCP server. + */ +export const zEnvVariable = z.object({ + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional(), + name: z.string(), + value: z.string() }); +/** + * Export a session as a JSON string. + */ +export const zExportSessionRequest_unstable = z.object({ + sessionId: z.string() +}); + +/** + * Export session response — raw JSON of the goose session with `conversation`. + */ +export const zExportSessionResponse_unstable = z.object({ + data: z.string() +}); + +export const zExportSourceResponse_unstable = z.object({ + filename: z.string(), + json: z.string() +}); + +/** + * List Goose-owned extension definitions available to configure or enable. + */ +export const zGetAvailableExtensionsRequest_unstable = z.record(z.unknown()); + +/** + * List configured extensions and any warnings. + */ +export const zGetConfigExtensionsRequest_unstable = z.record(z.unknown()); + export const zGetSessionExtensionsRequest_unstable = z.object({ sessionId: z.string() }); @@ -344,410 +368,433 @@ export const zGetSessionExtensionsResponse_unstable = z.object({ }); /** - * List providers with setup metadata and the current model inventory snapshot. + * List all tools available in a session. */ -export const zListProvidersRequest_unstable = z.object({ - providerIds: z.array(z.string()).optional().default([]) +export const zGetToolsRequest_unstable = z.object({ + sessionId: z.string() }); -export const zProviderSetupCategoryDto = z.enum(['agent', 'model']); +/** + * Tools response. + */ +export const zGetToolsResponse_unstable = z.object({ + tools: z.array(z.unknown()) +}); -export const zProviderConfigKey = z.object({ +/** + * Call a tool from an extension. + */ +export const zGooseToolCallRequest_unstable = z.object({ + arguments: z.unknown().optional().default(null), name: z.string(), - required: z.boolean(), - secret: z.boolean(), - default: z.union([ - z.string(), - z.null() - ]).optional().default(null), - oauthFlow: z.boolean().optional().default(false), - deviceCodeFlow: z.boolean().optional().default(false), - primary: z.boolean().optional().default(false) + sessionId: z.string() }); /** - * A single model in provider inventory. + * Tool call response. */ -export const zProviderInventoryModelDto = z.object({ - id: z.string(), - name: z.string(), - family: z.union([ - z.string(), - z.null() - ]).optional(), - contextLimit: z.union([ - z.number().int().gte(0), - z.null() - ]).optional(), - reasoning: z.union([ - z.boolean(), - z.null() - ]).optional(), - recommended: z.boolean().optional().default(false) +export const zGooseToolCallResponse_unstable = z.object({ + _meta: z.unknown().optional(), + content: z.array(z.unknown()).optional().default([]), + isError: z.boolean(), + structuredContent: z.unknown().optional() }); /** - * Provider inventory entry. + * An HTTP header to set when making requests to the MCP server. */ -export const zProviderInventoryEntryDto = z.object({ - providerId: z.string(), - providerName: z.string(), - description: z.string(), - defaultModel: z.string(), - configured: z.boolean(), - providerType: z.string(), - category: zProviderSetupCategoryDto, - configKeys: z.array(zProviderConfigKey), - setupSteps: z.array(z.string()), - supportsRefresh: z.boolean(), - refreshing: z.boolean(), - models: z.array(zProviderInventoryModelDto), - lastUpdatedAt: z.union([ - z.string(), - z.null() - ]).optional(), - lastRefreshAttemptAt: z.union([ - z.string(), +export const zHttpHeader = z.object({ + _meta: z.union([ + z.record(z.unknown()), z.null() ]).optional(), - lastRefreshError: z.union([ + name: z.string(), + value: z.string() +}); + +/** + * Import a session from a JSON string. + */ +export const zImportSessionRequest_unstable = z.object({ + data: z.string() +}); + +/** + * Import session response — metadata about the newly created session. + */ +export const zImportSessionResponse_unstable = z.object({ + messageCount: z.number().int().gte(0), + sessionId: z.string(), + title: z.union([ z.string(), z.null() ]).optional(), - stale: z.boolean(), - modelSelectionHint: z.union([ + updatedAt: z.union([ z.string(), z.null() ]).optional() }); /** - * Provider list response. + * List providers with setup metadata and the current model inventory snapshot. */ -export const zListProvidersResponse_unstable = z.object({ - entries: z.array(zProviderInventoryEntryDto) +export const zListProvidersRequest_unstable = z.object({ + providerIds: z.array(z.string()).optional().default([]) }); /** - * List the raw model identifiers returned by a provider's live supported-models API. + * HTTP transport configuration for MCP. */ -export const zProviderSupportedModelsListRequest_unstable = z.object({ - providerId: z.string() -}); - -export const zProviderSupportedModelsListResponse_unstable = z.object({ - providerId: z.string(), - models: z.array(z.string()) +export const zMcpServerHttp = z.object({ + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional(), + headers: z.array(zHttpHeader), + name: z.string(), + type: z.literal('http'), + url: z.string() }); /** - * List custom-provider catalog entries. Omit `format` to list all formats. + * SSE transport configuration for MCP. */ -export const zProviderCatalogListRequest_unstable = z.object({ - format: z.union([ - z.string(), +export const zMcpServerSse = z.object({ + _meta: z.union([ + z.record(z.unknown()), z.null() - ]).optional() -}); - -export const zProviderTemplateCatalogEntryDto = z.object({ - providerId: z.string(), + ]).optional(), + headers: z.array(zHttpHeader), name: z.string(), - format: z.string(), - apiUrl: z.string(), - modelCount: z.number().int().gte(0), - docUrl: z.string(), - envVar: z.string() + type: z.literal('sse'), + url: z.string() }); -export const zProviderCatalogListResponse_unstable = z.object({ - providers: z.array(zProviderTemplateCatalogEntryDto) +/** + * Stdio transport configuration for MCP. + */ +export const zMcpServerStdio = z.object({ + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional(), + args: z.array(z.string()), + command: z.string(), + env: z.array(zEnvVariable), + name: z.string() }); /** - * List provider setup catalog entries + * Configuration for connecting to an MCP (Model Context Protocol) server. + * + * MCP servers provide tools and context that the agent can use when + * processing prompts. + * + * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) */ -export const zProviderSetupCatalogListRequest_unstable = z.record(z.unknown()); - -export const zProviderSetupMethodDto = z.enum([ - 'none', - 'single_api_key', - 'config_fields', - 'host_with_oauth_fallback', - 'oauth_browser', - 'oauth_device_code', - 'cloud_credentials', - 'local', - 'cli_auth' +export const zMcpServer = z.union([ + zMcpServerHttp, + zMcpServerSse, + zMcpServerStdio ]); -export const zProviderSetupFieldDto = z.object({ - key: z.string(), - label: z.string(), - secret: z.boolean(), - required: z.boolean(), - placeholder: z.union([ - z.string(), - z.null() - ]).optional(), - defaultValue: z.union([ - z.string(), - z.null() - ]).optional() +export const zGooseExtension = z.union([ + z.object({ + bundled: z.union([ + z.boolean(), + z.null() + ]).optional(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + display_name: z.union([ + z.string(), + z.null() + ]).optional(), + name: z.string(), + timeout: z.union([ + z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), + z.null() + ]).optional(), + type: z.literal('builtin') + }), + z.object({ + bundled: z.union([ + z.boolean(), + z.null() + ]).optional(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + display_name: z.union([ + z.string(), + z.null() + ]).optional(), + name: z.string(), + type: z.literal('platform') + }), + z.object({ + bundled: z.union([ + z.boolean(), + z.null() + ]).optional(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + envKeys: z.array(z.string()).optional(), + server: zMcpServer, + socket: z.union([ + z.string(), + z.null() + ]).optional(), + timeout: z.union([ + z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), + z.null() + ]).optional(), + type: z.literal('mcp') + }), + z.object({ + code: z.string(), + dependencies: z.array(z.string()).optional(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + name: z.string(), + timeout: z.union([ + z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), + z.null() + ]).optional(), + type: z.literal('inline_python') + }), + z.object({ + bundled: z.union([ + z.boolean(), + z.null() + ]).optional(), + description: z.union([ + z.string(), + z.null() + ]).optional(), + instructions: z.union([ + z.string(), + z.null() + ]).optional(), + name: z.string(), + tools: z.array(z.unknown()).optional(), + type: z.literal('frontend') + }) +]); + +/** + * Persist a new extension to the user's global goose config. + */ +export const zAddConfigExtensionRequest_unstable = z.object({ + enabled: z.boolean().optional().default(false), + extension: zGooseExtension }); -export const zProviderSetupGroupDto = z.enum(['default', 'additional']); +export const zGetAvailableExtensionsResponse_unstable = z.object({ + extensions: z.array(zGooseExtension) +}); -export const zProviderSetupCatalogEntryDto = z.object({ - providerId: z.string(), - name: z.string(), - category: zProviderSetupCategoryDto, - description: z.string(), - setupMethod: zProviderSetupMethodDto, - nativeConnectQuery: z.union([ - z.string(), - z.null() - ]).optional(), - fields: z.array(zProviderSetupFieldDto).optional().default([]), - binaryName: z.union([ - z.string(), - z.null() - ]).optional(), - docUrl: z.union([ +export const zGooseExtensionEntry = z.object({ + configKey: z.union([ z.string(), z.null() ]).optional(), - group: zProviderSetupGroupDto, - showOnlyWhenInstalled: z.boolean(), - aliases: z.array(z.string()).optional().default([]), - supportsInstall: z.boolean(), - supportsAuth: z.boolean(), - supportsAuthStatus: z.boolean() + enabled: z.boolean(), + extension: zGooseExtension }); -export const zProviderSetupCatalogListResponse_unstable = z.object({ - providers: z.array(zProviderSetupCatalogEntryDto) +/** + * List configured extensions and any warnings. + */ +export const zGetConfigExtensionsResponse_unstable = z.object({ + extensions: z.array(zGooseExtensionEntry), + warnings: z.array(z.string()).optional().default([]) }); /** - * Return the editable template for one catalog provider. + * Import selected onboarding candidates. */ -export const zProviderCatalogTemplateRequest_unstable = z.object({ - providerId: z.string() +export const zOnboardingImportApplyRequest_unstable = z.object({ + candidateIds: z.array(z.string()).optional().default([]), + enableImportedExtensions: z.boolean().optional().default(false) }); -export const zProviderTemplateCapabilitiesDto = z.object({ - toolCall: z.boolean(), - reasoning: z.boolean(), - attachment: z.boolean(), - temperature: z.boolean() +export const zOnboardingImportCounts = z.object({ + extensions: z.number().int().gte(0), + preferences: z.number().int().gte(0), + projects: z.number().int().gte(0), + providers: z.number().int().gte(0), + sessions: z.number().int().gte(0), + skills: z.number().int().gte(0) }); -export const zProviderTemplateModelDto = z.object({ - id: z.string(), - name: z.string(), - contextLimit: z.number().int().gte(0), - capabilities: zProviderTemplateCapabilitiesDto, - deprecated: z.boolean() +export const zOnboardingImportApplyResponse_unstable = z.object({ + imported: zOnboardingImportCounts, + providerDefaults: z.union([ + zDefaultsReadResponse_unstable, + z.null() + ]).optional(), + skipped: zOnboardingImportCounts, + warnings: z.array(z.string()).optional().default([]) }); -export const zProviderTemplateDto = z.object({ - providerId: z.string(), - name: z.string(), - format: z.string(), - apiUrl: z.string(), - models: z.array(zProviderTemplateModelDto), - supportsStreaming: z.boolean(), - envVar: z.string(), - docUrl: z.string() -}); +/** + * Sources that onboarding knows how to discover and import. + */ +export const zOnboardingImportSourceKind = z.enum(['goose_config', 'claude_desktop']); -export const zProviderCatalogTemplateResponse_unstable = z.object({ - template: zProviderTemplateDto +export const zOnboardingImportCandidate = z.object({ + counts: zOnboardingImportCounts, + displayName: z.string(), + id: z.string(), + path: z.string(), + sourceKind: zOnboardingImportSourceKind, + warnings: z.array(z.string()).optional().default([]) }); /** - * Create a custom provider backed by Goose's declarative provider store. + * Scan for existing Goose and compatible app data that onboarding can import. */ -export const zCustomProviderCreateRequest_unstable = z.object({ - engine: z.string(), - displayName: z.string(), - apiUrl: z.string(), - apiKey: z.union([ - z.string(), - z.null() - ]).optional(), - models: z.array(z.string()).optional().default([]), - supportsStreaming: z.union([ - z.boolean(), - z.null() - ]).optional(), - headers: z.record(z.string()).optional().default({}), - requiresAuth: z.boolean(), - catalogProviderId: z.union([ - z.string(), - z.null() - ]).optional(), - basePath: z.union([ - z.string(), - z.null() - ]).optional(), - preservesThinking: z.union([ - z.boolean(), - z.null() - ]).optional() +export const zOnboardingImportScanRequest_unstable = z.object({ + sources: z.array(zOnboardingImportSourceKind).optional().default([]) }); -export const zProviderConfigStatusDto = z.object({ - providerId: z.string(), - isConfigured: z.boolean() +export const zOnboardingImportScanResponse_unstable = z.object({ + candidates: z.array(zOnboardingImportCandidate) }); -export const zRefreshProviderInventorySkipReasonDto = z.enum([ - 'unknown_provider', - 'not_configured', - 'does_not_support_refresh', - 'already_refreshing' +export const zPreferenceKey = z.enum([ + 'autoCompactThreshold', + 'voiceAutoSubmitPhrases', + 'voiceDictationProvider', + 'voiceDictationPreferredMic' ]); -export const zRefreshProviderInventorySkipDto = z.object({ - providerId: z.string(), - reason: zRefreshProviderInventorySkipReasonDto +export const zPreferenceValue = z.object({ + key: zPreferenceKey, + value: z.unknown().optional().default(null) }); /** - * Refresh acknowledgement. + * Read allowlisted user preferences. Empty `keys` means all supported preferences. */ -export const zRefreshProviderInventoryResponse_unstable = z.object({ - started: z.array(z.string()), - skipped: z.array(zRefreshProviderInventorySkipDto).optional().default([]) +export const zPreferencesReadRequest_unstable = z.object({ + keys: z.array(zPreferenceKey).optional().default([]) }); -export const zCustomProviderCreateResponse_unstable = z.object({ - providerId: z.string(), - status: zProviderConfigStatusDto, - refresh: zRefreshProviderInventoryResponse_unstable +export const zPreferencesReadResponse_unstable = z.object({ + values: z.array(zPreferenceValue) }); /** - * Read a declarative provider config. Custom configs are editable; bundled configs are read-only. + * Remove allowlisted user preferences. */ -export const zCustomProviderReadRequest_unstable = z.object({ - providerId: z.string() +export const zPreferencesRemoveRequest_unstable = z.object({ + keys: z.array(zPreferenceKey).optional().default([]) }); -export const zCustomProviderConfigDto = z.object({ - providerId: z.string(), - engine: z.string(), - displayName: z.string(), - apiUrl: z.string(), - models: z.array(z.string()).optional().default([]), - supportsStreaming: z.union([ - z.boolean(), - z.null() - ]).optional(), - headers: z.record(z.string()).optional().default({}), - requiresAuth: z.boolean(), - catalogProviderId: z.union([ - z.string(), - z.null() - ]).optional(), - basePath: z.union([ - z.string(), - z.null() - ]).optional(), - apiKeyEnv: z.union([ +/** + * Save allowlisted user preferences. + */ +export const zPreferencesSaveRequest_unstable = z.object({ + values: z.array(zPreferenceValue).optional().default([]) +}); + +/** + * List custom-provider catalog entries. Omit `format` to list all formats. + */ +export const zProviderCatalogListRequest_unstable = z.object({ + format: z.union([ z.string(), z.null() - ]).optional(), - apiKeySet: z.boolean(), - preservesThinking: z.boolean() + ]).optional() }); -export const zCustomProviderReadResponse_unstable = z.object({ - provider: zCustomProviderConfigDto, - editable: z.boolean(), - status: zProviderConfigStatusDto +/** + * Return the editable template for one catalog provider. + */ +export const zProviderCatalogTemplateRequest_unstable = z.object({ + providerId: z.string() }); /** - * Update a custom provider backed by Goose's declarative provider store. + * Run a provider-owned native authentication flow and start an inventory refresh when supported. */ -export const zCustomProviderUpdateRequest_unstable = z.object({ - providerId: z.string(), - engine: z.string(), - displayName: z.string(), - apiUrl: z.string(), - apiKey: z.union([ - z.string(), - z.null() - ]).optional(), - models: z.array(z.string()).optional().default([]), - supportsStreaming: z.union([ - z.boolean(), - z.null() - ]).optional(), - headers: z.record(z.string()).optional().default({}), - requiresAuth: z.boolean(), - catalogProviderId: z.union([ - z.string(), - z.null() - ]).optional(), - basePath: z.union([ +export const zProviderConfigAuthenticateRequest_unstable = z.object({ + providerId: z.string() +}); + +/** + * Delete provider configuration fields and start an inventory refresh when supported. + */ +export const zProviderConfigDeleteRequest_unstable = z.object({ + providerId: z.string() +}); + +export const zProviderConfigFieldUpdate = z.object({ + key: z.string(), + value: z.string() +}); + +export const zProviderConfigFieldValueDto = z.object({ + isSecret: z.boolean(), + isSet: z.boolean(), + key: z.string(), + required: z.boolean(), + value: z.union([ z.string(), z.null() - ]).optional(), - preservesThinking: z.union([ - z.boolean(), - z.null() - ]).optional() + ]).optional().default(null) }); -export const zCustomProviderUpdateResponse_unstable = z.object({ - providerId: z.string(), - status: zProviderConfigStatusDto, - refresh: zRefreshProviderInventoryResponse_unstable +export const zProviderConfigKey = z.object({ + default: z.union([ + z.string(), + z.null() + ]).optional().default(null), + deviceCodeFlow: z.boolean().optional().default(false), + name: z.string(), + oauthFlow: z.boolean().optional().default(false), + primary: z.boolean().optional().default(false), + required: z.boolean(), + secret: z.boolean() }); /** - * Delete a custom provider from Goose's declarative provider store. + * Read saved configuration field values for one provider. */ -export const zCustomProviderDeleteRequest_unstable = z.object({ +export const zProviderConfigReadRequest_unstable = z.object({ providerId: z.string() }); -export const zCustomProviderDeleteResponse_unstable = z.object({ - providerId: z.string(), - refresh: zRefreshProviderInventoryResponse_unstable -}); - -/** - * Trigger a background refresh of provider inventories. - */ -export const zRefreshProviderInventoryRequest_unstable = z.object({ - providerIds: z.array(z.string()).optional().default([]) +export const zProviderConfigReadResponse_unstable = z.object({ + fields: z.array(zProviderConfigFieldValueDto) }); /** - * Read saved configuration field values for one provider. + * Save provider configuration fields and start an inventory refresh when supported. */ -export const zProviderConfigReadRequest_unstable = z.object({ +export const zProviderConfigSaveRequest_unstable = z.object({ + fields: z.array(zProviderConfigFieldUpdate), providerId: z.string() }); -export const zProviderConfigFieldValueDto = z.object({ - key: z.string(), - value: z.union([ - z.string(), - z.null() - ]).optional().default(null), - isSet: z.boolean(), - isSecret: z.boolean(), - required: z.boolean() +export const zProviderConfigStatusDto = z.object({ + isConfigured: z.boolean(), + providerId: z.string() }); -export const zProviderConfigReadResponse_unstable = z.object({ - fields: z.array(zProviderConfigFieldValueDto) +export const zCustomProviderReadResponse_unstable = z.object({ + editable: z.boolean(), + provider: zCustomProviderConfigDto, + status: zProviderConfigStatusDto }); /** @@ -761,200 +808,270 @@ export const zProviderConfigStatusResponse_unstable = z.object({ statuses: z.array(zProviderConfigStatusDto) }); -export const zProviderConfigFieldUpdate = z.object({ - key: z.string(), - value: z.string() +/** + * A single model in provider inventory. + */ +export const zProviderInventoryModelDto = z.object({ + contextLimit: z.union([ + z.number().int().gte(0), + z.null() + ]).optional(), + family: z.union([ + z.string(), + z.null() + ]).optional(), + id: z.string(), + name: z.string(), + reasoning: z.union([ + z.boolean(), + z.null() + ]).optional(), + recommended: z.boolean().optional().default(false) }); /** - * Save provider configuration fields and start an inventory refresh when supported. + * List provider setup catalog entries */ -export const zProviderConfigSaveRequest_unstable = z.object({ - providerId: z.string(), - fields: z.array(zProviderConfigFieldUpdate) -}); +export const zProviderSetupCatalogListRequest_unstable = z.record(z.unknown()); -export const zProviderConfigChangeResponse_unstable = z.object({ - status: zProviderConfigStatusDto, - refresh: zRefreshProviderInventoryResponse_unstable -}); +export const zProviderSetupCategoryDto = z.enum(['agent', 'model']); /** - * Delete provider configuration fields and start an inventory refresh when supported. + * Provider inventory entry. */ -export const zProviderConfigDeleteRequest_unstable = z.object({ - providerId: z.string() +export const zProviderInventoryEntryDto = z.object({ + category: zProviderSetupCategoryDto, + configKeys: z.array(zProviderConfigKey), + configured: z.boolean(), + defaultModel: z.string(), + description: z.string(), + lastRefreshAttemptAt: z.union([ + z.string(), + z.null() + ]).optional(), + lastRefreshError: z.union([ + z.string(), + z.null() + ]).optional(), + lastUpdatedAt: z.union([ + z.string(), + z.null() + ]).optional(), + modelSelectionHint: z.union([ + z.string(), + z.null() + ]).optional(), + models: z.array(zProviderInventoryModelDto), + providerId: z.string(), + providerName: z.string(), + providerType: z.string(), + refreshing: z.boolean(), + setupSteps: z.array(z.string()), + stale: z.boolean(), + supportsRefresh: z.boolean() }); /** - * Run a provider-owned native authentication flow and start an inventory refresh when supported. + * Provider list response. */ -export const zProviderConfigAuthenticateRequest_unstable = z.object({ - providerId: z.string() +export const zListProvidersResponse_unstable = z.object({ + entries: z.array(zProviderInventoryEntryDto) }); -export const zPreferenceKey = z.enum([ - 'autoCompactThreshold', - 'voiceAutoSubmitPhrases', - 'voiceDictationProvider', - 'voiceDictationPreferredMic' +export const zProviderSetupFieldDto = z.object({ + defaultValue: z.union([ + z.string(), + z.null() + ]).optional(), + key: z.string(), + label: z.string(), + placeholder: z.union([ + z.string(), + z.null() + ]).optional(), + required: z.boolean(), + secret: z.boolean() +}); + +export const zProviderSetupGroupDto = z.enum(['default', 'additional']); + +export const zProviderSetupMethodDto = z.enum([ + 'none', + 'single_api_key', + 'config_fields', + 'host_with_oauth_fallback', + 'oauth_browser', + 'oauth_device_code', + 'cloud_credentials', + 'local', + 'cli_auth' ]); +export const zProviderSetupCatalogEntryDto = z.object({ + aliases: z.array(z.string()).optional().default([]), + binaryName: z.union([ + z.string(), + z.null() + ]).optional(), + category: zProviderSetupCategoryDto, + description: z.string(), + docUrl: z.union([ + z.string(), + z.null() + ]).optional(), + fields: z.array(zProviderSetupFieldDto).optional().default([]), + group: zProviderSetupGroupDto, + name: z.string(), + nativeConnectQuery: z.union([ + z.string(), + z.null() + ]).optional(), + providerId: z.string(), + setupMethod: zProviderSetupMethodDto, + showOnlyWhenInstalled: z.boolean(), + supportsAuth: z.boolean(), + supportsAuthStatus: z.boolean(), + supportsInstall: z.boolean() +}); + +export const zProviderSetupCatalogListResponse_unstable = z.object({ + providers: z.array(zProviderSetupCatalogEntryDto) +}); + /** - * Read allowlisted user preferences. Empty `keys` means all supported preferences. + * List the raw model identifiers returned by a provider's live supported-models API. */ -export const zPreferencesReadRequest_unstable = z.object({ - keys: z.array(zPreferenceKey).optional().default([]) +export const zProviderSupportedModelsListRequest_unstable = z.object({ + providerId: z.string() }); -export const zPreferenceValue = z.object({ - key: zPreferenceKey, - value: z.unknown().optional().default(null) +export const zProviderSupportedModelsListResponse_unstable = z.object({ + models: z.array(z.string()), + providerId: z.string() }); -export const zPreferencesReadResponse_unstable = z.object({ - values: z.array(zPreferenceValue) +export const zProviderTemplateCapabilitiesDto = z.object({ + attachment: z.boolean(), + reasoning: z.boolean(), + temperature: z.boolean(), + toolCall: z.boolean() }); -/** - * Save allowlisted user preferences. - */ -export const zPreferencesSaveRequest_unstable = z.object({ - values: z.array(zPreferenceValue).optional().default([]) +export const zProviderTemplateCatalogEntryDto = z.object({ + apiUrl: z.string(), + docUrl: z.string(), + envVar: z.string(), + format: z.string(), + modelCount: z.number().int().gte(0), + name: z.string(), + providerId: z.string() }); -/** - * Remove allowlisted user preferences. - */ -export const zPreferencesRemoveRequest_unstable = z.object({ - keys: z.array(zPreferenceKey).optional().default([]) +export const zProviderCatalogListResponse_unstable = z.object({ + providers: z.array(zProviderTemplateCatalogEntryDto) }); -/** - * Read Goose default provider and model configuration. - */ -export const zDefaultsReadRequest_unstable = z.record(z.unknown()); +export const zProviderTemplateModelDto = z.object({ + capabilities: zProviderTemplateCapabilitiesDto, + contextLimit: z.number().int().gte(0), + deprecated: z.boolean(), + id: z.string(), + name: z.string() +}); -export const zDefaultsReadResponse_unstable = z.object({ - providerId: z.union([ - z.string(), - z.null() - ]).optional(), - modelId: z.union([ - z.string(), - z.null() - ]).optional() +export const zProviderTemplateDto = z.object({ + apiUrl: z.string(), + docUrl: z.string(), + envVar: z.string(), + format: z.string(), + models: z.array(zProviderTemplateModelDto), + name: z.string(), + providerId: z.string(), + supportsStreaming: z.boolean() +}); + +export const zProviderCatalogTemplateResponse_unstable = z.object({ + template: zProviderTemplateDto }); /** - * Save Goose default provider and model configuration. + * Read a resource from an extension. */ -export const zDefaultsSaveRequest_unstable = z.object({ - providerId: z.string(), - modelId: z.union([ - z.string(), - z.null() - ]).optional() +export const zReadResourceRequest_unstable = z.object({ + extensionName: z.string(), + sessionId: z.string(), + uri: z.string() }); /** - * Sources that onboarding knows how to discover and import. + * Resource read response. */ -export const zOnboardingImportSourceKind = z.enum(['goose_config', 'claude_desktop']); +export const zReadResourceResponse_unstable = z.object({ + result: z.unknown().optional().default(null) +}); /** - * Scan for existing Goose and compatible app data that onboarding can import. + * Trigger a background refresh of provider inventories. */ -export const zOnboardingImportScanRequest_unstable = z.object({ - sources: z.array(zOnboardingImportSourceKind).optional().default([]) -}); - -export const zOnboardingImportCounts = z.object({ - providers: z.number().int().gte(0), - extensions: z.number().int().gte(0), - sessions: z.number().int().gte(0), - skills: z.number().int().gte(0), - projects: z.number().int().gte(0), - preferences: z.number().int().gte(0) +export const zRefreshProviderInventoryRequest_unstable = z.object({ + providerIds: z.array(z.string()).optional().default([]) }); -export const zOnboardingImportCandidate = z.object({ - id: z.string(), - sourceKind: zOnboardingImportSourceKind, - displayName: z.string(), - path: z.string(), - counts: zOnboardingImportCounts, - warnings: z.array(z.string()).optional().default([]) -}); +export const zRefreshProviderInventorySkipReasonDto = z.enum([ + 'unknown_provider', + 'not_configured', + 'does_not_support_refresh', + 'already_refreshing' +]); -export const zOnboardingImportScanResponse_unstable = z.object({ - candidates: z.array(zOnboardingImportCandidate) +export const zRefreshProviderInventorySkipDto = z.object({ + providerId: z.string(), + reason: zRefreshProviderInventorySkipReasonDto }); /** - * Import selected onboarding candidates. + * Refresh acknowledgement. */ -export const zOnboardingImportApplyRequest_unstable = z.object({ - candidateIds: z.array(z.string()).optional().default([]), - enableImportedExtensions: z.boolean().optional().default(false) +export const zRefreshProviderInventoryResponse_unstable = z.object({ + skipped: z.array(zRefreshProviderInventorySkipDto).optional().default([]), + started: z.array(z.string()) }); -export const zOnboardingImportApplyResponse_unstable = z.object({ - imported: zOnboardingImportCounts, - skipped: zOnboardingImportCounts, - warnings: z.array(z.string()).optional().default([]), - providerDefaults: z.union([ - zDefaultsReadResponse_unstable, - z.null() - ]).optional() +export const zCustomProviderCreateResponse_unstable = z.object({ + providerId: z.string(), + refresh: zRefreshProviderInventoryResponse_unstable, + status: zProviderConfigStatusDto }); -/** - * Export a session as a JSON string. - */ -export const zExportSessionRequest_unstable = z.object({ - sessionId: z.string() +export const zCustomProviderDeleteResponse_unstable = z.object({ + providerId: z.string(), + refresh: zRefreshProviderInventoryResponse_unstable }); -/** - * Export session response — raw JSON of the goose session with `conversation`. - */ -export const zExportSessionResponse_unstable = z.object({ - data: z.string() +export const zCustomProviderUpdateResponse_unstable = z.object({ + providerId: z.string(), + refresh: zRefreshProviderInventoryResponse_unstable, + status: zProviderConfigStatusDto }); -/** - * Import a session from a JSON string. - */ -export const zImportSessionRequest_unstable = z.object({ - data: z.string() +export const zProviderConfigChangeResponse_unstable = z.object({ + refresh: zRefreshProviderInventoryResponse_unstable, + status: zProviderConfigStatusDto }); /** - * Import session response — metadata about the newly created session. + * Remove a persisted extension from the user's global goose config. */ -export const zImportSessionResponse_unstable = z.object({ - sessionId: z.string(), - title: z.union([ - z.string(), - z.null() - ]).optional(), - updatedAt: z.union([ - z.string(), - z.null() - ]).optional(), - messageCount: z.number().int().gte(0) +export const zRemoveConfigExtensionRequest_unstable = z.object({ + configKey: z.string() }); /** - * Update the project association for a session. + * Remove an extension from an active session. */ -export const zUpdateSessionProjectRequest_unstable = z.object({ - sessionId: z.string(), - projectId: z.union([ - z.string(), - z.null() - ]).optional() +export const zRemoveExtensionRequest_unstable = z.object({ + name: z.string(), + sessionId: z.string() }); /** @@ -966,30 +1083,37 @@ export const zRenameSessionRequest_unstable = z.object({ }); /** - * Archive a session (soft delete). + * How a session system prompt update should be applied. */ -export const zArchiveSessionRequest_unstable = z.object({ - sessionId: z.string() -}); +export const zSessionSystemPromptMode = z.union([ + z.literal('set'), + z.literal('append') +]); /** - * Unarchive a previously archived session. + * Set the `enabled` flag for a persisted extension in the user's global goose config. */ -export const zUnarchiveSessionRequest_unstable = z.object({ - sessionId: z.string() +export const zSetConfigExtensionEnabledRequest_unstable = z.object({ + configKey: z.string(), + enabled: z.boolean() }); /** - * The type of source entity. + * Set, append, or clear system prompt text for a session. + * + * `mode: "set"` replaces Goose's base system prompt. `mode: "append"` adds an + * instruction under "Additional Instructions". Reusing a key replaces the + * previous value for that mode/key; sending empty text clears it. */ -export const zSourceType = z.enum([ - 'skill', - 'builtinSkill', - 'recipe', - 'subrecipe', - 'agent', - 'project' -]); +export const zSetSessionSystemPromptRequest_unstable = z.object({ + key: z.union([ + z.string(), + z.null() + ]).optional(), + mode: zSessionSystemPromptMode.optional().default('append'), + sessionId: z.string(), + text: z.string() +}); /** * Target scope for creating or importing sources. @@ -1008,103 +1132,6 @@ export const zSourceScope = z.union([ }) ]); -/** - * Create a new source in an explicit target scope (global or project-scoped). - */ -export const zCreateSourceRequest_unstable = z.object({ - type: zSourceType, - name: z.string(), - description: z.string(), - content: z.string(), - target: zSourceScope, - properties: z.record(z.unknown()).optional() -}); - -/** - * A source discovered by Goose. Filesystem sources use an on-disk path; - * built-in sources use a stable synthetic path. Sources may be either - * `global` (shared across all projects) or project-specific. - */ -export const zSourceEntry = z.object({ - type: zSourceType, - name: z.string(), - description: z.string(), - content: z.string(), - path: z.string(), - global: z.boolean(), - writable: z.boolean().optional().default(false), - supportingFiles: z.array(z.string()).optional(), - properties: z.record(z.unknown()).optional() -}); - -export const zCreateSourceResponse_unstable = z.object({ - source: zSourceEntry -}); - -/** - * List discovered sources. - * - * If `type` is omitted or `skill`, this lists filesystem/plugin skills only. - * Both global and project-scoped skills are included when `project_dir` is - * set. If `type` is `builtinSkill`, this lists shipped read-only built-in - * skills. - */ -export const zListSourcesRequest_unstable = z.object({ - type: z.union([ - zSourceType, - z.null() - ]).optional(), - projectDir: z.union([ - z.string(), - z.null() - ]).optional(), - includeProjectSources: z.boolean().optional().default(false) -}); - -export const zListSourcesResponse_unstable = z.object({ - sources: z.array(zSourceEntry) -}); - -/** - * Update an existing source's name, description, and content by absolute path. - */ -export const zUpdateSourceRequest_unstable = z.object({ - type: zSourceType, - path: z.string(), - name: z.string(), - description: z.string(), - content: z.string(), - properties: z.union([ - z.record(z.unknown()), - z.null() - ]).optional() -}); - -export const zUpdateSourceResponse_unstable = z.object({ - source: zSourceEntry -}); - -/** - * Delete a source and its on-disk directory by absolute path. - */ -export const zDeleteSourceRequest_unstable = z.object({ - type: zSourceType, - path: z.string() -}); - -/** - * Export a source at an absolute path as a portable JSON payload. - */ -export const zExportSourceRequest_unstable = z.object({ - type: zSourceType, - path: z.string() -}); - -export const zExportSourceResponse_unstable = z.object({ - json: z.string(), - filename: z.string() -}); - /** * Import a source from a JSON export payload produced by `_goose/unstable/sources/export`. * The imported source is written into the explicit target scope; on name @@ -1115,163 +1142,192 @@ export const zImportSourcesRequest_unstable = z.object({ target: zSourceScope }); -export const zImportSourcesResponse_unstable = z.object({ - sources: z.array(zSourceEntry) -}); +/** + * The type of source entity. + */ +export const zSourceType = z.enum([ + 'skill', + 'builtinSkill', + 'recipe', + 'subrecipe', + 'agent', + 'project' +]); /** - * Transcribe audio via a dictation provider. + * Create a new source in an explicit target scope (global or project-scoped). */ -export const zDictationTranscribeRequest_unstable = z.object({ - audio: z.string(), - mimeType: z.string(), - provider: z.string() +export const zCreateSourceRequest_unstable = z.object({ + content: z.string(), + description: z.string(), + name: z.string(), + properties: z.record(z.unknown()).optional(), + target: zSourceScope, + type: zSourceType }); /** - * Transcription result. + * Delete a source and its on-disk directory by absolute path. */ -export const zDictationTranscribeResponse_unstable = z.object({ - text: z.string() +export const zDeleteSourceRequest_unstable = z.object({ + path: z.string(), + type: zSourceType }); /** - * Get the configuration status of all dictation providers. + * Export a source at an absolute path as a portable JSON payload. */ -export const zDictationConfigRequest_unstable = z.record(z.unknown()); - -export const zDictationModelOption = z.object({ - id: z.string(), - label: z.string(), - description: z.string() +export const zExportSourceRequest_unstable = z.object({ + path: z.string(), + type: zSourceType }); /** - * Per-provider configuration status. + * List discovered sources. + * + * If `type` is omitted or `skill`, this lists filesystem/plugin skills only. + * Both global and project-scoped skills are included when `project_dir` is + * set. If `type` is `builtinSkill`, this lists shipped read-only built-in + * skills. */ -export const zDictationProviderStatusEntry = z.object({ - configured: z.boolean(), - host: z.union([ - z.string(), - z.null() - ]).optional(), - description: z.string(), - usesProviderConfig: z.boolean(), - settingsPath: z.union([ - z.string(), - z.null() - ]).optional(), - configKey: z.union([ - z.string(), - z.null() - ]).optional(), - modelConfigKey: z.union([ - z.string(), - z.null() - ]).optional(), - defaultModel: z.union([ +export const zListSourcesRequest_unstable = z.object({ + includeProjectSources: z.boolean().optional().default(false), + projectDir: z.union([ z.string(), z.null() ]).optional(), - selectedModel: z.union([ - z.string(), + type: z.union([ + zSourceType, z.null() - ]).optional(), - availableModels: z.array(zDictationModelOption).optional().default([]) -}); - -/** - * Dictation config response — map of provider name to status. - */ -export const zDictationConfigResponse_unstable = z.object({ - providers: z.record(zDictationProviderStatusEntry) + ]).optional() }); /** - * Set a dictation provider secret value. + * A source discovered by Goose. Filesystem sources use an on-disk path; + * built-in sources use a stable synthetic path. Sources may be either + * `global` (shared across all projects) or project-specific. */ -export const zDictationSecretSaveRequest_unstable = z.object({ - provider: z.string(), - value: z.string() +export const zSourceEntry = z.object({ + content: z.string(), + description: z.string(), + global: z.boolean(), + name: z.string(), + path: z.string(), + properties: z.record(z.unknown()).optional(), + supportingFiles: z.array(z.string()).optional(), + type: zSourceType, + writable: z.boolean().optional().default(false) }); -/** - * Remove a dictation provider secret value. - */ -export const zDictationSecretDeleteRequest_unstable = z.object({ - provider: z.string() +export const zCreateSourceResponse_unstable = z.object({ + source: zSourceEntry }); -/** - * List available local Whisper models with their download status. - */ -export const zDictationModelsListRequest_unstable = z.record(z.unknown()); - -export const zDictationLocalModelStatus = z.object({ - id: z.string(), - label: z.string(), - description: z.string(), - sizeMb: z.number().int().gte(0), - downloaded: z.boolean(), - downloadInProgress: z.boolean() +export const zImportSourcesResponse_unstable = z.object({ + sources: z.array(zSourceEntry) }); -export const zDictationModelsListResponse_unstable = z.object({ - models: z.array(zDictationLocalModelStatus) +export const zListSourcesResponse_unstable = z.object({ + sources: z.array(zSourceEntry) }); /** - * Kick off a background download of a local Whisper model. + * Unarchive a previously archived session. */ -export const zDictationModelDownloadRequest_unstable = z.object({ - modelId: z.string() +export const zUnarchiveSessionRequest_unstable = z.object({ + sessionId: z.string() }); /** - * Poll the progress of an in-flight download. + * Update the project association for a session. */ -export const zDictationModelDownloadProgressRequest_unstable = z.object({ - modelId: z.string() -}); - -export const zDictationDownloadProgress = z.object({ - bytesDownloaded: z.number().int().gte(0), - totalBytes: z.number().int().gte(0), - progressPercent: z.number(), - status: z.string(), - error: z.union([ +export const zUpdateSessionProjectRequest_unstable = z.object({ + projectId: z.union([ z.string(), z.null() - ]).optional() -}); - -export const zDictationModelDownloadProgressResponse_unstable = z.object({ - progress: z.union([ - zDictationDownloadProgress, - z.null() - ]).optional() + ]).optional(), + sessionId: z.string() }); /** - * Cancel an in-flight download. + * Update an existing source's name, description, and content by absolute path. */ -export const zDictationModelCancelRequest_unstable = z.object({ - modelId: z.string() +export const zUpdateSourceRequest_unstable = z.object({ + content: z.string(), + description: z.string(), + name: z.string(), + path: z.string(), + properties: z.union([ + z.record(z.unknown()), + z.null() + ]).optional(), + type: zSourceType }); -/** - * Delete a downloaded local Whisper model from disk. - */ -export const zDictationModelDeleteRequest_unstable = z.object({ - modelId: z.string() +export const zUpdateSourceResponse_unstable = z.object({ + source: zSourceEntry }); +export const zExtResponse = z.union([ + z.object({ + id: z.string(), + result: z.union([ + z.union([ + zEmptyResponse, + zGetToolsResponse_unstable, + zGooseToolCallResponse_unstable, + zReadResourceResponse_unstable, + zGetConfigExtensionsResponse_unstable, + zGetAvailableExtensionsResponse_unstable, + zGetSessionExtensionsResponse_unstable, + zListProvidersResponse_unstable, + zProviderSupportedModelsListResponse_unstable, + zProviderCatalogListResponse_unstable, + zProviderSetupCatalogListResponse_unstable, + zProviderCatalogTemplateResponse_unstable, + zCustomProviderCreateResponse_unstable, + zCustomProviderReadResponse_unstable, + zCustomProviderUpdateResponse_unstable, + zCustomProviderDeleteResponse_unstable, + zRefreshProviderInventoryResponse_unstable, + zProviderConfigReadResponse_unstable, + zProviderConfigStatusResponse_unstable, + zProviderConfigChangeResponse_unstable, + zPreferencesReadResponse_unstable, + zDefaultsReadResponse_unstable, + zOnboardingImportScanResponse_unstable, + zOnboardingImportApplyResponse_unstable, + zExportSessionResponse_unstable, + zImportSessionResponse_unstable, + zCreateSourceResponse_unstable, + zListSourcesResponse_unstable, + zUpdateSourceResponse_unstable, + zExportSourceResponse_unstable, + zImportSourcesResponse_unstable, + zDictationTranscribeResponse_unstable, + zDictationConfigResponse_unstable, + zDictationModelsListResponse_unstable, + zDictationModelDownloadProgressResponse_unstable + ]), + z.unknown() + ]).optional() + }), + z.object({ + error: z.object({ + code: z.number().int(), + data: z.unknown().optional(), + message: z.string() + }), + id: z.string() + }) +]); + /** - * Persist the user's model selection for a given provider. + * Update the working directory for a session. */ -export const zDictationModelSelectRequest_unstable = z.object({ - provider: z.string(), - modelId: z.string() +export const zUpdateWorkingDirRequest_unstable = z.object({ + sessionId: z.string(), + workingDir: z.string() }); export const zExtRequest = z.object({ @@ -1344,57 +1400,3 @@ export const zExtRequest = z.object({ ]) ]).optional() }); - -export const zExtResponse = z.union([ - z.object({ - id: z.string(), - result: z.union([ - z.union([ - zEmptyResponse, - zGetToolsResponse_unstable, - zGooseToolCallResponse_unstable, - zReadResourceResponse_unstable, - zGetConfigExtensionsResponse_unstable, - zGetAvailableExtensionsResponse_unstable, - zGetSessionExtensionsResponse_unstable, - zListProvidersResponse_unstable, - zProviderSupportedModelsListResponse_unstable, - zProviderCatalogListResponse_unstable, - zProviderSetupCatalogListResponse_unstable, - zProviderCatalogTemplateResponse_unstable, - zCustomProviderCreateResponse_unstable, - zCustomProviderReadResponse_unstable, - zCustomProviderUpdateResponse_unstable, - zCustomProviderDeleteResponse_unstable, - zRefreshProviderInventoryResponse_unstable, - zProviderConfigReadResponse_unstable, - zProviderConfigStatusResponse_unstable, - zProviderConfigChangeResponse_unstable, - zPreferencesReadResponse_unstable, - zDefaultsReadResponse_unstable, - zOnboardingImportScanResponse_unstable, - zOnboardingImportApplyResponse_unstable, - zExportSessionResponse_unstable, - zImportSessionResponse_unstable, - zCreateSourceResponse_unstable, - zListSourcesResponse_unstable, - zUpdateSourceResponse_unstable, - zExportSourceResponse_unstable, - zImportSourcesResponse_unstable, - zDictationTranscribeResponse_unstable, - zDictationConfigResponse_unstable, - zDictationModelsListResponse_unstable, - zDictationModelDownloadProgressResponse_unstable - ]), - z.unknown() - ]).optional() - }), - z.object({ - error: z.object({ - code: z.number().int(), - message: z.string(), - data: z.unknown().optional() - }), - id: z.string() - }) -]); From 2ddb22c853b9beeb185829c35f0de98eb4637a77 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 3 Jun 2026 22:47:15 +1000 Subject: [PATCH 11/16] fixed the test --- crates/goose/tests/acp_custom_requests_test.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crates/goose/tests/acp_custom_requests_test.rs b/crates/goose/tests/acp_custom_requests_test.rs index b8a201a2fe3d..e1be9ac4463d 100644 --- a/crates/goose/tests/acp_custom_requests_test.rs +++ b/crates/goose/tests/acp_custom_requests_test.rs @@ -138,12 +138,7 @@ GOOSE_PROVIDER: openai "name": config_key, "command": "test-command", "args": ["--flag", "value"], - "env": [ - { - "name": "SECRET_TOKEN", - "value": "literal-secret" - } - ] + "env": [] } } }), From eee54ee2edfa30a1bfcbea1ab9f4338ca5e2c787 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Thu, 4 Jun 2026 08:08:58 +1000 Subject: [PATCH 12/16] removed the frontend and pythoninline support in acp --- crates/goose-sdk/src/custom_requests.rs | 21 - crates/goose/acp-schema.json | 6228 ++++++++++----------- crates/goose/src/acp/server/extensions.rs | 207 +- ui/desktop/src/acp/extensions.ts | 8 - ui/sdk/src/generated/types.gen.ts | 1770 +++--- ui/sdk/src/generated/zod.gen.ts | 1805 +++--- 6 files changed, 4850 insertions(+), 5189 deletions(-) diff --git a/crates/goose-sdk/src/custom_requests.rs b/crates/goose-sdk/src/custom_requests.rs index 2c52b91f0698..2515d7e5c0a0 100644 --- a/crates/goose-sdk/src/custom_requests.rs +++ b/crates/goose-sdk/src/custom_requests.rs @@ -184,27 +184,6 @@ pub enum GooseExtension { #[serde(default, skip_serializing_if = "Option::is_none")] bundled: Option, }, - InlinePython { - name: String, - #[serde(default, skip_serializing_if = "Option::is_none")] - description: Option, - code: String, - #[serde(default, skip_serializing_if = "Option::is_none")] - timeout: Option, - #[serde(default, skip_serializing_if = "Vec::is_empty")] - dependencies: Vec, - }, - Frontend { - name: String, - #[serde(default, skip_serializing_if = "Option::is_none")] - description: Option, - #[serde(default, skip_serializing_if = "Vec::is_empty")] - tools: Vec, - #[serde(default, skip_serializing_if = "Option::is_none")] - instructions: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - bundled: Option, - }, } impl Default for GooseExtension { diff --git a/crates/goose/acp-schema.json b/crates/goose/acp-schema.json index f98cf2724909..62898ac0d67b 100644 --- a/crates/goose/acp-schema.json +++ b/crates/goose/acp-schema.json @@ -1,43 +1,50 @@ { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "GooseExtensions", "$defs": { - "AddConfigExtensionRequest_unstable": { - "description": "Persist a new extension to the user's global goose config.", + "AddExtensionRequest_unstable": { + "type": "object", "properties": { - "enabled": { - "default": false, - "type": "boolean" + "sessionId": { + "type": "string" }, - "extension": { - "$ref": "#/$defs/GooseExtension" + "config": { + "description": "Extension configuration (see ExtensionConfig variants: Stdio, StreamableHttp, Builtin, Platform).", + "default": null } }, "required": [ - "extension" + "sessionId" ], + "description": "Add an extension to an active session.", + "x-side": "agent", + "x-method": "_goose/unstable/session/extensions/add" + }, + "EmptyResponse": { "type": "object", - "x-method": "_goose/unstable/config/extensions/add", + "description": "Empty success response for operations that return no data.", "x-side": "agent" }, - "AddExtensionRequest_unstable": { - "description": "Add an extension to an active session.", + "RemoveExtensionRequest_unstable": { + "type": "object", "properties": { - "config": { - "default": null, - "description": "Extension configuration (see ExtensionConfig variants: Stdio, StreamableHttp, Builtin, Platform)." - }, "sessionId": { "type": "string" + }, + "name": { + "type": "string" } }, "required": [ - "sessionId" + "sessionId", + "name" ], - "type": "object", - "x-method": "_goose/unstable/session/extensions/add", - "x-side": "agent" + "description": "Remove an extension from an active session.", + "x-side": "agent", + "x-method": "_goose/unstable/session/extensions/remove" }, - "ArchiveSessionRequest_unstable": { - "description": "Archive a session (soft delete).", + "GetToolsRequest_unstable": { + "type": "object", "properties": { "sessionId": { "type": "string" @@ -46,429 +53,639 @@ "required": [ "sessionId" ], + "description": "List all tools available in a session.", + "x-side": "agent", + "x-method": "_goose/unstable/tools/list" + }, + "GetToolsResponse_unstable": { "type": "object", - "x-method": "_goose/unstable/session/archive", - "x-side": "agent" + "properties": { + "tools": { + "type": "array", + "items": {}, + "description": "Array of tool info objects with `name`, `description`, `parameters`, and optional `permission`." + } + }, + "required": [ + "tools" + ], + "description": "Tools response.", + "x-side": "agent", + "x-method": "_goose/unstable/tools/list" }, - "CreateSourceRequest_unstable": { - "description": "Create a new source in an explicit target scope (global or project-scoped).", + "GooseToolCallRequest_unstable": { + "type": "object", "properties": { - "content": { - "type": "string" - }, - "description": { + "sessionId": { "type": "string" }, "name": { "type": "string" }, - "properties": { - "additionalProperties": {}, - "description": "Arbitrary key/value metadata.", - "type": "object" - }, - "target": { - "$ref": "#/$defs/SourceScope" - }, - "type": { - "$ref": "#/$defs/SourceType" + "arguments": { + "default": null } }, "required": [ - "type", - "name", - "description", - "content", - "target" + "sessionId", + "name" ], + "description": "Call a tool from an extension.", + "x-side": "agent", + "x-method": "_goose/unstable/tools/call" + }, + "GooseToolCallResponse_unstable": { "type": "object", - "x-method": "_goose/unstable/sources/create", - "x-side": "agent" + "properties": { + "content": { + "type": "array", + "items": {}, + "default": [] + }, + "structuredContent": {}, + "isError": { + "type": "boolean" + }, + "_meta": {} + }, + "required": [ + "isError" + ], + "description": "Tool call response.", + "x-side": "agent", + "x-method": "_goose/unstable/tools/call" }, - "CreateSourceResponse_unstable": { + "ReadResourceRequest_unstable": { + "type": "object", "properties": { - "source": { - "$ref": "#/$defs/SourceEntry" + "sessionId": { + "type": "string" + }, + "uri": { + "type": "string" + }, + "extensionName": { + "type": "string" } }, "required": [ - "source" + "sessionId", + "uri", + "extensionName" ], + "description": "Read a resource from an extension.", + "x-side": "agent", + "x-method": "_goose/unstable/resources/read" + }, + "ReadResourceResponse_unstable": { "type": "object", - "x-method": "_goose/unstable/sources/create", - "x-side": "agent" + "properties": { + "result": { + "description": "The resource result from the extension (MCP ReadResourceResult).", + "default": null + } + }, + "description": "Resource read response.", + "x-side": "agent", + "x-method": "_goose/unstable/resources/read" }, - "CustomProviderConfigDto": { + "UpdateWorkingDirRequest_unstable": { + "type": "object", "properties": { - "apiKeyEnv": { - "type": [ - "string", - "null" - ] - }, - "apiKeySet": { - "type": "boolean" + "sessionId": { + "type": "string" }, - "apiUrl": { + "workingDir": { + "type": "string" + } + }, + "required": [ + "sessionId", + "workingDir" + ], + "description": "Update the working directory for a session.", + "x-side": "agent", + "x-method": "_goose/unstable/session/working-dir/update" + }, + "SetSessionSystemPromptRequest_unstable": { + "type": "object", + "properties": { + "sessionId": { "type": "string" }, - "basePath": { - "type": [ - "string", - "null" - ] + "mode": { + "$ref": "#/$defs/SessionSystemPromptMode", + "default": "append" }, - "catalogProviderId": { + "key": { "type": [ "string", "null" ] }, - "displayName": { + "text": { "type": "string" + } + }, + "required": [ + "sessionId", + "text" + ], + "description": "Set, append, or clear system prompt text for a session.\n\n`mode: \"set\"` replaces Goose's base system prompt. `mode: \"append\"` adds an\ninstruction under \"Additional Instructions\". Reusing a key replaces the\nprevious value for that mode/key; sending empty text clears it.", + "x-side": "agent", + "x-method": "_goose/unstable/session/system-prompt/set" + }, + "SessionSystemPromptMode": { + "oneOf": [ + { + "type": "string", + "const": "set", + "description": "Replace Goose's base system prompt with the provided text." }, - "engine": { + { + "type": "string", + "const": "append", + "description": "Append the provided text under Goose's \"Additional Instructions\" section." + } + ], + "description": "How a session system prompt update should be applied." + }, + "DeleteSessionRequest": { + "type": "object", + "properties": { + "sessionId": { "type": "string" + } + }, + "required": [ + "sessionId" + ], + "description": "Delete a session.", + "x-side": "agent", + "x-method": "session/delete" + }, + "GetConfigExtensionsRequest_unstable": { + "type": "object", + "description": "List configured extensions and any warnings.", + "x-side": "agent", + "x-method": "_goose/unstable/config/extensions/list" + }, + "GetConfigExtensionsResponse_unstable": { + "type": "object", + "properties": { + "extensions": { + "type": "array", + "items": { + "$ref": "#/$defs/GooseExtensionEntry" + } }, - "headers": { - "additionalProperties": { - "type": "string" - }, - "default": {}, - "type": "object" - }, - "models": { - "default": [], + "warnings": { + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "preservesThinking": { - "type": "boolean" - }, - "providerId": { - "type": "string" - }, - "requiresAuth": { - "type": "boolean" - }, - "supportsStreaming": { - "type": [ - "boolean", - "null" - ] + "default": [] } }, "required": [ - "providerId", - "engine", - "displayName", - "apiUrl", - "requiresAuth", - "apiKeySet", - "preservesThinking" + "extensions" ], - "type": "object" + "description": "List configured extensions and any warnings.", + "x-side": "agent", + "x-method": "_goose/unstable/config/extensions/list" }, - "CustomProviderCreateRequest_unstable": { - "description": "Create a custom provider backed by Goose's declarative provider store.", + "GooseExtensionEntry": { + "type": "object", "properties": { - "apiKey": { - "type": [ - "string", - "null" - ] - }, - "apiUrl": { - "type": "string" + "extension": { + "$ref": "#/$defs/GooseExtension" }, - "basePath": { - "type": [ - "string", - "null" - ] + "enabled": { + "type": "boolean" }, - "catalogProviderId": { + "configKey": { "type": [ "string", "null" ] + } + }, + "required": [ + "extension", + "enabled" + ] + }, + "GooseExtension": { + "oneOf": [ + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "timeout": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "bundled": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "const": "builtin" + } + }, + "required": [ + "type", + "name" + ] }, - "displayName": { - "type": "string" - }, - "engine": { - "type": "string" + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "bundled": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "const": "platform" + } + }, + "required": [ + "type", + "name" + ] }, - "headers": { - "additionalProperties": { - "type": "string" + { + "type": "object", + "properties": { + "server": { + "$ref": "#/$defs/McpServer" + }, + "envKeys": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "timeout": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "socket": { + "type": [ + "string", + "null" + ] + }, + "bundled": { + "type": [ + "boolean", + "null" + ] + }, + "type": { + "type": "string", + "const": "mcp" + } }, - "default": {}, - "type": "object" + "required": [ + "type", + "server" + ] + } + ] + }, + "McpServer": { + "anyOf": [ + { + "$ref": "#/$defs/McpServerHttp", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "http" + } + }, + "required": [ + "type" + ], + "description": "HTTP transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.http` is `true`." }, - "models": { - "default": [], - "items": { - "type": "string" + { + "$ref": "#/$defs/McpServerSse", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "sse" + } }, - "type": "array" + "required": [ + "type" + ], + "description": "SSE transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`." }, - "preservesThinking": { - "type": [ - "boolean", - "null" - ] + { + "$ref": "#/$defs/McpServerStdio", + "description": "Stdio transport configuration\n\nAll Agents MUST support this transport." + } + ], + "description": "Configuration for connecting to an MCP (Model Context Protocol) server.\n\nMCP servers provide tools and context that the agent can use when\nprocessing prompts.\n\nSee protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)" + }, + "HttpHeader": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the HTTP header." }, - "requiresAuth": { - "type": "boolean" + "value": { + "type": "string", + "description": "The value to set for the HTTP header." }, - "supportsStreaming": { + "_meta": { "type": [ - "boolean", + "object", "null" - ] + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" } }, "required": [ - "engine", - "displayName", - "apiUrl", - "requiresAuth" + "name", + "value" ], - "type": "object", - "x-method": "_goose/unstable/providers/custom/create", - "x-side": "agent" + "description": "An HTTP header to set when making requests to the MCP server." }, - "CustomProviderCreateResponse_unstable": { + "McpServerHttp": { + "type": "object", "properties": { - "providerId": { - "type": "string" + "name": { + "type": "string", + "description": "Human-readable name identifying this MCP server." }, - "refresh": { - "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" + "url": { + "type": "string", + "description": "URL to the MCP server." }, - "status": { - "$ref": "#/$defs/ProviderConfigStatusDto" + "headers": { + "type": "array", + "items": { + "$ref": "#/$defs/HttpHeader" + }, + "description": "HTTP headers to set when making requests to the MCP server." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + }, + "type": { + "type": "string", + "const": "http" } }, "required": [ - "providerId", - "status", - "refresh" + "type", + "name", + "url", + "headers" ], - "type": "object", - "x-method": "_goose/unstable/providers/custom/create", - "x-side": "agent" + "description": "HTTP transport configuration for MCP." }, - "CustomProviderDeleteRequest_unstable": { - "description": "Delete a custom provider from Goose's declarative provider store.", + "McpServerSse": { + "type": "object", "properties": { - "providerId": { - "type": "string" + "name": { + "type": "string", + "description": "Human-readable name identifying this MCP server." + }, + "url": { + "type": "string", + "description": "URL to the MCP server." + }, + "headers": { + "type": "array", + "items": { + "$ref": "#/$defs/HttpHeader" + }, + "description": "HTTP headers to set when making requests to the MCP server." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" + }, + "type": { + "type": "string", + "const": "sse" } }, "required": [ - "providerId" + "type", + "name", + "url", + "headers" ], - "type": "object", - "x-method": "_goose/unstable/providers/custom/delete", - "x-side": "agent" + "description": "SSE transport configuration for MCP." }, - "CustomProviderDeleteResponse_unstable": { + "McpServerStdio": { + "type": "object", "properties": { - "providerId": { - "type": "string" + "name": { + "type": "string", + "description": "Human-readable name identifying this MCP server." }, - "refresh": { - "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" - } - }, - "required": [ - "providerId", - "refresh" - ], - "type": "object", - "x-method": "_goose/unstable/providers/custom/delete", - "x-side": "agent" - }, - "CustomProviderReadRequest_unstable": { - "description": "Read a declarative provider config. Custom configs are editable; bundled configs are read-only.", - "properties": { - "providerId": { - "type": "string" + "command": { + "type": "string", + "description": "Path to the MCP server executable." + }, + "args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Command-line arguments to pass to the MCP server." + }, + "env": { + "type": "array", + "items": { + "$ref": "#/$defs/EnvVariable" + }, + "description": "Environment variables to set when launching the MCP server." + }, + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" } }, "required": [ - "providerId" + "name", + "command", + "args", + "env" ], - "type": "object", - "x-method": "_goose/unstable/providers/custom/read", - "x-side": "agent" + "description": "Stdio transport configuration for MCP." }, - "CustomProviderReadResponse_unstable": { + "EnvVariable": { + "type": "object", "properties": { - "editable": { - "type": "boolean" + "name": { + "type": "string", + "description": "The name of the environment variable." }, - "provider": { - "$ref": "#/$defs/CustomProviderConfigDto" + "value": { + "type": "string", + "description": "The value to set for the environment variable." }, - "status": { - "$ref": "#/$defs/ProviderConfigStatusDto" + "_meta": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)" } }, "required": [ - "provider", - "editable", - "status" + "name", + "value" ], + "description": "An environment variable to set when launching an MCP server." + }, + "GetAvailableExtensionsRequest_unstable": { "type": "object", - "x-method": "_goose/unstable/providers/custom/read", - "x-side": "agent" + "description": "List Goose-owned extension definitions available to configure or enable.", + "x-side": "agent", + "x-method": "_goose/unstable/extensions/available" }, - "CustomProviderUpdateRequest_unstable": { - "description": "Update a custom provider backed by Goose's declarative provider store.", + "GetAvailableExtensionsResponse_unstable": { + "type": "object", "properties": { - "apiKey": { - "type": [ - "string", - "null" - ] - }, - "apiUrl": { - "type": "string" - }, - "basePath": { - "type": [ - "string", - "null" - ] - }, - "catalogProviderId": { - "type": [ - "string", - "null" - ] - }, - "displayName": { - "type": "string" - }, - "engine": { - "type": "string" - }, - "headers": { - "additionalProperties": { - "type": "string" - }, - "default": {}, - "type": "object" - }, - "models": { - "default": [], + "extensions": { + "type": "array", "items": { - "type": "string" - }, - "type": "array" - }, - "preservesThinking": { - "type": [ - "boolean", - "null" - ] - }, - "providerId": { - "type": "string" - }, - "requiresAuth": { - "type": "boolean" - }, - "supportsStreaming": { - "type": [ - "boolean", - "null" - ] + "$ref": "#/$defs/GooseExtension" + } } }, "required": [ - "providerId", - "engine", - "displayName", - "apiUrl", - "requiresAuth" + "extensions" ], - "type": "object", - "x-method": "_goose/unstable/providers/custom/update", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/extensions/available" }, - "CustomProviderUpdateResponse_unstable": { + "AddConfigExtensionRequest_unstable": { + "type": "object", "properties": { - "providerId": { - "type": "string" - }, - "refresh": { - "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" + "extension": { + "$ref": "#/$defs/GooseExtension" }, - "status": { - "$ref": "#/$defs/ProviderConfigStatusDto" + "enabled": { + "type": "boolean", + "default": false } }, "required": [ - "providerId", - "status", - "refresh" + "extension" ], - "type": "object", - "x-method": "_goose/unstable/providers/custom/update", - "x-side": "agent" + "description": "Persist a new extension to the user's global goose config.", + "x-side": "agent", + "x-method": "_goose/unstable/config/extensions/add" }, - "DefaultsReadRequest_unstable": { - "description": "Read Goose default provider and model configuration.", + "RemoveConfigExtensionRequest_unstable": { "type": "object", - "x-method": "_goose/unstable/defaults/read", - "x-side": "agent" - }, - "DefaultsReadResponse_unstable": { "properties": { - "modelId": { - "type": [ - "string", - "null" - ] - }, - "providerId": { - "type": [ - "string", - "null" - ] + "configKey": { + "type": "string" } }, - "type": "object", - "x-side": "agent" + "required": [ + "configKey" + ], + "description": "Remove a persisted extension from the user's global goose config.", + "x-side": "agent", + "x-method": "_goose/unstable/config/extensions/remove" }, - "DefaultsSaveRequest_unstable": { - "description": "Save Goose default provider and model configuration.", + "SetConfigExtensionEnabledRequest_unstable": { + "type": "object", "properties": { - "modelId": { - "type": [ - "string", - "null" - ] - }, - "providerId": { + "configKey": { "type": "string" + }, + "enabled": { + "type": "boolean" } }, "required": [ - "providerId" + "configKey", + "enabled" ], - "type": "object", - "x-method": "_goose/unstable/defaults/save", - "x-side": "agent" + "description": "Set the `enabled` flag for a persisted extension in the user's global goose config.", + "x-side": "agent", + "x-method": "_goose/unstable/config/extensions/set-enabled" }, - "DeleteSessionRequest": { - "description": "Delete a session.", + "GetSessionExtensionsRequest_unstable": { + "type": "object", "properties": { "sessionId": { "type": "string" @@ -477,2259 +694,1253 @@ "required": [ "sessionId" ], - "type": "object", - "x-method": "session/delete", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/session/extensions/list" }, - "DeleteSourceRequest_unstable": { - "description": "Delete a source and its on-disk directory by absolute path.", + "GetSessionExtensionsResponse_unstable": { + "type": "object", "properties": { - "path": { - "type": "string" - }, - "type": { - "$ref": "#/$defs/SourceType" + "extensions": { + "type": "array", + "items": {} } }, "required": [ - "type", - "path" + "extensions" ], - "type": "object", - "x-method": "_goose/unstable/sources/delete", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/session/extensions/list" }, - "DictationConfigRequest_unstable": { - "description": "Get the configuration status of all dictation providers.", + "ListProvidersRequest_unstable": { "type": "object", - "x-method": "_goose/unstable/dictation/config", - "x-side": "agent" - }, - "DictationConfigResponse_unstable": { - "description": "Dictation config response — map of provider name to status.", "properties": { - "providers": { - "additionalProperties": { - "$ref": "#/$defs/DictationProviderStatusEntry" + "providerIds": { + "type": "array", + "items": { + "type": "string" }, - "type": "object" + "description": "Only return entries for these providers. Empty means all.", + "default": [] + } + }, + "description": "List providers with setup metadata and the current model inventory snapshot.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/list" + }, + "ListProvidersResponse_unstable": { + "type": "object", + "properties": { + "entries": { + "type": "array", + "items": { + "$ref": "#/$defs/ProviderInventoryEntryDto" + } } }, "required": [ - "providers" + "entries" ], - "type": "object", - "x-method": "_goose/unstable/dictation/config", - "x-side": "agent" + "description": "Provider list response.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/list" }, - "DictationDownloadProgress": { + "ProviderInventoryEntryDto": { + "type": "object", "properties": { - "bytesDownloaded": { - "minimum": 0, - "type": "integer" + "providerId": { + "type": "string", + "description": "Provider identifier." }, - "error": { - "type": [ + "providerName": { + "type": "string", + "description": "Human-readable provider name." + }, + "description": { + "type": "string", + "description": "Description of the provider's capabilities." + }, + "defaultModel": { + "type": "string", + "description": "The default/recommended model for this provider." + }, + "configured": { + "type": "boolean", + "description": "Whether Goose has enough configuration to use this provider." + }, + "providerType": { + "type": "string", + "description": "Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`." + }, + "category": { + "$ref": "#/$defs/ProviderSetupCategoryDto", + "description": "Whether this inventory entry represents an agent provider or a model provider." + }, + "configKeys": { + "type": "array", + "items": { + "$ref": "#/$defs/ProviderConfigKey" + }, + "description": "Required configuration keys and setup metadata." + }, + "setupSteps": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Step-by-step setup instructions, when present." + }, + "supportsRefresh": { + "type": "boolean", + "description": "Whether this provider supports background inventory refresh." + }, + "refreshing": { + "type": "boolean", + "description": "Whether a refresh is currently in flight." + }, + "models": { + "type": "array", + "items": { + "$ref": "#/$defs/ProviderInventoryModelDto" + }, + "description": "The list of available models." + }, + "lastUpdatedAt": { + "type": [ "string", "null" - ] + ], + "description": "When this entry was last successfully refreshed (ISO 8601)." }, - "progressPercent": { - "format": "float", - "type": "number" + "lastRefreshAttemptAt": { + "type": [ + "string", + "null" + ], + "description": "When a refresh was most recently attempted (ISO 8601)." }, - "status": { - "description": "serde lowercase of DownloadStatus: \"downloading\" | \"completed\" | \"failed\" | \"cancelled\"", - "type": "string" + "lastRefreshError": { + "type": [ + "string", + "null" + ], + "description": "The last refresh failure message, if any." }, - "totalBytes": { - "minimum": 0, - "type": "integer" + "stale": { + "type": "boolean", + "description": "Whether we believe this data may be outdated." + }, + "modelSelectionHint": { + "type": [ + "string", + "null" + ], + "description": "Guidance message shown when this provider manages its own model selection externally." } }, "required": [ - "bytesDownloaded", - "totalBytes", - "progressPercent", - "status" + "providerId", + "providerName", + "description", + "defaultModel", + "configured", + "providerType", + "category", + "configKeys", + "setupSteps", + "supportsRefresh", + "refreshing", + "models", + "stale" ], - "type": "object" + "description": "Provider inventory entry." }, - "DictationLocalModelStatus": { + "ProviderSetupCategoryDto": { + "type": "string", + "enum": [ + "agent", + "model" + ] + }, + "ProviderConfigKey": { + "type": "object", "properties": { - "description": { + "name": { "type": "string" }, - "downloadInProgress": { + "required": { "type": "boolean" }, - "downloaded": { + "secret": { "type": "boolean" }, - "id": { - "type": "string" + "default": { + "type": [ + "string", + "null" + ], + "default": null }, - "label": { - "type": "string" + "oauthFlow": { + "type": "boolean", + "default": false }, - "sizeMb": { - "minimum": 0, - "type": "integer" + "deviceCodeFlow": { + "type": "boolean", + "default": false + }, + "primary": { + "type": "boolean", + "default": false } }, "required": [ - "id", - "label", - "description", - "sizeMb", - "downloaded", - "downloadInProgress" - ], - "type": "object" + "name", + "required", + "secret" + ] }, - "DictationModelCancelRequest_unstable": { - "description": "Cancel an in-flight download.", + "ProviderInventoryModelDto": { + "type": "object", "properties": { - "modelId": { - "type": "string" + "id": { + "type": "string", + "description": "Model identifier as the provider knows it." + }, + "name": { + "type": "string", + "description": "Human-readable display name." + }, + "family": { + "type": [ + "string", + "null" + ], + "description": "Model family for grouping in UI." + }, + "contextLimit": { + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0, + "description": "Context window size in tokens." + }, + "reasoning": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the model supports reasoning/extended thinking." + }, + "recommended": { + "type": "boolean", + "description": "Whether this model should appear in the compact recommended picker.", + "default": false } }, "required": [ - "modelId" + "id", + "name" ], - "type": "object", - "x-method": "_goose/unstable/dictation/models/cancel", - "x-side": "agent" + "description": "A single model in provider inventory." }, - "DictationModelDeleteRequest_unstable": { - "description": "Delete a downloaded local Whisper model from disk.", + "ProviderSupportedModelsListRequest_unstable": { + "type": "object", "properties": { - "modelId": { + "providerId": { "type": "string" } }, "required": [ - "modelId" + "providerId" ], - "type": "object", - "x-method": "_goose/unstable/dictation/models/delete", - "x-side": "agent" + "description": "List the raw model identifiers returned by a provider's live supported-models API.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/supported-models/list" }, - "DictationModelDownloadProgressRequest_unstable": { - "description": "Poll the progress of an in-flight download.", + "ProviderSupportedModelsListResponse_unstable": { + "type": "object", "properties": { - "modelId": { + "providerId": { "type": "string" + }, + "models": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "modelId" + "providerId", + "models" ], - "type": "object", - "x-method": "_goose/unstable/dictation/models/download/progress", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/providers/supported-models/list" }, - "DictationModelDownloadProgressResponse_unstable": { + "ProviderCatalogListRequest_unstable": { + "type": "object", "properties": { - "progress": { - "anyOf": [ - { - "$ref": "#/$defs/DictationDownloadProgress" - }, - { - "type": "null" - } - ], - "description": "None when no download is active for this model id." + "format": { + "type": [ + "string", + "null" + ] } }, - "type": "object", - "x-method": "_goose/unstable/dictation/models/download/progress", - "x-side": "agent" + "description": "List custom-provider catalog entries. Omit `format` to list all formats.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/catalog/list" }, - "DictationModelDownloadRequest_unstable": { - "description": "Kick off a background download of a local Whisper model.", + "ProviderCatalogListResponse_unstable": { + "type": "object", "properties": { - "modelId": { - "type": "string" + "providers": { + "type": "array", + "items": { + "$ref": "#/$defs/ProviderTemplateCatalogEntryDto" + } } }, "required": [ - "modelId" + "providers" ], - "type": "object", - "x-method": "_goose/unstable/dictation/models/download", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/providers/catalog/list" }, - "DictationModelOption": { + "ProviderTemplateCatalogEntryDto": { + "type": "object", "properties": { - "description": { + "providerId": { "type": "string" }, - "id": { + "name": { "type": "string" }, - "label": { + "format": { "type": "string" - } - }, - "required": [ - "id", - "label", - "description" - ], - "type": "object" - }, - "DictationModelSelectRequest_unstable": { - "description": "Persist the user's model selection for a given provider.", - "properties": { - "modelId": { + }, + "apiUrl": { "type": "string" }, - "provider": { + "modelCount": { + "type": "integer", + "minimum": 0 + }, + "docUrl": { + "type": "string" + }, + "envVar": { "type": "string" } }, "required": [ - "provider", - "modelId" - ], - "type": "object", - "x-method": "_goose/unstable/dictation/models/select", - "x-side": "agent" - }, - "DictationModelsListRequest_unstable": { - "description": "List available local Whisper models with their download status.", - "type": "object", - "x-method": "_goose/unstable/dictation/models/list", - "x-side": "agent" - }, - "DictationModelsListResponse_unstable": { + "providerId", + "name", + "format", + "apiUrl", + "modelCount", + "docUrl", + "envVar" + ] + }, + "ProviderSetupCatalogListRequest_unstable": { + "type": "object", + "description": "List provider setup catalog entries", + "x-side": "agent", + "x-method": "_goose/unstable/providers/setup/catalog/list" + }, + "ProviderSetupCatalogListResponse_unstable": { + "type": "object", "properties": { - "models": { + "providers": { + "type": "array", "items": { - "$ref": "#/$defs/DictationLocalModelStatus" - }, - "type": "array" + "$ref": "#/$defs/ProviderSetupCatalogEntryDto" + } } }, "required": [ - "models" + "providers" ], - "type": "object", - "x-method": "_goose/unstable/dictation/models/list", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/providers/setup/catalog/list" }, - "DictationProviderStatusEntry": { - "description": "Per-provider configuration status.", + "ProviderSetupCatalogEntryDto": { + "type": "object", "properties": { - "availableModels": { - "default": [], - "items": { - "$ref": "#/$defs/DictationModelOption" - }, - "type": "array" + "providerId": { + "type": "string" }, - "configKey": { - "type": [ - "string", - "null" - ] + "name": { + "type": "string" }, - "configured": { - "type": "boolean" + "category": { + "$ref": "#/$defs/ProviderSetupCategoryDto" }, - "defaultModel": { + "description": { + "type": "string" + }, + "setupMethod": { + "$ref": "#/$defs/ProviderSetupMethodDto" + }, + "nativeConnectQuery": { "type": [ "string", "null" ] }, - "description": { - "type": "string" + "fields": { + "type": "array", + "items": { + "$ref": "#/$defs/ProviderSetupFieldDto" + }, + "default": [] }, - "host": { + "binaryName": { "type": [ "string", "null" ] }, - "modelConfigKey": { + "docUrl": { "type": [ "string", "null" ] }, - "selectedModel": { + "group": { + "$ref": "#/$defs/ProviderSetupGroupDto" + }, + "showOnlyWhenInstalled": { + "type": "boolean" + }, + "aliases": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "supportsInstall": { + "type": "boolean" + }, + "supportsAuth": { + "type": "boolean" + }, + "supportsAuthStatus": { + "type": "boolean" + } + }, + "required": [ + "providerId", + "name", + "category", + "description", + "setupMethod", + "group", + "showOnlyWhenInstalled", + "supportsInstall", + "supportsAuth", + "supportsAuthStatus" + ] + }, + "ProviderSetupMethodDto": { + "type": "string", + "enum": [ + "none", + "single_api_key", + "config_fields", + "host_with_oauth_fallback", + "oauth_browser", + "oauth_device_code", + "cloud_credentials", + "local", + "cli_auth" + ] + }, + "ProviderSetupFieldDto": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "secret": { + "type": "boolean" + }, + "required": { + "type": "boolean" + }, + "placeholder": { "type": [ "string", "null" ] }, - "settingsPath": { + "defaultValue": { "type": [ "string", "null" ] - }, - "usesProviderConfig": { - "type": "boolean" } }, "required": [ - "configured", - "description", - "usesProviderConfig" - ], - "type": "object" + "key", + "label", + "secret", + "required" + ] }, - "DictationSecretDeleteRequest_unstable": { - "description": "Remove a dictation provider secret value.", + "ProviderSetupGroupDto": { + "type": "string", + "enum": [ + "default", + "additional" + ] + }, + "ProviderCatalogTemplateRequest_unstable": { + "type": "object", "properties": { - "provider": { + "providerId": { "type": "string" } }, "required": [ - "provider" + "providerId" ], - "type": "object", - "x-method": "_goose/unstable/dictation/secret/delete", - "x-side": "agent" + "description": "Return the editable template for one catalog provider.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/catalog/template" }, - "DictationSecretSaveRequest_unstable": { - "description": "Set a dictation provider secret value.", + "ProviderCatalogTemplateResponse_unstable": { + "type": "object", "properties": { - "provider": { - "type": "string" - }, - "value": { - "type": "string" + "template": { + "$ref": "#/$defs/ProviderTemplateDto" } }, "required": [ - "provider", - "value" + "template" ], - "type": "object", - "x-method": "_goose/unstable/dictation/secret/save", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/providers/catalog/template" }, - "DictationTranscribeRequest_unstable": { - "description": "Transcribe audio via a dictation provider.", + "ProviderTemplateDto": { + "type": "object", "properties": { - "audio": { - "description": "Base64-encoded audio data", + "providerId": { "type": "string" }, - "mimeType": { - "description": "MIME type (e.g. \"audio/wav\", \"audio/webm\")", + "name": { "type": "string" }, - "provider": { - "description": "Provider to use: \"openai\", \"groq\", \"elevenlabs\", or \"local\"", + "format": { "type": "string" - } - }, - "required": [ - "audio", - "mimeType", - "provider" - ], - "type": "object", - "x-method": "_goose/unstable/dictation/transcribe", - "x-side": "agent" - }, - "DictationTranscribeResponse_unstable": { - "description": "Transcription result.", - "properties": { - "text": { + }, + "apiUrl": { + "type": "string" + }, + "models": { + "type": "array", + "items": { + "$ref": "#/$defs/ProviderTemplateModelDto" + } + }, + "supportsStreaming": { + "type": "boolean" + }, + "envVar": { + "type": "string" + }, + "docUrl": { "type": "string" } }, "required": [ - "text" - ], - "type": "object", - "x-method": "_goose/unstable/dictation/transcribe", - "x-side": "agent" + "providerId", + "name", + "format", + "apiUrl", + "models", + "supportsStreaming", + "envVar", + "docUrl" + ] }, - "EmptyResponse": { - "description": "Empty success response for operations that return no data.", + "ProviderTemplateModelDto": { "type": "object", - "x-side": "agent" - }, - "EnvVariable": { - "description": "An environment variable to set when launching an MCP server.", "properties": { - "_meta": { - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", - "type": [ - "object", - "null" - ] + "id": { + "type": "string" }, "name": { - "description": "The name of the environment variable.", "type": "string" }, - "value": { - "description": "The value to set for the environment variable.", - "type": "string" + "contextLimit": { + "type": "integer", + "minimum": 0 + }, + "capabilities": { + "$ref": "#/$defs/ProviderTemplateCapabilitiesDto" + }, + "deprecated": { + "type": "boolean" } }, "required": [ + "id", "name", - "value" - ], - "type": "object" + "contextLimit", + "capabilities", + "deprecated" + ] }, - "ExportSessionRequest_unstable": { - "description": "Export a session as a JSON string.", + "ProviderTemplateCapabilitiesDto": { + "type": "object", "properties": { - "sessionId": { + "toolCall": { + "type": "boolean" + }, + "reasoning": { + "type": "boolean" + }, + "attachment": { + "type": "boolean" + }, + "temperature": { + "type": "boolean" + } + }, + "required": [ + "toolCall", + "reasoning", + "attachment", + "temperature" + ] + }, + "CustomProviderCreateRequest_unstable": { + "type": "object", + "properties": { + "engine": { + "type": "string" + }, + "displayName": { "type": "string" + }, + "apiUrl": { + "type": "string" + }, + "apiKey": { + "type": [ + "string", + "null" + ] + }, + "models": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "supportsStreaming": { + "type": [ + "boolean", + "null" + ] + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "default": {} + }, + "requiresAuth": { + "type": "boolean" + }, + "catalogProviderId": { + "type": [ + "string", + "null" + ] + }, + "basePath": { + "type": [ + "string", + "null" + ] + }, + "preservesThinking": { + "type": [ + "boolean", + "null" + ] } }, "required": [ - "sessionId" + "engine", + "displayName", + "apiUrl", + "requiresAuth" ], - "type": "object", - "x-method": "_goose/unstable/session/export", - "x-side": "agent" + "description": "Create a custom provider backed by Goose's declarative provider store.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/custom/create" }, - "ExportSessionResponse_unstable": { - "description": "Export session response — raw JSON of the goose session with `conversation`.", + "CustomProviderCreateResponse_unstable": { + "type": "object", "properties": { - "data": { + "providerId": { "type": "string" + }, + "status": { + "$ref": "#/$defs/ProviderConfigStatusDto" + }, + "refresh": { + "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" } }, "required": [ - "data" + "providerId", + "status", + "refresh" ], - "type": "object", - "x-method": "_goose/unstable/session/export", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/providers/custom/create" }, - "ExportSourceRequest_unstable": { - "description": "Export a source at an absolute path as a portable JSON payload.", + "ProviderConfigStatusDto": { + "type": "object", "properties": { - "path": { + "providerId": { "type": "string" }, - "type": { - "$ref": "#/$defs/SourceType" + "isConfigured": { + "type": "boolean" } }, "required": [ - "type", - "path" - ], + "providerId", + "isConfigured" + ] + }, + "RefreshProviderInventoryResponse_unstable": { "type": "object", - "x-method": "_goose/unstable/sources/export", - "x-side": "agent" + "properties": { + "started": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Which providers will be refreshed." + }, + "skipped": { + "type": "array", + "items": { + "$ref": "#/$defs/RefreshProviderInventorySkipDto" + }, + "description": "Which providers were skipped and why.", + "default": [] + } + }, + "required": [ + "started" + ], + "description": "Refresh acknowledgement.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/inventory/refresh" }, - "ExportSourceResponse_unstable": { + "RefreshProviderInventorySkipDto": { + "type": "object", "properties": { - "filename": { + "providerId": { "type": "string" }, - "json": { + "reason": { + "$ref": "#/$defs/RefreshProviderInventorySkipReasonDto" + } + }, + "required": [ + "providerId", + "reason" + ] + }, + "RefreshProviderInventorySkipReasonDto": { + "type": "string", + "enum": [ + "unknown_provider", + "not_configured", + "does_not_support_refresh", + "already_refreshing" + ] + }, + "CustomProviderReadRequest_unstable": { + "type": "object", + "properties": { + "providerId": { "type": "string" } }, "required": [ - "json", - "filename" + "providerId" ], + "description": "Read a declarative provider config. Custom configs are editable; bundled configs are read-only.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/custom/read" + }, + "CustomProviderReadResponse_unstable": { "type": "object", - "x-method": "_goose/unstable/sources/export", - "x-side": "agent" + "properties": { + "provider": { + "$ref": "#/$defs/CustomProviderConfigDto" + }, + "editable": { + "type": "boolean" + }, + "status": { + "$ref": "#/$defs/ProviderConfigStatusDto" + } + }, + "required": [ + "provider", + "editable", + "status" + ], + "x-side": "agent", + "x-method": "_goose/unstable/providers/custom/read" }, - "ExtRequest": { + "CustomProviderConfigDto": { + "type": "object", "properties": { - "id": { + "providerId": { "type": "string" }, - "method": { + "engine": { "type": "string" }, - "params": { - "anyOf": [ - { - "anyOf": [ - { - "allOf": [ - { - "$ref": "#/$defs/AddExtensionRequest_unstable" - } - ], - "description": "Params for _goose/unstable/session/extensions/add", - "title": "AddExtensionRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/RemoveExtensionRequest_unstable" - } - ], - "description": "Params for _goose/unstable/session/extensions/remove", - "title": "RemoveExtensionRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GetToolsRequest_unstable" - } - ], - "description": "Params for _goose/unstable/tools/list", - "title": "GetToolsRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GooseToolCallRequest_unstable" - } - ], - "description": "Params for _goose/unstable/tools/call", - "title": "GooseToolCallRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ReadResourceRequest_unstable" - } - ], - "description": "Params for _goose/unstable/resources/read", - "title": "ReadResourceRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/UpdateWorkingDirRequest_unstable" - } - ], - "description": "Params for _goose/unstable/session/working-dir/update", - "title": "UpdateWorkingDirRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/SetSessionSystemPromptRequest_unstable" - } - ], - "description": "Params for _goose/unstable/session/system-prompt/set", - "title": "SetSessionSystemPromptRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DeleteSessionRequest" - } - ], - "description": "Params for session/delete", - "title": "DeleteSessionRequest" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GetConfigExtensionsRequest_unstable" - } - ], - "description": "Params for _goose/unstable/config/extensions/list", - "title": "GetConfigExtensionsRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GetAvailableExtensionsRequest_unstable" - } - ], - "description": "Params for _goose/unstable/extensions/available", - "title": "GetAvailableExtensionsRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/AddConfigExtensionRequest_unstable" - } - ], - "description": "Params for _goose/unstable/config/extensions/add", - "title": "AddConfigExtensionRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/RemoveConfigExtensionRequest_unstable" - } - ], - "description": "Params for _goose/unstable/config/extensions/remove", - "title": "RemoveConfigExtensionRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/SetConfigExtensionEnabledRequest_unstable" - } - ], - "description": "Params for _goose/unstable/config/extensions/set-enabled", - "title": "SetConfigExtensionEnabledRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GetSessionExtensionsRequest_unstable" - } - ], - "description": "Params for _goose/unstable/session/extensions/list", - "title": "GetSessionExtensionsRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ListProvidersRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/list", - "title": "ListProvidersRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderSupportedModelsListRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/supported-models/list", - "title": "ProviderSupportedModelsListRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderCatalogListRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/catalog/list", - "title": "ProviderCatalogListRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderSetupCatalogListRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/setup/catalog/list", - "title": "ProviderSetupCatalogListRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderCatalogTemplateRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/catalog/template", - "title": "ProviderCatalogTemplateRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/CustomProviderCreateRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/custom/create", - "title": "CustomProviderCreateRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/CustomProviderReadRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/custom/read", - "title": "CustomProviderReadRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/CustomProviderUpdateRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/custom/update", - "title": "CustomProviderUpdateRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/CustomProviderDeleteRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/custom/delete", - "title": "CustomProviderDeleteRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/RefreshProviderInventoryRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/inventory/refresh", - "title": "RefreshProviderInventoryRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderConfigReadRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/config/read", - "title": "ProviderConfigReadRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderConfigStatusRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/config/status", - "title": "ProviderConfigStatusRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderConfigSaveRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/config/save", - "title": "ProviderConfigSaveRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderConfigDeleteRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/config/delete", - "title": "ProviderConfigDeleteRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderConfigAuthenticateRequest_unstable" - } - ], - "description": "Params for _goose/unstable/providers/config/authenticate", - "title": "ProviderConfigAuthenticateRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/PreferencesReadRequest_unstable" - } - ], - "description": "Params for _goose/unstable/preferences/read", - "title": "PreferencesReadRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/PreferencesSaveRequest_unstable" - } - ], - "description": "Params for _goose/unstable/preferences/save", - "title": "PreferencesSaveRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/PreferencesRemoveRequest_unstable" - } - ], - "description": "Params for _goose/unstable/preferences/remove", - "title": "PreferencesRemoveRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DefaultsReadRequest_unstable" - } - ], - "description": "Params for _goose/unstable/defaults/read", - "title": "DefaultsReadRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DefaultsSaveRequest_unstable" - } - ], - "description": "Params for _goose/unstable/defaults/save", - "title": "DefaultsSaveRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/OnboardingImportScanRequest_unstable" - } - ], - "description": "Params for _goose/unstable/onboarding/import/scan", - "title": "OnboardingImportScanRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/OnboardingImportApplyRequest_unstable" - } - ], - "description": "Params for _goose/unstable/onboarding/import/apply", - "title": "OnboardingImportApplyRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ExportSessionRequest_unstable" - } - ], - "description": "Params for _goose/unstable/session/export", - "title": "ExportSessionRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ImportSessionRequest_unstable" - } - ], - "description": "Params for _goose/unstable/session/import", - "title": "ImportSessionRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/UpdateSessionProjectRequest_unstable" - } - ], - "description": "Params for _goose/unstable/session/project/update", - "title": "UpdateSessionProjectRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/RenameSessionRequest_unstable" - } - ], - "description": "Params for _goose/unstable/session/rename", - "title": "RenameSessionRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ArchiveSessionRequest_unstable" - } - ], - "description": "Params for _goose/unstable/session/archive", - "title": "ArchiveSessionRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/UnarchiveSessionRequest_unstable" - } - ], - "description": "Params for _goose/unstable/session/unarchive", - "title": "UnarchiveSessionRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/CreateSourceRequest_unstable" - } - ], - "description": "Params for _goose/unstable/sources/create", - "title": "CreateSourceRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ListSourcesRequest_unstable" - } - ], - "description": "Params for _goose/unstable/sources/list", - "title": "ListSourcesRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/UpdateSourceRequest_unstable" - } - ], - "description": "Params for _goose/unstable/sources/update", - "title": "UpdateSourceRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DeleteSourceRequest_unstable" - } - ], - "description": "Params for _goose/unstable/sources/delete", - "title": "DeleteSourceRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ExportSourceRequest_unstable" - } - ], - "description": "Params for _goose/unstable/sources/export", - "title": "ExportSourceRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ImportSourcesRequest_unstable" - } - ], - "description": "Params for _goose/unstable/sources/import", - "title": "ImportSourcesRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationTranscribeRequest_unstable" - } - ], - "description": "Params for _goose/unstable/dictation/transcribe", - "title": "DictationTranscribeRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationConfigRequest_unstable" - } - ], - "description": "Params for _goose/unstable/dictation/config", - "title": "DictationConfigRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationSecretSaveRequest_unstable" - } - ], - "description": "Params for _goose/unstable/dictation/secret/save", - "title": "DictationSecretSaveRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationSecretDeleteRequest_unstable" - } - ], - "description": "Params for _goose/unstable/dictation/secret/delete", - "title": "DictationSecretDeleteRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationModelsListRequest_unstable" - } - ], - "description": "Params for _goose/unstable/dictation/models/list", - "title": "DictationModelsListRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationModelDownloadRequest_unstable" - } - ], - "description": "Params for _goose/unstable/dictation/models/download", - "title": "DictationModelDownloadRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationModelDownloadProgressRequest_unstable" - } - ], - "description": "Params for _goose/unstable/dictation/models/download/progress", - "title": "DictationModelDownloadProgressRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationModelCancelRequest_unstable" - } - ], - "description": "Params for _goose/unstable/dictation/models/cancel", - "title": "DictationModelCancelRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationModelDeleteRequest_unstable" - } - ], - "description": "Params for _goose/unstable/dictation/models/delete", - "title": "DictationModelDeleteRequest_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationModelSelectRequest_unstable" - } - ], - "description": "Params for _goose/unstable/dictation/models/select", - "title": "DictationModelSelectRequest_unstable" - } - ] - }, - { - "description": "Untyped params", - "type": [ - "object", - "null" - ] - } - ] - } - }, - "required": [ - "id", - "method" - ], - "type": "object", - "x-docs-ignore": true - }, - "ExtResponse": { - "anyOf": [ - { - "properties": { - "id": { - "type": "string" - }, - "result": { - "anyOf": [ - { - "anyOf": [ - { - "allOf": [ - { - "$ref": "#/$defs/EmptyResponse" - } - ], - "title": "EmptyResponse" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GetToolsResponse_unstable" - } - ], - "title": "GetToolsResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GooseToolCallResponse_unstable" - } - ], - "title": "GooseToolCallResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ReadResourceResponse_unstable" - } - ], - "title": "ReadResourceResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GetConfigExtensionsResponse_unstable" - } - ], - "title": "GetConfigExtensionsResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GetAvailableExtensionsResponse_unstable" - } - ], - "title": "GetAvailableExtensionsResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GetSessionExtensionsResponse_unstable" - } - ], - "title": "GetSessionExtensionsResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ListProvidersResponse_unstable" - } - ], - "title": "ListProvidersResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderSupportedModelsListResponse_unstable" - } - ], - "title": "ProviderSupportedModelsListResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderCatalogListResponse_unstable" - } - ], - "title": "ProviderCatalogListResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderSetupCatalogListResponse_unstable" - } - ], - "title": "ProviderSetupCatalogListResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderCatalogTemplateResponse_unstable" - } - ], - "title": "ProviderCatalogTemplateResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/CustomProviderCreateResponse_unstable" - } - ], - "title": "CustomProviderCreateResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/CustomProviderReadResponse_unstable" - } - ], - "title": "CustomProviderReadResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/CustomProviderUpdateResponse_unstable" - } - ], - "title": "CustomProviderUpdateResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/CustomProviderDeleteResponse_unstable" - } - ], - "title": "CustomProviderDeleteResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" - } - ], - "title": "RefreshProviderInventoryResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderConfigReadResponse_unstable" - } - ], - "title": "ProviderConfigReadResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderConfigStatusResponse_unstable" - } - ], - "title": "ProviderConfigStatusResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ProviderConfigChangeResponse_unstable" - } - ], - "title": "ProviderConfigChangeResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/PreferencesReadResponse_unstable" - } - ], - "title": "PreferencesReadResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DefaultsReadResponse_unstable" - } - ], - "title": "DefaultsReadResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/OnboardingImportScanResponse_unstable" - } - ], - "title": "OnboardingImportScanResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/OnboardingImportApplyResponse_unstable" - } - ], - "title": "OnboardingImportApplyResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ExportSessionResponse_unstable" - } - ], - "title": "ExportSessionResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ImportSessionResponse_unstable" - } - ], - "title": "ImportSessionResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/CreateSourceResponse_unstable" - } - ], - "title": "CreateSourceResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ListSourcesResponse_unstable" - } - ], - "title": "ListSourcesResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/UpdateSourceResponse_unstable" - } - ], - "title": "UpdateSourceResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ExportSourceResponse_unstable" - } - ], - "title": "ExportSourceResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/ImportSourcesResponse_unstable" - } - ], - "title": "ImportSourcesResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationTranscribeResponse_unstable" - } - ], - "title": "DictationTranscribeResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationConfigResponse_unstable" - } - ], - "title": "DictationConfigResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationModelsListResponse_unstable" - } - ], - "title": "DictationModelsListResponse_unstable" - }, - { - "allOf": [ - { - "$ref": "#/$defs/DictationModelDownloadProgressResponse_unstable" - } - ], - "title": "DictationModelDownloadProgressResponse_unstable" - } - ] - }, - { - "description": "Untyped result" - } - ] - } - }, - "required": [ - "id" - ], - "title": "Success", - "type": "object" - }, - { - "properties": { - "error": { - "properties": { - "code": { - "type": "integer" - }, - "data": {}, - "message": { - "type": "string" - } - }, - "required": [ - "code", - "message" - ], - "type": "object" - }, - "id": { - "type": "string" - } - }, - "required": [ - "id", - "error" - ], - "title": "Error", - "type": "object" - } - ], - "x-docs-ignore": true - }, - "GetAvailableExtensionsRequest_unstable": { - "description": "List Goose-owned extension definitions available to configure or enable.", - "type": "object", - "x-method": "_goose/unstable/extensions/available", - "x-side": "agent" - }, - "GetAvailableExtensionsResponse_unstable": { - "properties": { - "extensions": { - "items": { - "$ref": "#/$defs/GooseExtension" - }, - "type": "array" - } - }, - "required": [ - "extensions" - ], - "type": "object", - "x-method": "_goose/unstable/extensions/available", - "x-side": "agent" - }, - "GetConfigExtensionsRequest_unstable": { - "description": "List configured extensions and any warnings.", - "type": "object", - "x-method": "_goose/unstable/config/extensions/list", - "x-side": "agent" - }, - "GetConfigExtensionsResponse_unstable": { - "description": "List configured extensions and any warnings.", - "properties": { - "extensions": { - "items": { - "$ref": "#/$defs/GooseExtensionEntry" - }, - "type": "array" - }, - "warnings": { - "default": [], - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "extensions" - ], - "type": "object", - "x-method": "_goose/unstable/config/extensions/list", - "x-side": "agent" - }, - "GetSessionExtensionsRequest_unstable": { - "properties": { - "sessionId": { - "type": "string" - } - }, - "required": [ - "sessionId" - ], - "type": "object", - "x-method": "_goose/unstable/session/extensions/list", - "x-side": "agent" - }, - "GetSessionExtensionsResponse_unstable": { - "properties": { - "extensions": { - "items": {}, - "type": "array" - } - }, - "required": [ - "extensions" - ], - "type": "object", - "x-method": "_goose/unstable/session/extensions/list", - "x-side": "agent" - }, - "GetToolsRequest_unstable": { - "description": "List all tools available in a session.", - "properties": { - "sessionId": { + "displayName": { "type": "string" - } - }, - "required": [ - "sessionId" - ], - "type": "object", - "x-method": "_goose/unstable/tools/list", - "x-side": "agent" - }, - "GetToolsResponse_unstable": { - "description": "Tools response.", - "properties": { - "tools": { - "description": "Array of tool info objects with `name`, `description`, `parameters`, and optional `permission`.", - "items": {}, - "type": "array" - } - }, - "required": [ - "tools" - ], - "type": "object", - "x-method": "_goose/unstable/tools/list", - "x-side": "agent" - }, - "GooseExtension": { - "oneOf": [ - { - "properties": { - "bundled": { - "type": [ - "boolean", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "display_name": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "timeout": { - "format": "uint64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "type": { - "const": "builtin", - "type": "string" - } - }, - "required": [ - "type", - "name" - ], - "type": "object" - }, - { - "properties": { - "bundled": { - "type": [ - "boolean", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "display_name": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "type": { - "const": "platform", - "type": "string" - } - }, - "required": [ - "type", - "name" - ], - "type": "object" }, - { - "properties": { - "bundled": { - "type": [ - "boolean", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "envKeys": { - "items": { - "type": "string" - }, - "type": "array" - }, - "server": { - "$ref": "#/$defs/McpServer" - }, - "socket": { - "type": [ - "string", - "null" - ] - }, - "timeout": { - "format": "uint64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "type": { - "const": "mcp", - "type": "string" - } - }, - "required": [ - "type", - "server" - ], - "type": "object" + "apiUrl": { + "type": "string" }, - { - "properties": { - "code": { - "type": "string" - }, - "dependencies": { - "items": { - "type": "string" - }, - "type": "array" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "timeout": { - "format": "uint64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "type": { - "const": "inline_python", - "type": "string" - } + "models": { + "type": "array", + "items": { + "type": "string" }, - "required": [ - "type", - "name", - "code" - ], - "type": "object" + "default": [] }, - { - "properties": { - "bundled": { - "type": [ - "boolean", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "instructions": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "tools": { - "items": {}, - "type": "array" - }, - "type": { - "const": "frontend", - "type": "string" - } + "supportsStreaming": { + "type": [ + "boolean", + "null" + ] + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" }, - "required": [ - "type", - "name" - ], - "type": "object" - } - ] - }, - "GooseExtensionEntry": { - "properties": { - "configKey": { + "default": {} + }, + "requiresAuth": { + "type": "boolean" + }, + "catalogProviderId": { "type": [ "string", "null" ] }, - "enabled": { + "basePath": { + "type": [ + "string", + "null" + ] + }, + "apiKeyEnv": { + "type": [ + "string", + "null" + ] + }, + "apiKeySet": { "type": "boolean" }, - "extension": { - "$ref": "#/$defs/GooseExtension" + "preservesThinking": { + "type": "boolean" } }, "required": [ - "extension", - "enabled" - ], - "type": "object" + "providerId", + "engine", + "displayName", + "apiUrl", + "requiresAuth", + "apiKeySet", + "preservesThinking" + ] }, - "GooseToolCallRequest_unstable": { - "description": "Call a tool from an extension.", + "CustomProviderUpdateRequest_unstable": { + "type": "object", "properties": { - "arguments": { - "default": null + "providerId": { + "type": "string" }, - "name": { + "engine": { "type": "string" }, - "sessionId": { + "displayName": { "type": "string" - } - }, - "required": [ - "sessionId", - "name" - ], - "type": "object", - "x-method": "_goose/unstable/tools/call", - "x-side": "agent" - }, - "GooseToolCallResponse_unstable": { - "description": "Tool call response.", - "properties": { - "_meta": {}, - "content": { - "default": [], - "items": {}, - "type": "array" }, - "isError": { - "type": "boolean" + "apiUrl": { + "type": "string" }, - "structuredContent": {} - }, - "required": [ - "isError" - ], - "type": "object", - "x-method": "_goose/unstable/tools/call", - "x-side": "agent" - }, - "HttpHeader": { - "description": "An HTTP header to set when making requests to the MCP server.", - "properties": { - "_meta": { - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "apiKey": { "type": [ - "object", + "string", "null" ] }, - "name": { - "description": "The name of the HTTP header.", - "type": "string" + "models": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] }, - "value": { - "description": "The value to set for the HTTP header.", - "type": "string" - } - }, - "required": [ - "name", - "value" - ], - "type": "object" - }, - "ImportSessionRequest_unstable": { - "description": "Import a session from a JSON string.", - "properties": { - "data": { - "type": "string" - } - }, - "required": [ - "data" - ], - "type": "object", - "x-method": "_goose/unstable/session/import", - "x-side": "agent" - }, - "ImportSessionResponse_unstable": { - "description": "Import session response — metadata about the newly created session.", - "properties": { - "messageCount": { - "minimum": 0, - "type": "integer" + "supportsStreaming": { + "type": [ + "boolean", + "null" + ] }, - "sessionId": { - "type": "string" + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "default": {} }, - "title": { + "requiresAuth": { + "type": "boolean" + }, + "catalogProviderId": { "type": [ "string", "null" ] }, - "updatedAt": { + "basePath": { "type": [ "string", "null" ] - } - }, - "required": [ - "sessionId", - "messageCount" - ], - "type": "object", - "x-method": "_goose/unstable/session/import", - "x-side": "agent" - }, - "ImportSourcesRequest_unstable": { - "description": "Import a source from a JSON export payload produced by `_goose/unstable/sources/export`.\nThe imported source is written into the explicit target scope; on name\ncollisions a `-imported` suffix is appended.", - "properties": { - "data": { - "type": "string" }, - "target": { - "$ref": "#/$defs/SourceScope" - } - }, - "required": [ - "data", - "target" - ], - "type": "object", - "x-method": "_goose/unstable/sources/import", - "x-side": "agent" - }, - "ImportSourcesResponse_unstable": { - "properties": { - "sources": { - "items": { - "$ref": "#/$defs/SourceEntry" - }, - "type": "array" + "preservesThinking": { + "type": [ + "boolean", + "null" + ] } }, "required": [ - "sources" + "providerId", + "engine", + "displayName", + "apiUrl", + "requiresAuth" ], - "type": "object", - "x-method": "_goose/unstable/sources/import", - "x-side": "agent" - }, - "ListProvidersRequest_unstable": { - "description": "List providers with setup metadata and the current model inventory snapshot.", - "properties": { - "providerIds": { - "default": [], - "description": "Only return entries for these providers. Empty means all.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "type": "object", - "x-method": "_goose/unstable/providers/list", - "x-side": "agent" + "description": "Update a custom provider backed by Goose's declarative provider store.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/custom/update" }, - "ListProvidersResponse_unstable": { - "description": "Provider list response.", - "properties": { - "entries": { - "items": { - "$ref": "#/$defs/ProviderInventoryEntryDto" - }, - "type": "array" - } - }, - "required": [ - "entries" - ], + "CustomProviderUpdateResponse_unstable": { "type": "object", - "x-method": "_goose/unstable/providers/list", - "x-side": "agent" - }, - "ListSourcesRequest_unstable": { - "description": "List discovered sources.\n\nIf `type` is omitted or `skill`, this lists filesystem/plugin skills only.\nBoth global and project-scoped skills are included when `project_dir` is\nset. If `type` is `builtinSkill`, this lists shipped read-only built-in\nskills.", "properties": { - "includeProjectSources": { - "default": false, - "description": "When true, also scan the working directories of all known projects for\nproject-scoped sources (e.g. skills stored under `{workingDir}/.agents/skills/`).", - "type": "boolean" + "providerId": { + "type": "string" }, - "projectDir": { - "type": [ - "string", - "null" - ] + "status": { + "$ref": "#/$defs/ProviderConfigStatusDto" }, - "type": { - "anyOf": [ - { - "$ref": "#/$defs/SourceType" - }, - { - "type": "null" - } - ] + "refresh": { + "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" } }, - "type": "object", - "x-method": "_goose/unstable/sources/list", - "x-side": "agent" + "required": [ + "providerId", + "status", + "refresh" + ], + "x-side": "agent", + "x-method": "_goose/unstable/providers/custom/update" }, - "ListSourcesResponse_unstable": { - "properties": { - "sources": { - "items": { - "$ref": "#/$defs/SourceEntry" - }, - "type": "array" + "CustomProviderDeleteRequest_unstable": { + "type": "object", + "properties": { + "providerId": { + "type": "string" } }, "required": [ - "sources" + "providerId" ], - "type": "object", - "x-method": "_goose/unstable/sources/list", - "x-side": "agent" + "description": "Delete a custom provider from Goose's declarative provider store.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/custom/delete" }, - "McpServer": { - "anyOf": [ - { - "$ref": "#/$defs/McpServerHttp", - "description": "HTTP transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.http` is `true`.", - "properties": { - "type": { - "const": "http", - "type": "string" - } - }, - "required": [ - "type" - ], - "type": "object" - }, - { - "$ref": "#/$defs/McpServerSse", - "description": "SSE transport configuration\n\nOnly available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`.", - "properties": { - "type": { - "const": "sse", - "type": "string" - } - }, - "required": [ - "type" - ], - "type": "object" + "CustomProviderDeleteResponse_unstable": { + "type": "object", + "properties": { + "providerId": { + "type": "string" }, - { - "$ref": "#/$defs/McpServerStdio", - "description": "Stdio transport configuration\n\nAll Agents MUST support this transport." + "refresh": { + "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" } + }, + "required": [ + "providerId", + "refresh" ], - "description": "Configuration for connecting to an MCP (Model Context Protocol) server.\n\nMCP servers provide tools and context that the agent can use when\nprocessing prompts.\n\nSee protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)" + "x-side": "agent", + "x-method": "_goose/unstable/providers/custom/delete" }, - "McpServerHttp": { - "description": "HTTP transport configuration for MCP.", + "RefreshProviderInventoryRequest_unstable": { + "type": "object", "properties": { - "_meta": { - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", - "type": [ - "object", - "null" - ] - }, - "headers": { - "description": "HTTP headers to set when making requests to the MCP server.", + "providerIds": { + "type": "array", "items": { - "$ref": "#/$defs/HttpHeader" + "type": "string" }, - "type": "array" - }, - "name": { - "description": "Human-readable name identifying this MCP server.", - "type": "string" - }, - "type": { - "const": "http", - "type": "string" - }, - "url": { - "description": "URL to the MCP server.", + "description": "Which providers to refresh. Empty means all known providers.", + "default": [] + } + }, + "description": "Trigger a background refresh of provider inventories.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/inventory/refresh" + }, + "ProviderConfigReadRequest_unstable": { + "type": "object", + "properties": { + "providerId": { "type": "string" } }, "required": [ - "type", - "name", - "url", - "headers" + "providerId" ], - "type": "object" + "description": "Read saved configuration field values for one provider.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/config/read" }, - "McpServerSse": { - "description": "SSE transport configuration for MCP.", + "ProviderConfigReadResponse_unstable": { + "type": "object", "properties": { - "_meta": { - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", - "type": [ - "object", - "null" - ] - }, - "headers": { - "description": "HTTP headers to set when making requests to the MCP server.", + "fields": { + "type": "array", "items": { - "$ref": "#/$defs/HttpHeader" - }, - "type": "array" - }, - "name": { - "description": "Human-readable name identifying this MCP server.", - "type": "string" - }, - "type": { - "const": "sse", - "type": "string" - }, - "url": { - "description": "URL to the MCP server.", - "type": "string" + "$ref": "#/$defs/ProviderConfigFieldValueDto" + } } }, "required": [ - "type", - "name", - "url", - "headers" + "fields" ], - "type": "object" + "x-side": "agent", + "x-method": "_goose/unstable/providers/config/read" }, - "McpServerStdio": { - "description": "Stdio transport configuration for MCP.", + "ProviderConfigFieldValueDto": { + "type": "object", "properties": { - "_meta": { - "additionalProperties": {}, - "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "key": { + "type": "string" + }, + "value": { "type": [ - "object", + "string", "null" - ] - }, - "args": { - "description": "Command-line arguments to pass to the MCP server.", - "items": { - "type": "string" - }, - "type": "array" + ], + "default": null }, - "command": { - "description": "Path to the MCP server executable.", - "type": "string" + "isSet": { + "type": "boolean" }, - "env": { - "description": "Environment variables to set when launching the MCP server.", - "items": { - "$ref": "#/$defs/EnvVariable" - }, - "type": "array" + "isSecret": { + "type": "boolean" }, - "name": { - "description": "Human-readable name identifying this MCP server.", - "type": "string" + "required": { + "type": "boolean" } }, "required": [ - "name", - "command", - "args", - "env" - ], - "type": "object" + "key", + "isSet", + "isSecret", + "required" + ] }, - "OnboardingImportApplyRequest_unstable": { - "description": "Import selected onboarding candidates.", + "ProviderConfigStatusRequest_unstable": { + "type": "object", "properties": { - "candidateIds": { - "default": [], + "providerIds": { + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "enableImportedExtensions": { - "default": false, - "type": "boolean" + "default": [] } }, - "type": "object", - "x-method": "_goose/unstable/onboarding/import/apply", - "x-side": "agent" + "description": "Return provider configured statuses. Empty provider_ids means all providers.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/config/status" }, - "OnboardingImportApplyResponse_unstable": { + "ProviderConfigStatusResponse_unstable": { + "type": "object", "properties": { - "imported": { - "$ref": "#/$defs/OnboardingImportCounts" - }, - "providerDefaults": { - "anyOf": [ - { - "$ref": "#/$defs/DefaultsReadResponse_unstable" - }, - { - "type": "null" - } - ] - }, - "skipped": { - "$ref": "#/$defs/OnboardingImportCounts" - }, - "warnings": { - "default": [], + "statuses": { + "type": "array", "items": { - "type": "string" - }, - "type": "array" + "$ref": "#/$defs/ProviderConfigStatusDto" + } } }, "required": [ - "imported", - "skipped" + "statuses" ], - "type": "object", - "x-method": "_goose/unstable/onboarding/import/apply", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/providers/config/status" }, - "OnboardingImportCandidate": { + "ProviderConfigSaveRequest_unstable": { + "type": "object", "properties": { - "counts": { - "$ref": "#/$defs/OnboardingImportCounts" - }, - "displayName": { - "type": "string" - }, - "id": { - "type": "string" - }, - "path": { + "providerId": { "type": "string" }, - "sourceKind": { - "$ref": "#/$defs/OnboardingImportSourceKind" - }, - "warnings": { - "default": [], + "fields": { + "type": "array", "items": { - "type": "string" - }, - "type": "array" + "$ref": "#/$defs/ProviderConfigFieldUpdate" + } } }, "required": [ - "id", - "sourceKind", - "displayName", - "path", - "counts" + "providerId", + "fields" ], - "type": "object" + "description": "Save provider configuration fields and start an inventory refresh when supported.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/config/save" }, - "OnboardingImportCounts": { + "ProviderConfigFieldUpdate": { + "type": "object", "properties": { - "extensions": { - "minimum": 0, - "type": "integer" - }, - "preferences": { - "minimum": 0, - "type": "integer" - }, - "projects": { - "minimum": 0, - "type": "integer" - }, - "providers": { - "minimum": 0, - "type": "integer" + "key": { + "type": "string" }, - "sessions": { - "minimum": 0, - "type": "integer" + "value": { + "type": "string" + } + }, + "required": [ + "key", + "value" + ] + }, + "ProviderConfigChangeResponse_unstable": { + "type": "object", + "properties": { + "status": { + "$ref": "#/$defs/ProviderConfigStatusDto" }, - "skills": { - "minimum": 0, - "type": "integer" + "refresh": { + "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" } }, "required": [ - "providers", - "extensions", - "sessions", - "skills", - "projects", - "preferences" + "status", + "refresh" ], - "type": "object" + "x-side": "agent" }, - "OnboardingImportScanRequest_unstable": { - "description": "Scan for existing Goose and compatible app data that onboarding can import.", + "ProviderConfigDeleteRequest_unstable": { + "type": "object", "properties": { - "sources": { - "default": [], - "description": "Empty means all supported import sources.", - "items": { - "$ref": "#/$defs/OnboardingImportSourceKind" - }, - "type": "array" + "providerId": { + "type": "string" } }, - "type": "object", - "x-method": "_goose/unstable/onboarding/import/scan", - "x-side": "agent" + "required": [ + "providerId" + ], + "description": "Delete provider configuration fields and start an inventory refresh when supported.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/config/delete" }, - "OnboardingImportScanResponse_unstable": { + "ProviderConfigAuthenticateRequest_unstable": { + "type": "object", "properties": { - "candidates": { - "items": { - "$ref": "#/$defs/OnboardingImportCandidate" - }, - "type": "array" + "providerId": { + "type": "string" } }, "required": [ - "candidates" + "providerId" ], - "type": "object", - "x-method": "_goose/unstable/onboarding/import/scan", - "x-side": "agent" + "description": "Run a provider-owned native authentication flow and start an inventory refresh when supported.", + "x-side": "agent", + "x-method": "_goose/unstable/providers/config/authenticate" }, - "OnboardingImportSourceKind": { - "description": "Sources that onboarding knows how to discover and import.", - "enum": [ - "goose_config", - "claude_desktop" - ], - "type": "string" + "PreferencesReadRequest_unstable": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "items": { + "$ref": "#/$defs/PreferenceKey" + }, + "default": [] + } + }, + "description": "Read allowlisted user preferences. Empty `keys` means all supported preferences.", + "x-side": "agent", + "x-method": "_goose/unstable/preferences/read" }, "PreferenceKey": { + "type": "string", "enum": [ "autoCompactThreshold", "voiceAutoSubmitPhrases", "voiceDictationProvider", "voiceDictationPreferredMic" + ] + }, + "PreferencesReadResponse_unstable": { + "type": "object", + "properties": { + "values": { + "type": "array", + "items": { + "$ref": "#/$defs/PreferenceValue" + } + } + }, + "required": [ + "values" ], - "type": "string" + "x-side": "agent", + "x-method": "_goose/unstable/preferences/read" }, "PreferenceValue": { + "type": "object", "properties": { "key": { "$ref": "#/$defs/PreferenceKey" @@ -2740,1262 +1951,1974 @@ }, "required": [ "key" - ], - "type": "object" + ] }, - "PreferencesReadRequest_unstable": { - "description": "Read allowlisted user preferences. Empty `keys` means all supported preferences.", - "properties": { - "keys": { - "default": [], - "items": { - "$ref": "#/$defs/PreferenceKey" - }, - "type": "array" - } - }, + "PreferencesSaveRequest_unstable": { "type": "object", - "x-method": "_goose/unstable/preferences/read", - "x-side": "agent" - }, - "PreferencesReadResponse_unstable": { "properties": { "values": { + "type": "array", "items": { "$ref": "#/$defs/PreferenceValue" }, - "type": "array" + "default": [] } }, - "required": [ - "values" - ], - "type": "object", - "x-method": "_goose/unstable/preferences/read", - "x-side": "agent" + "description": "Save allowlisted user preferences.", + "x-side": "agent", + "x-method": "_goose/unstable/preferences/save" }, "PreferencesRemoveRequest_unstable": { - "description": "Remove allowlisted user preferences.", + "type": "object", "properties": { "keys": { - "default": [], + "type": "array", "items": { "$ref": "#/$defs/PreferenceKey" }, - "type": "array" + "default": [] } }, + "description": "Remove allowlisted user preferences.", + "x-side": "agent", + "x-method": "_goose/unstable/preferences/remove" + }, + "DefaultsReadRequest_unstable": { "type": "object", - "x-method": "_goose/unstable/preferences/remove", - "x-side": "agent" + "description": "Read Goose default provider and model configuration.", + "x-side": "agent", + "x-method": "_goose/unstable/defaults/read" }, - "PreferencesSaveRequest_unstable": { - "description": "Save allowlisted user preferences.", + "DefaultsReadResponse_unstable": { + "type": "object", "properties": { - "values": { - "default": [], - "items": { - "$ref": "#/$defs/PreferenceValue" - }, - "type": "array" + "providerId": { + "type": [ + "string", + "null" + ] + }, + "modelId": { + "type": [ + "string", + "null" + ] } }, - "type": "object", - "x-method": "_goose/unstable/preferences/save", "x-side": "agent" }, - "ProviderCatalogListRequest_unstable": { - "description": "List custom-provider catalog entries. Omit `format` to list all formats.", + "DefaultsSaveRequest_unstable": { + "type": "object", "properties": { - "format": { + "providerId": { + "type": "string" + }, + "modelId": { "type": [ "string", "null" ] } }, - "type": "object", - "x-method": "_goose/unstable/providers/catalog/list", - "x-side": "agent" + "required": [ + "providerId" + ], + "description": "Save Goose default provider and model configuration.", + "x-side": "agent", + "x-method": "_goose/unstable/defaults/save" }, - "ProviderCatalogListResponse_unstable": { + "OnboardingImportScanRequest_unstable": { + "type": "object", "properties": { - "providers": { + "sources": { + "type": "array", "items": { - "$ref": "#/$defs/ProviderTemplateCatalogEntryDto" + "$ref": "#/$defs/OnboardingImportSourceKind" }, - "type": "array" + "description": "Empty means all supported import sources.", + "default": [] } }, - "required": [ - "providers" + "description": "Scan for existing Goose and compatible app data that onboarding can import.", + "x-side": "agent", + "x-method": "_goose/unstable/onboarding/import/scan" + }, + "OnboardingImportSourceKind": { + "type": "string", + "enum": [ + "goose_config", + "claude_desktop" ], + "description": "Sources that onboarding knows how to discover and import." + }, + "OnboardingImportScanResponse_unstable": { "type": "object", - "x-method": "_goose/unstable/providers/catalog/list", - "x-side": "agent" + "properties": { + "candidates": { + "type": "array", + "items": { + "$ref": "#/$defs/OnboardingImportCandidate" + } + } + }, + "required": [ + "candidates" + ], + "x-side": "agent", + "x-method": "_goose/unstable/onboarding/import/scan" }, - "ProviderCatalogTemplateRequest_unstable": { - "description": "Return the editable template for one catalog provider.", + "OnboardingImportCandidate": { + "type": "object", "properties": { - "providerId": { + "id": { + "type": "string" + }, + "sourceKind": { + "$ref": "#/$defs/OnboardingImportSourceKind" + }, + "displayName": { + "type": "string" + }, + "path": { "type": "string" + }, + "counts": { + "$ref": "#/$defs/OnboardingImportCounts" + }, + "warnings": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + } + }, + "required": [ + "id", + "sourceKind", + "displayName", + "path", + "counts" + ] + }, + "OnboardingImportCounts": { + "type": "object", + "properties": { + "providers": { + "type": "integer", + "minimum": 0 + }, + "extensions": { + "type": "integer", + "minimum": 0 + }, + "sessions": { + "type": "integer", + "minimum": 0 + }, + "skills": { + "type": "integer", + "minimum": 0 + }, + "projects": { + "type": "integer", + "minimum": 0 + }, + "preferences": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "providers", + "extensions", + "sessions", + "skills", + "projects", + "preferences" + ] + }, + "OnboardingImportApplyRequest_unstable": { + "type": "object", + "properties": { + "candidateIds": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "enableImportedExtensions": { + "type": "boolean", + "default": false + } + }, + "description": "Import selected onboarding candidates.", + "x-side": "agent", + "x-method": "_goose/unstable/onboarding/import/apply" + }, + "OnboardingImportApplyResponse_unstable": { + "type": "object", + "properties": { + "imported": { + "$ref": "#/$defs/OnboardingImportCounts" + }, + "skipped": { + "$ref": "#/$defs/OnboardingImportCounts" + }, + "warnings": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "providerDefaults": { + "anyOf": [ + { + "$ref": "#/$defs/DefaultsReadResponse_unstable" + }, + { + "type": "null" + } + ] } }, "required": [ - "providerId" + "imported", + "skipped" ], - "type": "object", - "x-method": "_goose/unstable/providers/catalog/template", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/onboarding/import/apply" }, - "ProviderCatalogTemplateResponse_unstable": { - "properties": { - "template": { - "$ref": "#/$defs/ProviderTemplateDto" - } - }, - "required": [ - "template" - ], + "ExportSessionRequest_unstable": { "type": "object", - "x-method": "_goose/unstable/providers/catalog/template", - "x-side": "agent" - }, - "ProviderConfigAuthenticateRequest_unstable": { - "description": "Run a provider-owned native authentication flow and start an inventory refresh when supported.", "properties": { - "providerId": { + "sessionId": { "type": "string" } }, "required": [ - "providerId" + "sessionId" ], - "type": "object", - "x-method": "_goose/unstable/providers/config/authenticate", - "x-side": "agent" + "description": "Export a session as a JSON string.", + "x-side": "agent", + "x-method": "_goose/unstable/session/export" }, - "ProviderConfigChangeResponse_unstable": { - "properties": { - "refresh": { - "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" - }, - "status": { - "$ref": "#/$defs/ProviderConfigStatusDto" - } - }, - "required": [ - "status", - "refresh" - ], + "ExportSessionResponse_unstable": { "type": "object", - "x-side": "agent" - }, - "ProviderConfigDeleteRequest_unstable": { - "description": "Delete provider configuration fields and start an inventory refresh when supported.", "properties": { - "providerId": { + "data": { "type": "string" } }, "required": [ - "providerId" + "data" ], - "type": "object", - "x-method": "_goose/unstable/providers/config/delete", - "x-side": "agent" + "description": "Export session response — raw JSON of the goose session with `conversation`.", + "x-side": "agent", + "x-method": "_goose/unstable/session/export" }, - "ProviderConfigFieldUpdate": { + "ImportSessionRequest_unstable": { + "type": "object", "properties": { - "key": { - "type": "string" - }, - "value": { + "data": { "type": "string" } }, "required": [ - "key", - "value" + "data" ], - "type": "object" + "description": "Import a session from a JSON string.", + "x-side": "agent", + "x-method": "_goose/unstable/session/import" }, - "ProviderConfigFieldValueDto": { + "ImportSessionResponse_unstable": { + "type": "object", "properties": { - "isSecret": { - "type": "boolean" - }, - "isSet": { - "type": "boolean" - }, - "key": { + "sessionId": { "type": "string" }, - "required": { - "type": "boolean" + "title": { + "type": [ + "string", + "null" + ] }, - "value": { - "default": null, + "updatedAt": { "type": [ "string", "null" ] + }, + "messageCount": { + "type": "integer", + "minimum": 0 } }, "required": [ - "key", - "isSet", - "isSecret", - "required" + "sessionId", + "messageCount" ], - "type": "object" + "description": "Import session response — metadata about the newly created session.", + "x-side": "agent", + "x-method": "_goose/unstable/session/import" }, - "ProviderConfigKey": { + "UpdateSessionProjectRequest_unstable": { + "type": "object", "properties": { - "default": { - "default": null, + "sessionId": { + "type": "string" + }, + "projectId": { "type": [ "string", "null" ] - }, - "deviceCodeFlow": { - "default": false, - "type": "boolean" - }, - "name": { - "type": "string" - }, - "oauthFlow": { - "default": false, - "type": "boolean" - }, - "primary": { - "default": false, - "type": "boolean" - }, - "required": { - "type": "boolean" - }, - "secret": { - "type": "boolean" } }, "required": [ - "name", - "required", - "secret" + "sessionId" ], - "type": "object" + "description": "Update the project association for a session.", + "x-side": "agent", + "x-method": "_goose/unstable/session/project/update" }, - "ProviderConfigReadRequest_unstable": { - "description": "Read saved configuration field values for one provider.", + "RenameSessionRequest_unstable": { + "type": "object", "properties": { - "providerId": { + "sessionId": { + "type": "string" + }, + "title": { "type": "string" } }, "required": [ - "providerId" + "sessionId", + "title" ], - "type": "object", - "x-method": "_goose/unstable/providers/config/read", - "x-side": "agent" + "description": "Rename a session.", + "x-side": "agent", + "x-method": "_goose/unstable/session/rename" }, - "ProviderConfigReadResponse_unstable": { + "ArchiveSessionRequest_unstable": { + "type": "object", "properties": { - "fields": { - "items": { - "$ref": "#/$defs/ProviderConfigFieldValueDto" - }, - "type": "array" + "sessionId": { + "type": "string" } }, "required": [ - "fields" + "sessionId" ], - "type": "object", - "x-method": "_goose/unstable/providers/config/read", - "x-side": "agent" + "description": "Archive a session (soft delete).", + "x-side": "agent", + "x-method": "_goose/unstable/session/archive" }, - "ProviderConfigSaveRequest_unstable": { - "description": "Save provider configuration fields and start an inventory refresh when supported.", + "UnarchiveSessionRequest_unstable": { + "type": "object", "properties": { - "fields": { - "items": { - "$ref": "#/$defs/ProviderConfigFieldUpdate" - }, - "type": "array" - }, - "providerId": { + "sessionId": { "type": "string" } }, "required": [ - "providerId", - "fields" + "sessionId" ], - "type": "object", - "x-method": "_goose/unstable/providers/config/save", - "x-side": "agent" + "description": "Unarchive a previously archived session.", + "x-side": "agent", + "x-method": "_goose/unstable/session/unarchive" }, - "ProviderConfigStatusDto": { + "CreateSourceRequest_unstable": { + "type": "object", "properties": { - "isConfigured": { - "type": "boolean" + "type": { + "$ref": "#/$defs/SourceType" }, - "providerId": { + "name": { + "type": "string" + }, + "description": { "type": "string" + }, + "content": { + "type": "string" + }, + "target": { + "$ref": "#/$defs/SourceScope" + }, + "properties": { + "type": "object", + "additionalProperties": {}, + "description": "Arbitrary key/value metadata." } }, "required": [ - "providerId", - "isConfigured" + "type", + "name", + "description", + "content", + "target" ], - "type": "object" + "description": "Create a new source in an explicit target scope (global or project-scoped).", + "x-side": "agent", + "x-method": "_goose/unstable/sources/create" }, - "ProviderConfigStatusRequest_unstable": { - "description": "Return provider configured statuses. Empty provider_ids means all providers.", - "properties": { - "providerIds": { - "default": [], - "items": { - "type": "string" + "SourceType": { + "type": "string", + "enum": [ + "skill", + "builtinSkill", + "recipe", + "subrecipe", + "agent", + "project" + ], + "description": "The type of source entity." + }, + "SourceScope": { + "oneOf": [ + { + "type": "object", + "properties": { + "scope": { + "type": "string", + "const": "global" + } + }, + "required": [ + "scope" + ] + }, + { + "type": "object", + "properties": { + "projectDir": { + "type": "string" + }, + "scope": { + "type": "string", + "const": "projectDir" + } + }, + "required": [ + "scope", + "projectDir" + ] + }, + { + "type": "object", + "properties": { + "projectId": { + "type": "string" + }, + "scope": { + "type": "string", + "const": "projectId" + } }, - "type": "array" + "required": [ + "scope", + "projectId" + ] } - }, - "type": "object", - "x-method": "_goose/unstable/providers/config/status", - "x-side": "agent" + ], + "description": "Target scope for creating or importing sources." }, - "ProviderConfigStatusResponse_unstable": { + "CreateSourceResponse_unstable": { + "type": "object", "properties": { - "statuses": { - "items": { - "$ref": "#/$defs/ProviderConfigStatusDto" - }, - "type": "array" + "source": { + "$ref": "#/$defs/SourceEntry" } }, "required": [ - "statuses" + "source" ], - "type": "object", - "x-method": "_goose/unstable/providers/config/status", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/sources/create" }, - "ProviderInventoryEntryDto": { - "description": "Provider inventory entry.", + "SourceEntry": { + "type": "object", "properties": { - "category": { - "$ref": "#/$defs/ProviderSetupCategoryDto", - "description": "Whether this inventory entry represents an agent provider or a model provider." - }, - "configKeys": { - "description": "Required configuration keys and setup metadata.", - "items": { - "$ref": "#/$defs/ProviderConfigKey" - }, - "type": "array" - }, - "configured": { - "description": "Whether Goose has enough configuration to use this provider.", - "type": "boolean" + "type": { + "$ref": "#/$defs/SourceType" }, - "defaultModel": { - "description": "The default/recommended model for this provider.", + "name": { "type": "string" }, "description": { - "description": "Description of the provider's capabilities.", "type": "string" }, - "lastRefreshAttemptAt": { - "description": "When a refresh was most recently attempted (ISO 8601).", - "type": [ - "string", - "null" - ] - }, - "lastRefreshError": { - "description": "The last refresh failure message, if any.", - "type": [ - "string", - "null" - ] - }, - "lastUpdatedAt": { - "description": "When this entry was last successfully refreshed (ISO 8601).", - "type": [ - "string", - "null" - ] - }, - "modelSelectionHint": { - "description": "Guidance message shown when this provider manages its own model selection externally.", - "type": [ - "string", - "null" - ] - }, - "models": { - "description": "The list of available models.", - "items": { - "$ref": "#/$defs/ProviderInventoryModelDto" - }, - "type": "array" - }, - "providerId": { - "description": "Provider identifier.", + "content": { "type": "string" }, - "providerName": { - "description": "Human-readable provider name.", - "type": "string" + "path": { + "type": "string", + "description": "Stable on-disk path identifying this source. Pass it back to\nupdate/delete/export to operate on this entry. Skills use the directory\ncontaining `SKILL.md`; projects use the project file path; built-in\nskills use `builtin://skills/` synthetic paths." }, - "providerType": { - "description": "Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`.", - "type": "string" + "global": { + "type": "boolean", + "description": "True when the source lives in the user's global sources directory; false\nwhen it lives inside a specific project." }, - "refreshing": { - "description": "Whether a refresh is currently in flight.", - "type": "boolean" + "writable": { + "type": "boolean", + "description": "True when this source can be modified through source CRUD methods.\nClient-provided bundled sources are returned as read-only.", + "default": false }, - "setupSteps": { - "description": "Step-by-step setup instructions, when present.", + "supportingFiles": { + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "stale": { - "description": "Whether we believe this data may be outdated.", - "type": "boolean" + "description": "Paths (absolute) of additional files that live alongside the source.\nOnly skills currently populate this; empty for other source types." }, - "supportsRefresh": { - "description": "Whether this provider supports background inventory refresh.", - "type": "boolean" + "properties": { + "type": "object", + "additionalProperties": {}, + "description": "Arbitrary key/value pairs for type-specific metadata (e.g. icon, color,\npreferredProvider for projects). Stored in the frontmatter." } }, "required": [ - "providerId", - "providerName", + "type", + "name", "description", - "defaultModel", - "configured", - "providerType", - "category", - "configKeys", - "setupSteps", - "supportsRefresh", - "refreshing", - "models", - "stale" + "content", + "path", + "global" ], - "type": "object" + "description": "A source discovered by Goose. Filesystem sources use an on-disk path;\nbuilt-in sources use a stable synthetic path. Sources may be either\n`global` (shared across all projects) or project-specific." }, - "ProviderInventoryModelDto": { - "description": "A single model in provider inventory.", + "ListSourcesRequest_unstable": { + "type": "object", "properties": { - "contextLimit": { - "description": "Context window size in tokens.", - "format": "uint", - "minimum": 0, - "type": [ - "integer", - "null" + "type": { + "anyOf": [ + { + "$ref": "#/$defs/SourceType" + }, + { + "type": "null" + } ] }, - "family": { - "description": "Model family for grouping in UI.", + "projectDir": { "type": [ "string", "null" ] }, - "id": { - "description": "Model identifier as the provider knows it.", - "type": "string" - }, - "name": { - "description": "Human-readable display name.", - "type": "string" - }, - "reasoning": { - "description": "Whether the model supports reasoning/extended thinking.", - "type": [ - "boolean", - "null" - ] - }, - "recommended": { - "default": false, - "description": "Whether this model should appear in the compact recommended picker.", - "type": "boolean" + "includeProjectSources": { + "type": "boolean", + "description": "When true, also scan the working directories of all known projects for\nproject-scoped sources (e.g. skills stored under `{workingDir}/.agents/skills/`).", + "default": false + } + }, + "description": "List discovered sources.\n\nIf `type` is omitted or `skill`, this lists filesystem/plugin skills only.\nBoth global and project-scoped skills are included when `project_dir` is\nset. If `type` is `builtinSkill`, this lists shipped read-only built-in\nskills.", + "x-side": "agent", + "x-method": "_goose/unstable/sources/list" + }, + "ListSourcesResponse_unstable": { + "type": "object", + "properties": { + "sources": { + "type": "array", + "items": { + "$ref": "#/$defs/SourceEntry" + } } }, "required": [ - "id", - "name" + "sources" ], - "type": "object" + "x-side": "agent", + "x-method": "_goose/unstable/sources/list" }, - "ProviderSetupCatalogEntryDto": { + "UpdateSourceRequest_unstable": { + "type": "object", "properties": { - "aliases": { - "default": [], - "items": { - "type": "string" - }, - "type": "array" + "type": { + "$ref": "#/$defs/SourceType" }, - "binaryName": { - "type": [ - "string", - "null" - ] + "path": { + "type": "string" }, - "category": { - "$ref": "#/$defs/ProviderSetupCategoryDto" + "name": { + "type": "string" }, "description": { "type": "string" }, - "docUrl": { - "type": [ - "string", - "null" - ] - }, - "fields": { - "default": [], - "items": { - "$ref": "#/$defs/ProviderSetupFieldDto" - }, - "type": "array" - }, - "group": { - "$ref": "#/$defs/ProviderSetupGroupDto" - }, - "name": { + "content": { "type": "string" }, - "nativeConnectQuery": { + "properties": { "type": [ - "string", + "object", "null" - ] - }, - "providerId": { - "type": "string" - }, - "setupMethod": { - "$ref": "#/$defs/ProviderSetupMethodDto" - }, - "showOnlyWhenInstalled": { - "type": "boolean" - }, - "supportsAuth": { - "type": "boolean" - }, - "supportsAuthStatus": { - "type": "boolean" - }, - "supportsInstall": { - "type": "boolean" + ], + "additionalProperties": {}, + "description": "When `Some`, replaces all stored properties on the source. When\n`None` (or omitted), the source's existing properties are\npreserved. Callers that don't model the full property bag (e.g.\nthe skills editor, which only edits name/description/content)\nshould omit this so per-skill metadata isn't silently erased." } }, "required": [ - "providerId", + "type", + "path", "name", - "category", "description", - "setupMethod", - "group", - "showOnlyWhenInstalled", - "supportsInstall", - "supportsAuth", - "supportsAuthStatus" + "content" ], - "type": "object" + "description": "Update an existing source's name, description, and content by absolute path.", + "x-side": "agent", + "x-method": "_goose/unstable/sources/update" }, - "ProviderSetupCatalogListRequest_unstable": { - "description": "List provider setup catalog entries", + "UpdateSourceResponse_unstable": { "type": "object", - "x-method": "_goose/unstable/providers/setup/catalog/list", - "x-side": "agent" + "properties": { + "source": { + "$ref": "#/$defs/SourceEntry" + } + }, + "required": [ + "source" + ], + "x-side": "agent", + "x-method": "_goose/unstable/sources/update" }, - "ProviderSetupCatalogListResponse_unstable": { + "DeleteSourceRequest_unstable": { + "type": "object", "properties": { - "providers": { - "items": { - "$ref": "#/$defs/ProviderSetupCatalogEntryDto" - }, - "type": "array" + "type": { + "$ref": "#/$defs/SourceType" + }, + "path": { + "type": "string" + } + }, + "required": [ + "type", + "path" + ], + "description": "Delete a source and its on-disk directory by absolute path.", + "x-side": "agent", + "x-method": "_goose/unstable/sources/delete" + }, + "ExportSourceRequest_unstable": { + "type": "object", + "properties": { + "type": { + "$ref": "#/$defs/SourceType" + }, + "path": { + "type": "string" } }, "required": [ - "providers" - ], - "type": "object", - "x-method": "_goose/unstable/providers/setup/catalog/list", - "x-side": "agent" - }, - "ProviderSetupCategoryDto": { - "enum": [ - "agent", - "model" + "type", + "path" ], - "type": "string" + "description": "Export a source at an absolute path as a portable JSON payload.", + "x-side": "agent", + "x-method": "_goose/unstable/sources/export" }, - "ProviderSetupFieldDto": { + "ExportSourceResponse_unstable": { + "type": "object", "properties": { - "defaultValue": { - "type": [ - "string", - "null" - ] - }, - "key": { + "json": { "type": "string" }, - "label": { + "filename": { "type": "string" - }, - "placeholder": { - "type": [ - "string", - "null" - ] - }, - "required": { - "type": "boolean" - }, - "secret": { - "type": "boolean" } }, "required": [ - "key", - "label", - "secret", - "required" - ], - "type": "object" - }, - "ProviderSetupGroupDto": { - "enum": [ - "default", - "additional" - ], - "type": "string" - }, - "ProviderSetupMethodDto": { - "enum": [ - "none", - "single_api_key", - "config_fields", - "host_with_oauth_fallback", - "oauth_browser", - "oauth_device_code", - "cloud_credentials", - "local", - "cli_auth" + "json", + "filename" ], - "type": "string" + "x-side": "agent", + "x-method": "_goose/unstable/sources/export" }, - "ProviderSupportedModelsListRequest_unstable": { - "description": "List the raw model identifiers returned by a provider's live supported-models API.", + "ImportSourcesRequest_unstable": { + "type": "object", "properties": { - "providerId": { + "data": { "type": "string" + }, + "target": { + "$ref": "#/$defs/SourceScope" } }, "required": [ - "providerId" + "data", + "target" ], - "type": "object", - "x-method": "_goose/unstable/providers/supported-models/list", - "x-side": "agent" + "description": "Import a source from a JSON export payload produced by `_goose/unstable/sources/export`.\nThe imported source is written into the explicit target scope; on name\ncollisions a `-imported` suffix is appended.", + "x-side": "agent", + "x-method": "_goose/unstable/sources/import" }, - "ProviderSupportedModelsListResponse_unstable": { + "ImportSourcesResponse_unstable": { + "type": "object", "properties": { - "models": { + "sources": { + "type": "array", "items": { - "type": "string" - }, - "type": "array" - }, - "providerId": { - "type": "string" + "$ref": "#/$defs/SourceEntry" + } } }, "required": [ - "providerId", - "models" + "sources" ], - "type": "object", - "x-method": "_goose/unstable/providers/supported-models/list", - "x-side": "agent" + "x-side": "agent", + "x-method": "_goose/unstable/sources/import" }, - "ProviderTemplateCapabilitiesDto": { + "DictationTranscribeRequest_unstable": { + "type": "object", "properties": { - "attachment": { - "type": "boolean" - }, - "reasoning": { - "type": "boolean" + "audio": { + "type": "string", + "description": "Base64-encoded audio data" }, - "temperature": { - "type": "boolean" + "mimeType": { + "type": "string", + "description": "MIME type (e.g. \"audio/wav\", \"audio/webm\")" }, - "toolCall": { - "type": "boolean" + "provider": { + "type": "string", + "description": "Provider to use: \"openai\", \"groq\", \"elevenlabs\", or \"local\"" } }, "required": [ - "toolCall", - "reasoning", - "attachment", - "temperature" + "audio", + "mimeType", + "provider" ], - "type": "object" + "description": "Transcribe audio via a dictation provider.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/transcribe" }, - "ProviderTemplateCatalogEntryDto": { + "DictationTranscribeResponse_unstable": { + "type": "object", "properties": { - "apiUrl": { - "type": "string" - }, - "docUrl": { - "type": "string" - }, - "envVar": { - "type": "string" - }, - "format": { - "type": "string" - }, - "modelCount": { - "minimum": 0, - "type": "integer" - }, - "name": { - "type": "string" - }, - "providerId": { + "text": { "type": "string" } }, "required": [ - "providerId", - "name", - "format", - "apiUrl", - "modelCount", - "docUrl", - "envVar" + "text" ], - "type": "object" + "description": "Transcription result.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/transcribe" }, - "ProviderTemplateDto": { + "DictationConfigRequest_unstable": { + "type": "object", + "description": "Get the configuration status of all dictation providers.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/config" + }, + "DictationConfigResponse_unstable": { + "type": "object", "properties": { - "apiUrl": { - "type": "string" + "providers": { + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/DictationProviderStatusEntry" + } + } + }, + "required": [ + "providers" + ], + "description": "Dictation config response — map of provider name to status.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/config" + }, + "DictationProviderStatusEntry": { + "type": "object", + "properties": { + "configured": { + "type": "boolean" }, - "docUrl": { - "type": "string" + "host": { + "type": [ + "string", + "null" + ] }, - "envVar": { + "description": { "type": "string" }, - "format": { - "type": "string" + "usesProviderConfig": { + "type": "boolean" }, - "models": { - "items": { - "$ref": "#/$defs/ProviderTemplateModelDto" - }, - "type": "array" + "settingsPath": { + "type": [ + "string", + "null" + ] }, - "name": { - "type": "string" + "configKey": { + "type": [ + "string", + "null" + ] }, - "providerId": { - "type": "string" + "modelConfigKey": { + "type": [ + "string", + "null" + ] }, - "supportsStreaming": { - "type": "boolean" + "defaultModel": { + "type": [ + "string", + "null" + ] + }, + "selectedModel": { + "type": [ + "string", + "null" + ] + }, + "availableModels": { + "type": "array", + "items": { + "$ref": "#/$defs/DictationModelOption" + }, + "default": [] } }, "required": [ - "providerId", - "name", - "format", - "apiUrl", - "models", - "supportsStreaming", - "envVar", - "docUrl" + "configured", + "description", + "usesProviderConfig" ], - "type": "object" + "description": "Per-provider configuration status." }, - "ProviderTemplateModelDto": { - "properties": { - "capabilities": { - "$ref": "#/$defs/ProviderTemplateCapabilitiesDto" - }, - "contextLimit": { - "minimum": 0, - "type": "integer" - }, - "deprecated": { - "type": "boolean" - }, + "DictationModelOption": { + "type": "object", + "properties": { "id": { "type": "string" }, - "name": { + "label": { + "type": "string" + }, + "description": { "type": "string" } }, "required": [ "id", - "name", - "contextLimit", - "capabilities", - "deprecated" - ], - "type": "object" + "label", + "description" + ] }, - "ReadResourceRequest_unstable": { - "description": "Read a resource from an extension.", + "DictationSecretSaveRequest_unstable": { + "type": "object", "properties": { - "extensionName": { - "type": "string" - }, - "sessionId": { + "provider": { "type": "string" }, - "uri": { + "value": { "type": "string" } }, "required": [ - "sessionId", - "uri", - "extensionName" + "provider", + "value" ], - "type": "object", - "x-method": "_goose/unstable/resources/read", - "x-side": "agent" + "description": "Set a dictation provider secret value.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/secret/save" }, - "ReadResourceResponse_unstable": { - "description": "Resource read response.", + "DictationSecretDeleteRequest_unstable": { + "type": "object", "properties": { - "result": { - "default": null, - "description": "The resource result from the extension (MCP ReadResourceResult)." + "provider": { + "type": "string" } }, + "required": [ + "provider" + ], + "description": "Remove a dictation provider secret value.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/secret/delete" + }, + "DictationModelsListRequest_unstable": { "type": "object", - "x-method": "_goose/unstable/resources/read", - "x-side": "agent" + "description": "List available local Whisper models with their download status.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/models/list" }, - "RefreshProviderInventoryRequest_unstable": { - "description": "Trigger a background refresh of provider inventories.", + "DictationModelsListResponse_unstable": { + "type": "object", "properties": { - "providerIds": { - "default": [], - "description": "Which providers to refresh. Empty means all known providers.", + "models": { + "type": "array", "items": { - "type": "string" - }, - "type": "array" + "$ref": "#/$defs/DictationLocalModelStatus" + } } }, - "type": "object", - "x-method": "_goose/unstable/providers/inventory/refresh", - "x-side": "agent" + "required": [ + "models" + ], + "x-side": "agent", + "x-method": "_goose/unstable/dictation/models/list" }, - "RefreshProviderInventoryResponse_unstable": { - "description": "Refresh acknowledgement.", + "DictationLocalModelStatus": { + "type": "object", "properties": { - "skipped": { - "default": [], - "description": "Which providers were skipped and why.", - "items": { - "$ref": "#/$defs/RefreshProviderInventorySkipDto" - }, - "type": "array" + "id": { + "type": "string" }, - "started": { - "description": "Which providers will be refreshed.", - "items": { - "type": "string" - }, - "type": "array" + "label": { + "type": "string" + }, + "description": { + "type": "string" + }, + "sizeMb": { + "type": "integer", + "minimum": 0 + }, + "downloaded": { + "type": "boolean" + }, + "downloadInProgress": { + "type": "boolean" } }, "required": [ - "started" - ], - "type": "object", - "x-method": "_goose/unstable/providers/inventory/refresh", - "x-side": "agent" + "id", + "label", + "description", + "sizeMb", + "downloaded", + "downloadInProgress" + ] }, - "RefreshProviderInventorySkipDto": { + "DictationModelDownloadRequest_unstable": { + "type": "object", "properties": { - "providerId": { + "modelId": { "type": "string" - }, - "reason": { - "$ref": "#/$defs/RefreshProviderInventorySkipReasonDto" } }, "required": [ - "providerId", - "reason" - ], - "type": "object" - }, - "RefreshProviderInventorySkipReasonDto": { - "enum": [ - "unknown_provider", - "not_configured", - "does_not_support_refresh", - "already_refreshing" + "modelId" ], - "type": "string" + "description": "Kick off a background download of a local Whisper model.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/models/download" }, - "RemoveConfigExtensionRequest_unstable": { - "description": "Remove a persisted extension from the user's global goose config.", + "DictationModelDownloadProgressRequest_unstable": { + "type": "object", "properties": { - "configKey": { + "modelId": { "type": "string" } }, "required": [ - "configKey" + "modelId" ], + "description": "Poll the progress of an in-flight download.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/models/download/progress" + }, + "DictationModelDownloadProgressResponse_unstable": { "type": "object", - "x-method": "_goose/unstable/config/extensions/remove", - "x-side": "agent" + "properties": { + "progress": { + "anyOf": [ + { + "$ref": "#/$defs/DictationDownloadProgress" + }, + { + "type": "null" + } + ], + "description": "None when no download is active for this model id." + } + }, + "x-side": "agent", + "x-method": "_goose/unstable/dictation/models/download/progress" }, - "RemoveExtensionRequest_unstable": { - "description": "Remove an extension from an active session.", + "DictationDownloadProgress": { + "type": "object", "properties": { - "name": { - "type": "string" + "bytesDownloaded": { + "type": "integer", + "minimum": 0 }, - "sessionId": { - "type": "string" + "totalBytes": { + "type": "integer", + "minimum": 0 + }, + "progressPercent": { + "type": "number", + "format": "float" + }, + "status": { + "type": "string", + "description": "serde lowercase of DownloadStatus: \"downloading\" | \"completed\" | \"failed\" | \"cancelled\"" + }, + "error": { + "type": [ + "string", + "null" + ] } }, "required": [ - "sessionId", - "name" - ], - "type": "object", - "x-method": "_goose/unstable/session/extensions/remove", - "x-side": "agent" + "bytesDownloaded", + "totalBytes", + "progressPercent", + "status" + ] }, - "RenameSessionRequest_unstable": { - "description": "Rename a session.", + "DictationModelCancelRequest_unstable": { + "type": "object", "properties": { - "sessionId": { - "type": "string" - }, - "title": { + "modelId": { "type": "string" } }, "required": [ - "sessionId", - "title" + "modelId" ], - "type": "object", - "x-method": "_goose/unstable/session/rename", - "x-side": "agent" + "description": "Cancel an in-flight download.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/models/cancel" }, - "SessionSystemPromptMode": { - "description": "How a session system prompt update should be applied.", - "oneOf": [ - { - "const": "set", - "description": "Replace Goose's base system prompt with the provided text.", - "type": "string" - }, - { - "const": "append", - "description": "Append the provided text under Goose's \"Additional Instructions\" section.", + "DictationModelDeleteRequest_unstable": { + "type": "object", + "properties": { + "modelId": { "type": "string" } - ] + }, + "required": [ + "modelId" + ], + "description": "Delete a downloaded local Whisper model from disk.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/models/delete" }, - "SetConfigExtensionEnabledRequest_unstable": { - "description": "Set the `enabled` flag for a persisted extension in the user's global goose config.", + "DictationModelSelectRequest_unstable": { + "type": "object", "properties": { - "configKey": { + "provider": { "type": "string" }, - "enabled": { - "type": "boolean" + "modelId": { + "type": "string" } }, "required": [ - "configKey", - "enabled" + "provider", + "modelId" ], - "type": "object", - "x-method": "_goose/unstable/config/extensions/set-enabled", - "x-side": "agent" + "description": "Persist the user's model selection for a given provider.", + "x-side": "agent", + "x-method": "_goose/unstable/dictation/models/select" }, - "SetSessionSystemPromptRequest_unstable": { - "description": "Set, append, or clear system prompt text for a session.\n\n`mode: \"set\"` replaces Goose's base system prompt. `mode: \"append\"` adds an\ninstruction under \"Additional Instructions\". Reusing a key replaces the\nprevious value for that mode/key; sending empty text clears it.", + "ExtRequest": { "properties": { - "key": { - "type": [ - "string", - "null" + "id": { + "type": "string" + }, + "method": { + "type": "string" + }, + "params": { + "anyOf": [ + { + "anyOf": [ + { + "allOf": [ + { + "$ref": "#/$defs/AddExtensionRequest_unstable" + } + ], + "description": "Params for _goose/unstable/session/extensions/add", + "title": "AddExtensionRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/RemoveExtensionRequest_unstable" + } + ], + "description": "Params for _goose/unstable/session/extensions/remove", + "title": "RemoveExtensionRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GetToolsRequest_unstable" + } + ], + "description": "Params for _goose/unstable/tools/list", + "title": "GetToolsRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GooseToolCallRequest_unstable" + } + ], + "description": "Params for _goose/unstable/tools/call", + "title": "GooseToolCallRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ReadResourceRequest_unstable" + } + ], + "description": "Params for _goose/unstable/resources/read", + "title": "ReadResourceRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/UpdateWorkingDirRequest_unstable" + } + ], + "description": "Params for _goose/unstable/session/working-dir/update", + "title": "UpdateWorkingDirRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/SetSessionSystemPromptRequest_unstable" + } + ], + "description": "Params for _goose/unstable/session/system-prompt/set", + "title": "SetSessionSystemPromptRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DeleteSessionRequest" + } + ], + "description": "Params for session/delete", + "title": "DeleteSessionRequest" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GetConfigExtensionsRequest_unstable" + } + ], + "description": "Params for _goose/unstable/config/extensions/list", + "title": "GetConfigExtensionsRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GetAvailableExtensionsRequest_unstable" + } + ], + "description": "Params for _goose/unstable/extensions/available", + "title": "GetAvailableExtensionsRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/AddConfigExtensionRequest_unstable" + } + ], + "description": "Params for _goose/unstable/config/extensions/add", + "title": "AddConfigExtensionRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/RemoveConfigExtensionRequest_unstable" + } + ], + "description": "Params for _goose/unstable/config/extensions/remove", + "title": "RemoveConfigExtensionRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/SetConfigExtensionEnabledRequest_unstable" + } + ], + "description": "Params for _goose/unstable/config/extensions/set-enabled", + "title": "SetConfigExtensionEnabledRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GetSessionExtensionsRequest_unstable" + } + ], + "description": "Params for _goose/unstable/session/extensions/list", + "title": "GetSessionExtensionsRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ListProvidersRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/list", + "title": "ListProvidersRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderSupportedModelsListRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/supported-models/list", + "title": "ProviderSupportedModelsListRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderCatalogListRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/catalog/list", + "title": "ProviderCatalogListRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderSetupCatalogListRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/setup/catalog/list", + "title": "ProviderSetupCatalogListRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderCatalogTemplateRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/catalog/template", + "title": "ProviderCatalogTemplateRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CustomProviderCreateRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/custom/create", + "title": "CustomProviderCreateRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CustomProviderReadRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/custom/read", + "title": "CustomProviderReadRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CustomProviderUpdateRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/custom/update", + "title": "CustomProviderUpdateRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CustomProviderDeleteRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/custom/delete", + "title": "CustomProviderDeleteRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/RefreshProviderInventoryRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/inventory/refresh", + "title": "RefreshProviderInventoryRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderConfigReadRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/config/read", + "title": "ProviderConfigReadRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderConfigStatusRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/config/status", + "title": "ProviderConfigStatusRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderConfigSaveRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/config/save", + "title": "ProviderConfigSaveRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderConfigDeleteRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/config/delete", + "title": "ProviderConfigDeleteRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderConfigAuthenticateRequest_unstable" + } + ], + "description": "Params for _goose/unstable/providers/config/authenticate", + "title": "ProviderConfigAuthenticateRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/PreferencesReadRequest_unstable" + } + ], + "description": "Params for _goose/unstable/preferences/read", + "title": "PreferencesReadRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/PreferencesSaveRequest_unstable" + } + ], + "description": "Params for _goose/unstable/preferences/save", + "title": "PreferencesSaveRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/PreferencesRemoveRequest_unstable" + } + ], + "description": "Params for _goose/unstable/preferences/remove", + "title": "PreferencesRemoveRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DefaultsReadRequest_unstable" + } + ], + "description": "Params for _goose/unstable/defaults/read", + "title": "DefaultsReadRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DefaultsSaveRequest_unstable" + } + ], + "description": "Params for _goose/unstable/defaults/save", + "title": "DefaultsSaveRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/OnboardingImportScanRequest_unstable" + } + ], + "description": "Params for _goose/unstable/onboarding/import/scan", + "title": "OnboardingImportScanRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/OnboardingImportApplyRequest_unstable" + } + ], + "description": "Params for _goose/unstable/onboarding/import/apply", + "title": "OnboardingImportApplyRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ExportSessionRequest_unstable" + } + ], + "description": "Params for _goose/unstable/session/export", + "title": "ExportSessionRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ImportSessionRequest_unstable" + } + ], + "description": "Params for _goose/unstable/session/import", + "title": "ImportSessionRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/UpdateSessionProjectRequest_unstable" + } + ], + "description": "Params for _goose/unstable/session/project/update", + "title": "UpdateSessionProjectRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/RenameSessionRequest_unstable" + } + ], + "description": "Params for _goose/unstable/session/rename", + "title": "RenameSessionRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ArchiveSessionRequest_unstable" + } + ], + "description": "Params for _goose/unstable/session/archive", + "title": "ArchiveSessionRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/UnarchiveSessionRequest_unstable" + } + ], + "description": "Params for _goose/unstable/session/unarchive", + "title": "UnarchiveSessionRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CreateSourceRequest_unstable" + } + ], + "description": "Params for _goose/unstable/sources/create", + "title": "CreateSourceRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ListSourcesRequest_unstable" + } + ], + "description": "Params for _goose/unstable/sources/list", + "title": "ListSourcesRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/UpdateSourceRequest_unstable" + } + ], + "description": "Params for _goose/unstable/sources/update", + "title": "UpdateSourceRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DeleteSourceRequest_unstable" + } + ], + "description": "Params for _goose/unstable/sources/delete", + "title": "DeleteSourceRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ExportSourceRequest_unstable" + } + ], + "description": "Params for _goose/unstable/sources/export", + "title": "ExportSourceRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ImportSourcesRequest_unstable" + } + ], + "description": "Params for _goose/unstable/sources/import", + "title": "ImportSourcesRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationTranscribeRequest_unstable" + } + ], + "description": "Params for _goose/unstable/dictation/transcribe", + "title": "DictationTranscribeRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationConfigRequest_unstable" + } + ], + "description": "Params for _goose/unstable/dictation/config", + "title": "DictationConfigRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationSecretSaveRequest_unstable" + } + ], + "description": "Params for _goose/unstable/dictation/secret/save", + "title": "DictationSecretSaveRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationSecretDeleteRequest_unstable" + } + ], + "description": "Params for _goose/unstable/dictation/secret/delete", + "title": "DictationSecretDeleteRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationModelsListRequest_unstable" + } + ], + "description": "Params for _goose/unstable/dictation/models/list", + "title": "DictationModelsListRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationModelDownloadRequest_unstable" + } + ], + "description": "Params for _goose/unstable/dictation/models/download", + "title": "DictationModelDownloadRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationModelDownloadProgressRequest_unstable" + } + ], + "description": "Params for _goose/unstable/dictation/models/download/progress", + "title": "DictationModelDownloadProgressRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationModelCancelRequest_unstable" + } + ], + "description": "Params for _goose/unstable/dictation/models/cancel", + "title": "DictationModelCancelRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationModelDeleteRequest_unstable" + } + ], + "description": "Params for _goose/unstable/dictation/models/delete", + "title": "DictationModelDeleteRequest_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationModelSelectRequest_unstable" + } + ], + "description": "Params for _goose/unstable/dictation/models/select", + "title": "DictationModelSelectRequest_unstable" + } + ] + }, + { + "description": "Untyped params", + "type": [ + "object", + "null" + ] + } ] - }, - "mode": { - "$ref": "#/$defs/SessionSystemPromptMode", - "default": "append" - }, - "sessionId": { - "type": "string" - }, - "text": { - "type": "string" } }, "required": [ - "sessionId", - "text" + "id", + "method" ], "type": "object", - "x-method": "_goose/unstable/session/system-prompt/set", - "x-side": "agent" - }, - "SourceEntry": { - "description": "A source discovered by Goose. Filesystem sources use an on-disk path;\nbuilt-in sources use a stable synthetic path. Sources may be either\n`global` (shared across all projects) or project-specific.", - "properties": { - "content": { - "type": "string" - }, - "description": { - "type": "string" - }, - "global": { - "description": "True when the source lives in the user's global sources directory; false\nwhen it lives inside a specific project.", - "type": "boolean" - }, - "name": { - "type": "string" - }, - "path": { - "description": "Stable on-disk path identifying this source. Pass it back to\nupdate/delete/export to operate on this entry. Skills use the directory\ncontaining `SKILL.md`; projects use the project file path; built-in\nskills use `builtin://skills/` synthetic paths.", - "type": "string" - }, - "properties": { - "additionalProperties": {}, - "description": "Arbitrary key/value pairs for type-specific metadata (e.g. icon, color,\npreferredProvider for projects). Stored in the frontmatter.", - "type": "object" - }, - "supportingFiles": { - "description": "Paths (absolute) of additional files that live alongside the source.\nOnly skills currently populate this; empty for other source types.", - "items": { - "type": "string" - }, - "type": "array" - }, - "type": { - "$ref": "#/$defs/SourceType" - }, - "writable": { - "default": false, - "description": "True when this source can be modified through source CRUD methods.\nClient-provided bundled sources are returned as read-only.", - "type": "boolean" - } - }, - "required": [ - "type", - "name", - "description", - "content", - "path", - "global" - ], - "type": "object" + "x-docs-ignore": true }, - "SourceScope": { - "description": "Target scope for creating or importing sources.", - "oneOf": [ - { - "properties": { - "scope": { - "const": "global", - "type": "string" - } - }, - "required": [ - "scope" - ], - "type": "object" - }, + "ExtResponse": { + "anyOf": [ { "properties": { - "projectDir": { + "id": { "type": "string" }, - "scope": { - "const": "projectDir", - "type": "string" + "result": { + "anyOf": [ + { + "anyOf": [ + { + "allOf": [ + { + "$ref": "#/$defs/EmptyResponse" + } + ], + "title": "EmptyResponse" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GetToolsResponse_unstable" + } + ], + "title": "GetToolsResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GooseToolCallResponse_unstable" + } + ], + "title": "GooseToolCallResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ReadResourceResponse_unstable" + } + ], + "title": "ReadResourceResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GetConfigExtensionsResponse_unstable" + } + ], + "title": "GetConfigExtensionsResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GetAvailableExtensionsResponse_unstable" + } + ], + "title": "GetAvailableExtensionsResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/GetSessionExtensionsResponse_unstable" + } + ], + "title": "GetSessionExtensionsResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ListProvidersResponse_unstable" + } + ], + "title": "ListProvidersResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderSupportedModelsListResponse_unstable" + } + ], + "title": "ProviderSupportedModelsListResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderCatalogListResponse_unstable" + } + ], + "title": "ProviderCatalogListResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderSetupCatalogListResponse_unstable" + } + ], + "title": "ProviderSetupCatalogListResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderCatalogTemplateResponse_unstable" + } + ], + "title": "ProviderCatalogTemplateResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CustomProviderCreateResponse_unstable" + } + ], + "title": "CustomProviderCreateResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CustomProviderReadResponse_unstable" + } + ], + "title": "CustomProviderReadResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CustomProviderUpdateResponse_unstable" + } + ], + "title": "CustomProviderUpdateResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CustomProviderDeleteResponse_unstable" + } + ], + "title": "CustomProviderDeleteResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/RefreshProviderInventoryResponse_unstable" + } + ], + "title": "RefreshProviderInventoryResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderConfigReadResponse_unstable" + } + ], + "title": "ProviderConfigReadResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderConfigStatusResponse_unstable" + } + ], + "title": "ProviderConfigStatusResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ProviderConfigChangeResponse_unstable" + } + ], + "title": "ProviderConfigChangeResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/PreferencesReadResponse_unstable" + } + ], + "title": "PreferencesReadResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DefaultsReadResponse_unstable" + } + ], + "title": "DefaultsReadResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/OnboardingImportScanResponse_unstable" + } + ], + "title": "OnboardingImportScanResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/OnboardingImportApplyResponse_unstable" + } + ], + "title": "OnboardingImportApplyResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ExportSessionResponse_unstable" + } + ], + "title": "ExportSessionResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ImportSessionResponse_unstable" + } + ], + "title": "ImportSessionResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CreateSourceResponse_unstable" + } + ], + "title": "CreateSourceResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ListSourcesResponse_unstable" + } + ], + "title": "ListSourcesResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/UpdateSourceResponse_unstable" + } + ], + "title": "UpdateSourceResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ExportSourceResponse_unstable" + } + ], + "title": "ExportSourceResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/ImportSourcesResponse_unstable" + } + ], + "title": "ImportSourcesResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationTranscribeResponse_unstable" + } + ], + "title": "DictationTranscribeResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationConfigResponse_unstable" + } + ], + "title": "DictationConfigResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationModelsListResponse_unstable" + } + ], + "title": "DictationModelsListResponse_unstable" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DictationModelDownloadProgressResponse_unstable" + } + ], + "title": "DictationModelDownloadProgressResponse_unstable" + } + ] + }, + { + "description": "Untyped result" + } + ] } }, "required": [ - "scope", - "projectDir" + "id" ], + "title": "Success", "type": "object" }, { "properties": { - "projectId": { - "type": "string" + "error": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "data": {} + }, + "required": [ + "code", + "message" + ] }, - "scope": { - "const": "projectId", + "id": { "type": "string" } }, "required": [ - "scope", - "projectId" + "id", + "error" ], + "title": "Error", "type": "object" } - ] - }, - "SourceType": { - "description": "The type of source entity.", - "enum": [ - "skill", - "builtinSkill", - "recipe", - "subrecipe", - "agent", - "project" - ], - "type": "string" - }, - "UnarchiveSessionRequest_unstable": { - "description": "Unarchive a previously archived session.", - "properties": { - "sessionId": { - "type": "string" - } - }, - "required": [ - "sessionId" - ], - "type": "object", - "x-method": "_goose/unstable/session/unarchive", - "x-side": "agent" - }, - "UpdateSessionProjectRequest_unstable": { - "description": "Update the project association for a session.", - "properties": { - "projectId": { - "type": [ - "string", - "null" - ] - }, - "sessionId": { - "type": "string" - } - }, - "required": [ - "sessionId" - ], - "type": "object", - "x-method": "_goose/unstable/session/project/update", - "x-side": "agent" - }, - "UpdateSourceRequest_unstable": { - "description": "Update an existing source's name, description, and content by absolute path.", - "properties": { - "content": { - "type": "string" - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - }, - "path": { - "type": "string" - }, - "properties": { - "additionalProperties": {}, - "description": "When `Some`, replaces all stored properties on the source. When\n`None` (or omitted), the source's existing properties are\npreserved. Callers that don't model the full property bag (e.g.\nthe skills editor, which only edits name/description/content)\nshould omit this so per-skill metadata isn't silently erased.", - "type": [ - "object", - "null" - ] - }, - "type": { - "$ref": "#/$defs/SourceType" - } - }, - "required": [ - "type", - "path", - "name", - "description", - "content" - ], - "type": "object", - "x-method": "_goose/unstable/sources/update", - "x-side": "agent" - }, - "UpdateSourceResponse_unstable": { - "properties": { - "source": { - "$ref": "#/$defs/SourceEntry" - } - }, - "required": [ - "source" - ], - "type": "object", - "x-method": "_goose/unstable/sources/update", - "x-side": "agent" - }, - "UpdateWorkingDirRequest_unstable": { - "description": "Update the working directory for a session.", - "properties": { - "sessionId": { - "type": "string" - }, - "workingDir": { - "type": "string" - } - }, - "required": [ - "sessionId", - "workingDir" ], - "type": "object", - "x-method": "_goose/unstable/session/working-dir/update", - "x-side": "agent" + "x-docs-ignore": true } }, - "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "allOf": [ @@ -4015,6 +3938,5 @@ "description": "Extension response (agent → client)", "title": "Response" } - ], - "title": "GooseExtensions" + ] } diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index e193f5065a01..c4ff4937c774 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -204,42 +204,9 @@ fn config_to_goose_extension( bundled: *bundled, } } - ExtensionConfig::Frontend { - name, - description, - tools, - instructions, - bundled, - .. - } => { - let tools = tools - .iter() - .map(serde_json::to_value) - .collect::, _>>() - .internal_err()?; - GooseExtension::Frontend { - name: name.clone(), - description: empty_string_to_none(description), - tools, - instructions: instructions.clone(), - bundled: *bundled, - } - } - ExtensionConfig::InlinePython { - name, - description, - code, - timeout, - dependencies, - .. - } => GooseExtension::InlinePython { - name: name.clone(), - description: empty_string_to_none(description), - code: code.clone(), - timeout: *timeout, - dependencies: dependencies.clone().unwrap_or_default(), - }, - ExtensionConfig::Sse { .. } => return Ok(None), + ExtensionConfig::Frontend { .. } + | ExtensionConfig::InlinePython { .. } + | ExtensionConfig::Sse { .. } => return Ok(None), }; Ok(Some(extension)) } @@ -330,41 +297,6 @@ fn goose_extension_to_config( ); } }, - GooseExtension::InlinePython { - name, - description, - code, - timeout, - dependencies, - } => ExtensionConfig::InlinePython { - name, - description: description.unwrap_or_default(), - code, - timeout, - dependencies: (!dependencies.is_empty()).then_some(dependencies), - available_tools: Vec::new(), - }, - GooseExtension::Frontend { - name, - description, - tools, - instructions, - bundled, - } => ExtensionConfig::Frontend { - name, - description: description.unwrap_or_default(), - tools: tools - .into_iter() - .map(serde_json::from_value) - .collect::, _>>() - .map_err(|error| { - agent_client_protocol::Error::invalid_params() - .data(format!("bad frontend tool: {error}")) - })?, - instructions, - bundled, - available_tools: Vec::new(), - }, }; Ok(config) } @@ -396,7 +328,6 @@ mod tests { use super::*; use crate::agents::extension::Envs; use agent_client_protocol::schema::{McpServer, McpServerSse}; - use rmcp::model::Tool; use std::collections::HashMap; #[test] @@ -566,7 +497,7 @@ mod tests { } #[test] - fn inline_python_config_converts_to_goose_inline_python_extension() { + fn inline_python_config_is_skipped() { let config = ExtensionConfig::InlinePython { name: "python-tools".to_string(), description: "Python tools".to_string(), @@ -576,31 +507,14 @@ mod tests { available_tools: vec!["fetch".to_string()], }; - let extension = config_to_goose_extension(&config) - .expect("conversion should succeed") - .expect("inline python should be supported"); - - let GooseExtension::InlinePython { - name, - description, - code, - timeout, - dependencies, - } = extension - else { - panic!("expected inline python extension"); - }; + let extension = config_to_goose_extension(&config).expect("conversion should succeed"); - assert_eq!(name, "python-tools"); - assert_eq!(description.as_deref(), Some("Python tools")); - assert_eq!(code, "print('hello')"); - assert_eq!(timeout, Some(12)); - assert_eq!(dependencies, vec!["requests"]); + assert!(extension.is_none()); } #[test] - fn frontend_config_converts_to_goose_frontend_extension() { - let tool = Tool::new( + fn frontend_config_is_skipped() { + let tool = rmcp::model::Tool::new( "pick_color", "Pick a color", serde_json::json!({ @@ -622,31 +536,9 @@ mod tests { available_tools: vec!["pick_color".to_string()], }; - let extension = config_to_goose_extension(&config) - .expect("conversion should succeed") - .expect("frontend should be supported"); - - let GooseExtension::Frontend { - name, - description, - tools, - instructions, - bundled, - } = extension - else { - panic!("expected frontend extension"); - }; + let extension = config_to_goose_extension(&config).expect("conversion should succeed"); - assert_eq!(name, "frontend-tools"); - assert_eq!(description.as_deref(), Some("Frontend tools")); - assert_eq!( - instructions.as_deref(), - Some("Use frontend tools carefully") - ); - assert_eq!(tools.len(), 1); - assert_eq!(tools[0]["name"], "pick_color"); - assert_eq!(tools[0]["description"], "Pick a color"); - assert_eq!(bundled, None); + assert!(extension.is_none()); } #[test] @@ -777,85 +669,6 @@ mod tests { assert!(available_tools.is_empty()); } - #[test] - fn goose_inline_python_extension_converts_to_config() { - let extension = GooseExtension::InlinePython { - name: "python-tools".to_string(), - description: Some("Python tools".to_string()), - code: "print('hello')".to_string(), - timeout: Some(12), - dependencies: vec!["requests".to_string()], - }; - - let config = goose_extension_to_config(extension).expect("conversion should succeed"); - - let ExtensionConfig::InlinePython { - name, - description, - code, - timeout, - dependencies, - available_tools, - } = config - else { - panic!("expected inline python config"); - }; - - assert_eq!(name, "python-tools"); - assert_eq!(description, "Python tools"); - assert_eq!(code, "print('hello')"); - assert_eq!(timeout, Some(12)); - assert_eq!(dependencies, Some(vec!["requests".to_string()])); - assert!(available_tools.is_empty()); - } - - #[test] - fn goose_frontend_extension_converts_to_config() { - let tool = serde_json::json!({ - "name": "pick_color", - "description": "Pick a color", - "inputSchema": { - "type": "object", - "properties": { - "hex": { "type": "string" } - } - } - }); - let extension = GooseExtension::Frontend { - name: "frontend-tools".to_string(), - description: Some("Frontend tools".to_string()), - tools: vec![tool], - instructions: Some("Use frontend tools carefully".to_string()), - bundled: Some(true), - }; - - let config = goose_extension_to_config(extension).expect("conversion should succeed"); - - let ExtensionConfig::Frontend { - name, - description, - tools, - instructions, - bundled, - available_tools, - } = config - else { - panic!("expected frontend config"); - }; - - assert_eq!(name, "frontend-tools"); - assert_eq!(description, "Frontend tools"); - assert_eq!(tools.len(), 1); - assert_eq!(tools[0].name, "pick_color"); - assert_eq!(tools[0].description.as_deref(), Some("Pick a color")); - assert_eq!( - instructions.as_deref(), - Some("Use frontend tools carefully") - ); - assert_eq!(bundled, Some(true)); - assert!(available_tools.is_empty()); - } - #[test] fn goose_builtin_extension_converts_to_config() { let builtin = GooseExtension::Builtin { diff --git a/ui/desktop/src/acp/extensions.ts b/ui/desktop/src/acp/extensions.ts index bf9961242fb5..7964210b8538 100644 --- a/ui/desktop/src/acp/extensions.ts +++ b/ui/desktop/src/acp/extensions.ts @@ -53,7 +53,6 @@ function gooseExtensionEntryToExtensionEntry(entry: GooseExtensionEntry): Extens switch (extension.type) { case 'builtin': case 'platform': - case 'inline_python': return { ...extension, description: extension.description ?? '', @@ -61,13 +60,6 @@ function gooseExtensionEntryToExtensionEntry(entry: GooseExtensionEntry): Extens }; case 'mcp': return mcpServerToExtension(extension.server, entry); - case 'frontend': - return { - ...extension, - description: extension.description ?? '', - tools: extension.tools ?? [], - enabled: entry.enabled, - } as ExtensionEntry; } return null; diff --git a/ui/sdk/src/generated/types.gen.ts b/ui/sdk/src/generated/types.gen.ts index 95d23e4523bf..24628061eba8 100644 --- a/ui/sdk/src/generated/types.gen.ts +++ b/ui/sdk/src/generated/types.gen.ts @@ -1,166 +1,113 @@ // This file is auto-generated by @hey-api/openapi-ts -/** - * Persist a new extension to the user's global goose config. - */ -export type AddConfigExtensionRequest_unstable = { - enabled?: boolean; - extension: GooseExtension; -}; - /** * Add an extension to an active session. */ export type AddExtensionRequest_unstable = { + sessionId: string; /** * Extension configuration (see ExtensionConfig variants: Stdio, StreamableHttp, Builtin, Platform). */ config?: unknown; - sessionId: string; }; /** - * Archive a session (soft delete). + * Empty success response for operations that return no data. */ -export type ArchiveSessionRequest_unstable = { - sessionId: string; +export type EmptyResponse = { + [key: string]: unknown; }; /** - * Create a new source in an explicit target scope (global or project-scoped). + * Remove an extension from an active session. */ -export type CreateSourceRequest_unstable = { - content: string; - description: string; +export type RemoveExtensionRequest_unstable = { + sessionId: string; name: string; - /** - * Arbitrary key/value metadata. - */ - properties?: { - [key: string]: unknown; - }; - target: SourceScope; - type: SourceType; -}; - -export type CreateSourceResponse_unstable = { - source: SourceEntry; -}; - -export type CustomProviderConfigDto = { - apiKeyEnv?: string | null; - apiKeySet: boolean; - apiUrl: string; - basePath?: string | null; - catalogProviderId?: string | null; - displayName: string; - engine: string; - headers?: { - [key: string]: string; - }; - models?: Array; - preservesThinking: boolean; - providerId: string; - requiresAuth: boolean; - supportsStreaming?: boolean | null; }; /** - * Create a custom provider backed by Goose's declarative provider store. + * List all tools available in a session. */ -export type CustomProviderCreateRequest_unstable = { - apiKey?: string | null; - apiUrl: string; - basePath?: string | null; - catalogProviderId?: string | null; - displayName: string; - engine: string; - headers?: { - [key: string]: string; - }; - models?: Array; - preservesThinking?: boolean | null; - requiresAuth: boolean; - supportsStreaming?: boolean | null; -}; - -export type CustomProviderCreateResponse_unstable = { - providerId: string; - refresh: RefreshProviderInventoryResponse_unstable; - status: ProviderConfigStatusDto; +export type GetToolsRequest_unstable = { + sessionId: string; }; /** - * Delete a custom provider from Goose's declarative provider store. + * Tools response. */ -export type CustomProviderDeleteRequest_unstable = { - providerId: string; -}; - -export type CustomProviderDeleteResponse_unstable = { - providerId: string; - refresh: RefreshProviderInventoryResponse_unstable; +export type GetToolsResponse_unstable = { + /** + * Array of tool info objects with `name`, `description`, `parameters`, and optional `permission`. + */ + tools: Array; }; /** - * Read a declarative provider config. Custom configs are editable; bundled configs are read-only. + * Call a tool from an extension. */ -export type CustomProviderReadRequest_unstable = { - providerId: string; +export type GooseToolCallRequest_unstable = { + sessionId: string; + name: string; + arguments?: unknown; }; -export type CustomProviderReadResponse_unstable = { - editable: boolean; - provider: CustomProviderConfigDto; - status: ProviderConfigStatusDto; +/** + * Tool call response. + */ +export type GooseToolCallResponse_unstable = { + content?: Array; + structuredContent?: unknown; + isError: boolean; + _meta?: unknown; }; /** - * Update a custom provider backed by Goose's declarative provider store. + * Read a resource from an extension. */ -export type CustomProviderUpdateRequest_unstable = { - apiKey?: string | null; - apiUrl: string; - basePath?: string | null; - catalogProviderId?: string | null; - displayName: string; - engine: string; - headers?: { - [key: string]: string; - }; - models?: Array; - preservesThinking?: boolean | null; - providerId: string; - requiresAuth: boolean; - supportsStreaming?: boolean | null; +export type ReadResourceRequest_unstable = { + sessionId: string; + uri: string; + extensionName: string; }; -export type CustomProviderUpdateResponse_unstable = { - providerId: string; - refresh: RefreshProviderInventoryResponse_unstable; - status: ProviderConfigStatusDto; +/** + * Resource read response. + */ +export type ReadResourceResponse_unstable = { + /** + * The resource result from the extension (MCP ReadResourceResult). + */ + result?: unknown; }; /** - * Read Goose default provider and model configuration. + * Update the working directory for a session. */ -export type DefaultsReadRequest_unstable = { - [key: string]: unknown; +export type UpdateWorkingDirRequest_unstable = { + sessionId: string; + workingDir: string; }; -export type DefaultsReadResponse_unstable = { - modelId?: string | null; - providerId?: string | null; +/** + * Set, append, or clear system prompt text for a session. + * + * `mode: "set"` replaces Goose's base system prompt. `mode: "append"` adds an + * instruction under "Additional Instructions". Reusing a key replaces the + * previous value for that mode/key; sending empty text clears it. + */ +export type SetSessionSystemPromptRequest_unstable = { + sessionId: string; + mode?: SessionSystemPromptMode; + key?: string | null; + text: string; }; /** - * Save Goose default provider and model configuration. + * How a session system prompt update should be applied. */ -export type DefaultsSaveRequest_unstable = { - modelId?: string | null; - providerId: string; -}; +export type SessionSystemPromptMode = 'set' | 'append'; /** * Delete a session. @@ -170,176 +117,161 @@ export type DeleteSessionRequest = { }; /** - * Delete a source and its on-disk directory by absolute path. - */ -export type DeleteSourceRequest_unstable = { - path: string; - type: SourceType; -}; - -/** - * Get the configuration status of all dictation providers. + * List configured extensions and any warnings. */ -export type DictationConfigRequest_unstable = { +export type GetConfigExtensionsRequest_unstable = { [key: string]: unknown; }; /** - * Dictation config response — map of provider name to status. + * List configured extensions and any warnings. */ -export type DictationConfigResponse_unstable = { - providers: { - [key: string]: DictationProviderStatusEntry; - }; -}; - -export type DictationDownloadProgress = { - bytesDownloaded: number; - error?: string | null; - progressPercent: number; - /** - * serde lowercase of DownloadStatus: "downloading" | "completed" | "failed" | "cancelled" - */ - status: string; - totalBytes: number; +export type GetConfigExtensionsResponse_unstable = { + extensions: Array; + warnings?: Array; }; -export type DictationLocalModelStatus = { - description: string; - downloadInProgress: boolean; - downloaded: boolean; - id: string; - label: string; - sizeMb: number; +export type GooseExtensionEntry = { + extension: GooseExtension; + enabled: boolean; + configKey?: string | null; }; -/** - * Cancel an in-flight download. - */ -export type DictationModelCancelRequest_unstable = { - modelId: string; +export type GooseExtension = { + name: string; + description?: string | null; + display_name?: string | null; + timeout?: number | null; + bundled?: boolean | null; + type: 'builtin'; +} | { + name: string; + description?: string | null; + display_name?: string | null; + bundled?: boolean | null; + type: 'platform'; +} | { + server: McpServer; + envKeys?: Array; + description?: string | null; + timeout?: number | null; + socket?: string | null; + bundled?: boolean | null; + type: 'mcp'; }; /** - * Delete a downloaded local Whisper model from disk. + * Configuration for connecting to an MCP (Model Context Protocol) server. + * + * MCP servers provide tools and context that the agent can use when + * processing prompts. + * + * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) */ -export type DictationModelDeleteRequest_unstable = { - modelId: string; -}; +export type McpServer = McpServerHttp | McpServerSse | McpServerStdio; /** - * Poll the progress of an in-flight download. + * An HTTP header to set when making requests to the MCP server. */ -export type DictationModelDownloadProgressRequest_unstable = { - modelId: string; -}; - -export type DictationModelDownloadProgressResponse_unstable = { +export type HttpHeader = { /** - * None when no download is active for this model id. + * The name of the HTTP header. + */ + name: string; + /** + * The value to set for the HTTP header. */ - progress?: DictationDownloadProgress | null; -}; - -/** - * Kick off a background download of a local Whisper model. - */ -export type DictationModelDownloadRequest_unstable = { - modelId: string; -}; - -export type DictationModelOption = { - description: string; - id: string; - label: string; -}; - -/** - * Persist the user's model selection for a given provider. - */ -export type DictationModelSelectRequest_unstable = { - modelId: string; - provider: string; -}; - -/** - * List available local Whisper models with their download status. - */ -export type DictationModelsListRequest_unstable = { - [key: string]: unknown; -}; - -export type DictationModelsListResponse_unstable = { - models: Array; -}; - -/** - * Per-provider configuration status. - */ -export type DictationProviderStatusEntry = { - availableModels?: Array; - configKey?: string | null; - configured: boolean; - defaultModel?: string | null; - description: string; - host?: string | null; - modelConfigKey?: string | null; - selectedModel?: string | null; - settingsPath?: string | null; - usesProviderConfig: boolean; -}; - -/** - * Remove a dictation provider secret value. - */ -export type DictationSecretDeleteRequest_unstable = { - provider: string; -}; - -/** - * Set a dictation provider secret value. - */ -export type DictationSecretSaveRequest_unstable = { - provider: string; value: string; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; }; /** - * Transcribe audio via a dictation provider. + * HTTP transport configuration for MCP. */ -export type DictationTranscribeRequest_unstable = { +export type McpServerHttp = { /** - * Base64-encoded audio data + * Human-readable name identifying this MCP server. */ - audio: string; + name: string; /** - * MIME type (e.g. "audio/wav", "audio/webm") + * URL to the MCP server. */ - mimeType: string; + url: string; /** - * Provider to use: "openai", "groq", "elevenlabs", or "local" + * HTTP headers to set when making requests to the MCP server. */ - provider: string; -}; - -/** - * Transcription result. - */ -export type DictationTranscribeResponse_unstable = { - text: string; + headers: Array; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + type: 'http'; }; /** - * Empty success response for operations that return no data. + * SSE transport configuration for MCP. */ -export type EmptyResponse = { - [key: string]: unknown; +export type McpServerSse = { + /** + * Human-readable name identifying this MCP server. + */ + name: string; + /** + * URL to the MCP server. + */ + url: string; + /** + * HTTP headers to set when making requests to the MCP server. + */ + headers: Array; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + type: 'sse'; }; /** - * An environment variable to set when launching an MCP server. + * Stdio transport configuration for MCP. */ -export type EnvVariable = { +export type McpServerStdio = { + /** + * Human-readable name identifying this MCP server. + */ + name: string; + /** + * Path to the MCP server executable. + */ + command: string; + /** + * Command-line arguments to pass to the MCP server. + */ + args: Array; + /** + * Environment variables to set when launching the MCP server. + */ + env: Array; /** * The _meta property is reserved by ACP to allow clients and agents to attach additional * metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -350,6 +282,12 @@ export type EnvVariable = { _meta?: { [key: string]: unknown; } | null; +}; + +/** + * An environment variable to set when launching an MCP server. + */ +export type EnvVariable = { /** * The name of the environment variable. */ @@ -358,55 +296,18 @@ export type EnvVariable = { * The value to set for the environment variable. */ value: string; -}; - -/** - * Export a session as a JSON string. - */ -export type ExportSessionRequest_unstable = { - sessionId: string; -}; - -/** - * Export session response — raw JSON of the goose session with `conversation`. - */ -export type ExportSessionResponse_unstable = { - data: string; -}; - -/** - * Export a source at an absolute path as a portable JSON payload. - */ -export type ExportSourceRequest_unstable = { - path: string; - type: SourceType; -}; - -export type ExportSourceResponse_unstable = { - filename: string; - json: string; -}; - -export type ExtRequest = { - id: string; - method: string; - params?: AddExtensionRequest_unstable | RemoveExtensionRequest_unstable | GetToolsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | DeleteSessionRequest | GetConfigExtensionsRequest_unstable | GetAvailableExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | SetConfigExtensionEnabledRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { [key: string]: unknown; } | null; }; -export type ExtResponse = { - id: string; - result?: EmptyResponse | GetToolsResponse_unstable | GooseToolCallResponse_unstable | ReadResourceResponse_unstable | GetConfigExtensionsResponse_unstable | GetAvailableExtensionsResponse_unstable | GetSessionExtensionsResponse_unstable | ListProvidersResponse_unstable | ProviderSupportedModelsListResponse_unstable | ProviderCatalogListResponse_unstable | ProviderSetupCatalogListResponse_unstable | ProviderCatalogTemplateResponse_unstable | CustomProviderCreateResponse_unstable | CustomProviderReadResponse_unstable | CustomProviderUpdateResponse_unstable | CustomProviderDeleteResponse_unstable | RefreshProviderInventoryResponse_unstable | ProviderConfigReadResponse_unstable | ProviderConfigStatusResponse_unstable | ProviderConfigChangeResponse_unstable | PreferencesReadResponse_unstable | DefaultsReadResponse_unstable | OnboardingImportScanResponse_unstable | OnboardingImportApplyResponse_unstable | ExportSessionResponse_unstable | ImportSessionResponse_unstable | CreateSourceResponse_unstable | ListSourcesResponse_unstable | UpdateSourceResponse_unstable | ExportSourceResponse_unstable | ImportSourcesResponse_unstable | DictationTranscribeResponse_unstable | DictationConfigResponse_unstable | DictationModelsListResponse_unstable | DictationModelDownloadProgressResponse_unstable | unknown; -} | { - error: { - code: number; - data?: unknown; - message: string; - }; - id: string; -}; - /** * List Goose-owned extension definitions available to configure or enable. */ @@ -419,18 +320,26 @@ export type GetAvailableExtensionsResponse_unstable = { }; /** - * List configured extensions and any warnings. + * Persist a new extension to the user's global goose config. */ -export type GetConfigExtensionsRequest_unstable = { - [key: string]: unknown; +export type AddConfigExtensionRequest_unstable = { + extension: GooseExtension; + enabled?: boolean; }; /** - * List configured extensions and any warnings. + * Remove a persisted extension from the user's global goose config. */ -export type GetConfigExtensionsResponse_unstable = { - extensions: Array; - warnings?: Array; +export type RemoveConfigExtensionRequest_unstable = { + configKey: string; +}; + +/** + * Set the `enabled` flag for a persisted extension in the user's global goose config. + */ +export type SetConfigExtensionEnabledRequest_unstable = { + configKey: string; + enabled: boolean; }; export type GetSessionExtensionsRequest_unstable = { @@ -442,335 +351,440 @@ export type GetSessionExtensionsResponse_unstable = { }; /** - * List all tools available in a session. + * List providers with setup metadata and the current model inventory snapshot. */ -export type GetToolsRequest_unstable = { - sessionId: string; +export type ListProvidersRequest_unstable = { + /** + * Only return entries for these providers. Empty means all. + */ + providerIds?: Array; }; /** - * Tools response. + * Provider list response. */ -export type GetToolsResponse_unstable = { - /** - * Array of tool info objects with `name`, `description`, `parameters`, and optional `permission`. - */ - tools: Array; -}; - -export type GooseExtension = { - bundled?: boolean | null; - description?: string | null; - display_name?: string | null; - name: string; - timeout?: number | null; - type: 'builtin'; -} | { - bundled?: boolean | null; - description?: string | null; - display_name?: string | null; - name: string; - type: 'platform'; -} | { - bundled?: boolean | null; - description?: string | null; - envKeys?: Array; - server: McpServer; - socket?: string | null; - timeout?: number | null; - type: 'mcp'; -} | { - code: string; - dependencies?: Array; - description?: string | null; - name: string; - timeout?: number | null; - type: 'inline_python'; -} | { - bundled?: boolean | null; - description?: string | null; - instructions?: string | null; - name: string; - tools?: Array; - type: 'frontend'; -}; - -export type GooseExtensionEntry = { - configKey?: string | null; - enabled: boolean; - extension: GooseExtension; +export type ListProvidersResponse_unstable = { + entries: Array; }; /** - * Call a tool from an extension. + * Provider inventory entry. */ -export type GooseToolCallRequest_unstable = { - arguments?: unknown; - name: string; - sessionId: string; +export type ProviderInventoryEntryDto = { + /** + * Provider identifier. + */ + providerId: string; + /** + * Human-readable provider name. + */ + providerName: string; + /** + * Description of the provider's capabilities. + */ + description: string; + /** + * The default/recommended model for this provider. + */ + defaultModel: string; + /** + * Whether Goose has enough configuration to use this provider. + */ + configured: boolean; + /** + * Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`. + */ + providerType: string; + /** + * Whether this inventory entry represents an agent provider or a model provider. + */ + category: ProviderSetupCategoryDto; + /** + * Required configuration keys and setup metadata. + */ + configKeys: Array; + /** + * Step-by-step setup instructions, when present. + */ + setupSteps: Array; + /** + * Whether this provider supports background inventory refresh. + */ + supportsRefresh: boolean; + /** + * Whether a refresh is currently in flight. + */ + refreshing: boolean; + /** + * The list of available models. + */ + models: Array; + /** + * When this entry was last successfully refreshed (ISO 8601). + */ + lastUpdatedAt?: string | null; + /** + * When a refresh was most recently attempted (ISO 8601). + */ + lastRefreshAttemptAt?: string | null; + /** + * The last refresh failure message, if any. + */ + lastRefreshError?: string | null; + /** + * Whether we believe this data may be outdated. + */ + stale: boolean; + /** + * Guidance message shown when this provider manages its own model selection externally. + */ + modelSelectionHint?: string | null; }; -/** - * Tool call response. - */ -export type GooseToolCallResponse_unstable = { - _meta?: unknown; - content?: Array; - isError: boolean; - structuredContent?: unknown; +export type ProviderSetupCategoryDto = 'agent' | 'model'; + +export type ProviderConfigKey = { + name: string; + required: boolean; + secret: boolean; + default?: string | null; + oauthFlow?: boolean; + deviceCodeFlow?: boolean; + primary?: boolean; }; /** - * An HTTP header to set when making requests to the MCP server. + * A single model in provider inventory. */ -export type HttpHeader = { +export type ProviderInventoryModelDto = { /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + * Model identifier as the provider knows it. */ - _meta?: { - [key: string]: unknown; - } | null; + id: string; /** - * The name of the HTTP header. + * Human-readable display name. */ name: string; /** - * The value to set for the HTTP header. + * Model family for grouping in UI. */ - value: string; + family?: string | null; + /** + * Context window size in tokens. + */ + contextLimit?: number | null; + /** + * Whether the model supports reasoning/extended thinking. + */ + reasoning?: boolean | null; + /** + * Whether this model should appear in the compact recommended picker. + */ + recommended?: boolean; }; /** - * Import a session from a JSON string. + * List the raw model identifiers returned by a provider's live supported-models API. */ -export type ImportSessionRequest_unstable = { - data: string; +export type ProviderSupportedModelsListRequest_unstable = { + providerId: string; +}; + +export type ProviderSupportedModelsListResponse_unstable = { + providerId: string; + models: Array; }; /** - * Import session response — metadata about the newly created session. + * List custom-provider catalog entries. Omit `format` to list all formats. */ -export type ImportSessionResponse_unstable = { - messageCount: number; - sessionId: string; - title?: string | null; - updatedAt?: string | null; +export type ProviderCatalogListRequest_unstable = { + format?: string | null; +}; + +export type ProviderCatalogListResponse_unstable = { + providers: Array; +}; + +export type ProviderTemplateCatalogEntryDto = { + providerId: string; + name: string; + format: string; + apiUrl: string; + modelCount: number; + docUrl: string; + envVar: string; }; /** - * Import a source from a JSON export payload produced by `_goose/unstable/sources/export`. - * The imported source is written into the explicit target scope; on name - * collisions a `-imported` suffix is appended. + * List provider setup catalog entries */ -export type ImportSourcesRequest_unstable = { - data: string; - target: SourceScope; +export type ProviderSetupCatalogListRequest_unstable = { + [key: string]: unknown; }; -export type ImportSourcesResponse_unstable = { - sources: Array; +export type ProviderSetupCatalogListResponse_unstable = { + providers: Array; +}; + +export type ProviderSetupCatalogEntryDto = { + providerId: string; + name: string; + category: ProviderSetupCategoryDto; + description: string; + setupMethod: ProviderSetupMethodDto; + nativeConnectQuery?: string | null; + fields?: Array; + binaryName?: string | null; + docUrl?: string | null; + group: ProviderSetupGroupDto; + showOnlyWhenInstalled: boolean; + aliases?: Array; + supportsInstall: boolean; + supportsAuth: boolean; + supportsAuthStatus: boolean; +}; + +export type ProviderSetupMethodDto = 'none' | 'single_api_key' | 'config_fields' | 'host_with_oauth_fallback' | 'oauth_browser' | 'oauth_device_code' | 'cloud_credentials' | 'local' | 'cli_auth'; + +export type ProviderSetupFieldDto = { + key: string; + label: string; + secret: boolean; + required: boolean; + placeholder?: string | null; + defaultValue?: string | null; }; +export type ProviderSetupGroupDto = 'default' | 'additional'; + /** - * List providers with setup metadata and the current model inventory snapshot. + * Return the editable template for one catalog provider. */ -export type ListProvidersRequest_unstable = { - /** - * Only return entries for these providers. Empty means all. - */ - providerIds?: Array; +export type ProviderCatalogTemplateRequest_unstable = { + providerId: string; +}; + +export type ProviderCatalogTemplateResponse_unstable = { + template: ProviderTemplateDto; +}; + +export type ProviderTemplateDto = { + providerId: string; + name: string; + format: string; + apiUrl: string; + models: Array; + supportsStreaming: boolean; + envVar: string; + docUrl: string; +}; + +export type ProviderTemplateModelDto = { + id: string; + name: string; + contextLimit: number; + capabilities: ProviderTemplateCapabilitiesDto; + deprecated: boolean; +}; + +export type ProviderTemplateCapabilitiesDto = { + toolCall: boolean; + reasoning: boolean; + attachment: boolean; + temperature: boolean; }; /** - * Provider list response. + * Create a custom provider backed by Goose's declarative provider store. */ -export type ListProvidersResponse_unstable = { - entries: Array; +export type CustomProviderCreateRequest_unstable = { + engine: string; + displayName: string; + apiUrl: string; + apiKey?: string | null; + models?: Array; + supportsStreaming?: boolean | null; + headers?: { + [key: string]: string; + }; + requiresAuth: boolean; + catalogProviderId?: string | null; + basePath?: string | null; + preservesThinking?: boolean | null; +}; + +export type CustomProviderCreateResponse_unstable = { + providerId: string; + status: ProviderConfigStatusDto; + refresh: RefreshProviderInventoryResponse_unstable; +}; + +export type ProviderConfigStatusDto = { + providerId: string; + isConfigured: boolean; }; /** - * List discovered sources. - * - * If `type` is omitted or `skill`, this lists filesystem/plugin skills only. - * Both global and project-scoped skills are included when `project_dir` is - * set. If `type` is `builtinSkill`, this lists shipped read-only built-in - * skills. + * Refresh acknowledgement. */ -export type ListSourcesRequest_unstable = { +export type RefreshProviderInventoryResponse_unstable = { /** - * When true, also scan the working directories of all known projects for - * project-scoped sources (e.g. skills stored under `{workingDir}/.agents/skills/`). + * Which providers will be refreshed. */ - includeProjectSources?: boolean; - projectDir?: string | null; - type?: SourceType | null; + started: Array; + /** + * Which providers were skipped and why. + */ + skipped?: Array; }; -export type ListSourcesResponse_unstable = { - sources: Array; +export type RefreshProviderInventorySkipDto = { + providerId: string; + reason: RefreshProviderInventorySkipReasonDto; }; +export type RefreshProviderInventorySkipReasonDto = 'unknown_provider' | 'not_configured' | 'does_not_support_refresh' | 'already_refreshing'; + /** - * Configuration for connecting to an MCP (Model Context Protocol) server. - * - * MCP servers provide tools and context that the agent can use when - * processing prompts. - * - * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) + * Read a declarative provider config. Custom configs are editable; bundled configs are read-only. */ -export type McpServer = McpServerHttp | McpServerSse | McpServerStdio; +export type CustomProviderReadRequest_unstable = { + providerId: string; +}; + +export type CustomProviderReadResponse_unstable = { + provider: CustomProviderConfigDto; + editable: boolean; + status: ProviderConfigStatusDto; +}; + +export type CustomProviderConfigDto = { + providerId: string; + engine: string; + displayName: string; + apiUrl: string; + models?: Array; + supportsStreaming?: boolean | null; + headers?: { + [key: string]: string; + }; + requiresAuth: boolean; + catalogProviderId?: string | null; + basePath?: string | null; + apiKeyEnv?: string | null; + apiKeySet: boolean; + preservesThinking: boolean; +}; /** - * HTTP transport configuration for MCP. + * Update a custom provider backed by Goose's declarative provider store. */ -export type McpServerHttp = { - /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - */ - _meta?: { - [key: string]: unknown; - } | null; - /** - * HTTP headers to set when making requests to the MCP server. - */ - headers: Array; - /** - * Human-readable name identifying this MCP server. - */ - name: string; - type: 'http'; - /** - * URL to the MCP server. - */ - url: string; +export type CustomProviderUpdateRequest_unstable = { + providerId: string; + engine: string; + displayName: string; + apiUrl: string; + apiKey?: string | null; + models?: Array; + supportsStreaming?: boolean | null; + headers?: { + [key: string]: string; + }; + requiresAuth: boolean; + catalogProviderId?: string | null; + basePath?: string | null; + preservesThinking?: boolean | null; +}; + +export type CustomProviderUpdateResponse_unstable = { + providerId: string; + status: ProviderConfigStatusDto; + refresh: RefreshProviderInventoryResponse_unstable; }; /** - * SSE transport configuration for MCP. + * Delete a custom provider from Goose's declarative provider store. */ -export type McpServerSse = { - /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - */ - _meta?: { - [key: string]: unknown; - } | null; - /** - * HTTP headers to set when making requests to the MCP server. - */ - headers: Array; - /** - * Human-readable name identifying this MCP server. - */ - name: string; - type: 'sse'; - /** - * URL to the MCP server. - */ - url: string; +export type CustomProviderDeleteRequest_unstable = { + providerId: string; +}; + +export type CustomProviderDeleteResponse_unstable = { + providerId: string; + refresh: RefreshProviderInventoryResponse_unstable; }; /** - * Stdio transport configuration for MCP. + * Trigger a background refresh of provider inventories. */ -export type McpServerStdio = { - /** - * The _meta property is reserved by ACP to allow clients and agents to attach additional - * metadata to their interactions. Implementations MUST NOT make assumptions about values at - * these keys. - * - * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) - */ - _meta?: { - [key: string]: unknown; - } | null; - /** - * Command-line arguments to pass to the MCP server. - */ - args: Array; - /** - * Path to the MCP server executable. - */ - command: string; - /** - * Environment variables to set when launching the MCP server. - */ - env: Array; +export type RefreshProviderInventoryRequest_unstable = { /** - * Human-readable name identifying this MCP server. + * Which providers to refresh. Empty means all known providers. */ - name: string; + providerIds?: Array; }; /** - * Import selected onboarding candidates. + * Read saved configuration field values for one provider. */ -export type OnboardingImportApplyRequest_unstable = { - candidateIds?: Array; - enableImportedExtensions?: boolean; +export type ProviderConfigReadRequest_unstable = { + providerId: string; }; -export type OnboardingImportApplyResponse_unstable = { - imported: OnboardingImportCounts; - providerDefaults?: DefaultsReadResponse_unstable | null; - skipped: OnboardingImportCounts; - warnings?: Array; +export type ProviderConfigReadResponse_unstable = { + fields: Array; }; -export type OnboardingImportCandidate = { - counts: OnboardingImportCounts; - displayName: string; - id: string; - path: string; - sourceKind: OnboardingImportSourceKind; - warnings?: Array; +export type ProviderConfigFieldValueDto = { + key: string; + value?: string | null; + isSet: boolean; + isSecret: boolean; + required: boolean; }; -export type OnboardingImportCounts = { - extensions: number; - preferences: number; - projects: number; - providers: number; - sessions: number; - skills: number; +/** + * Return provider configured statuses. Empty provider_ids means all providers. + */ +export type ProviderConfigStatusRequest_unstable = { + providerIds?: Array; +}; + +export type ProviderConfigStatusResponse_unstable = { + statuses: Array; }; /** - * Scan for existing Goose and compatible app data that onboarding can import. + * Save provider configuration fields and start an inventory refresh when supported. */ -export type OnboardingImportScanRequest_unstable = { - /** - * Empty means all supported import sources. - */ - sources?: Array; +export type ProviderConfigSaveRequest_unstable = { + providerId: string; + fields: Array; }; -export type OnboardingImportScanResponse_unstable = { - candidates: Array; +export type ProviderConfigFieldUpdate = { + key: string; + value: string; +}; + +export type ProviderConfigChangeResponse_unstable = { + status: ProviderConfigStatusDto; + refresh: RefreshProviderInventoryResponse_unstable; }; /** - * Sources that onboarding knows how to discover and import. + * Delete provider configuration fields and start an inventory refresh when supported. */ -export type OnboardingImportSourceKind = 'goose_config' | 'claude_desktop'; - -export type PreferenceKey = 'autoCompactThreshold' | 'voiceAutoSubmitPhrases' | 'voiceDictationProvider' | 'voiceDictationPreferredMic'; +export type ProviderConfigDeleteRequest_unstable = { + providerId: string; +}; -export type PreferenceValue = { - key: PreferenceKey; - value?: unknown; +/** + * Run a provider-owned native authentication flow and start an inventory refresh when supported. + */ +export type ProviderConfigAuthenticateRequest_unstable = { + providerId: string; }; /** @@ -780,10 +794,24 @@ export type PreferencesReadRequest_unstable = { keys?: Array; }; +export type PreferenceKey = 'autoCompactThreshold' | 'voiceAutoSubmitPhrases' | 'voiceDictationProvider' | 'voiceDictationPreferredMic'; + export type PreferencesReadResponse_unstable = { values: Array; }; +export type PreferenceValue = { + key: PreferenceKey; + value?: unknown; +}; + +/** + * Save allowlisted user preferences. + */ +export type PreferencesSaveRequest_unstable = { + values?: Array; +}; + /** * Remove allowlisted user preferences. */ @@ -792,510 +820,468 @@ export type PreferencesRemoveRequest_unstable = { }; /** - * Save allowlisted user preferences. + * Read Goose default provider and model configuration. */ -export type PreferencesSaveRequest_unstable = { - values?: Array; +export type DefaultsReadRequest_unstable = { + [key: string]: unknown; +}; + +export type DefaultsReadResponse_unstable = { + providerId?: string | null; + modelId?: string | null; }; /** - * List custom-provider catalog entries. Omit `format` to list all formats. + * Save Goose default provider and model configuration. */ -export type ProviderCatalogListRequest_unstable = { - format?: string | null; +export type DefaultsSaveRequest_unstable = { + providerId: string; + modelId?: string | null; }; -export type ProviderCatalogListResponse_unstable = { - providers: Array; +/** + * Scan for existing Goose and compatible app data that onboarding can import. + */ +export type OnboardingImportScanRequest_unstable = { + /** + * Empty means all supported import sources. + */ + sources?: Array; }; /** - * Return the editable template for one catalog provider. + * Sources that onboarding knows how to discover and import. */ -export type ProviderCatalogTemplateRequest_unstable = { - providerId: string; +export type OnboardingImportSourceKind = 'goose_config' | 'claude_desktop'; + +export type OnboardingImportScanResponse_unstable = { + candidates: Array; }; -export type ProviderCatalogTemplateResponse_unstable = { - template: ProviderTemplateDto; +export type OnboardingImportCandidate = { + id: string; + sourceKind: OnboardingImportSourceKind; + displayName: string; + path: string; + counts: OnboardingImportCounts; + warnings?: Array; +}; + +export type OnboardingImportCounts = { + providers: number; + extensions: number; + sessions: number; + skills: number; + projects: number; + preferences: number; }; /** - * Run a provider-owned native authentication flow and start an inventory refresh when supported. + * Import selected onboarding candidates. */ -export type ProviderConfigAuthenticateRequest_unstable = { - providerId: string; +export type OnboardingImportApplyRequest_unstable = { + candidateIds?: Array; + enableImportedExtensions?: boolean; }; -export type ProviderConfigChangeResponse_unstable = { - refresh: RefreshProviderInventoryResponse_unstable; - status: ProviderConfigStatusDto; +export type OnboardingImportApplyResponse_unstable = { + imported: OnboardingImportCounts; + skipped: OnboardingImportCounts; + warnings?: Array; + providerDefaults?: DefaultsReadResponse_unstable | null; }; /** - * Delete provider configuration fields and start an inventory refresh when supported. + * Export a session as a JSON string. */ -export type ProviderConfigDeleteRequest_unstable = { - providerId: string; +export type ExportSessionRequest_unstable = { + sessionId: string; }; -export type ProviderConfigFieldUpdate = { - key: string; - value: string; +/** + * Export session response — raw JSON of the goose session with `conversation`. + */ +export type ExportSessionResponse_unstable = { + data: string; }; -export type ProviderConfigFieldValueDto = { - isSecret: boolean; - isSet: boolean; - key: string; - required: boolean; - value?: string | null; +/** + * Import a session from a JSON string. + */ +export type ImportSessionRequest_unstable = { + data: string; }; -export type ProviderConfigKey = { - default?: string | null; - deviceCodeFlow?: boolean; - name: string; - oauthFlow?: boolean; - primary?: boolean; - required: boolean; - secret: boolean; +/** + * Import session response — metadata about the newly created session. + */ +export type ImportSessionResponse_unstable = { + sessionId: string; + title?: string | null; + updatedAt?: string | null; + messageCount: number; }; /** - * Read saved configuration field values for one provider. + * Update the project association for a session. */ -export type ProviderConfigReadRequest_unstable = { - providerId: string; +export type UpdateSessionProjectRequest_unstable = { + sessionId: string; + projectId?: string | null; }; -export type ProviderConfigReadResponse_unstable = { - fields: Array; +/** + * Rename a session. + */ +export type RenameSessionRequest_unstable = { + sessionId: string; + title: string; }; /** - * Save provider configuration fields and start an inventory refresh when supported. + * Archive a session (soft delete). */ -export type ProviderConfigSaveRequest_unstable = { - fields: Array; - providerId: string; +export type ArchiveSessionRequest_unstable = { + sessionId: string; }; -export type ProviderConfigStatusDto = { - isConfigured: boolean; - providerId: string; +/** + * Unarchive a previously archived session. + */ +export type UnarchiveSessionRequest_unstable = { + sessionId: string; +}; + +/** + * Create a new source in an explicit target scope (global or project-scoped). + */ +export type CreateSourceRequest_unstable = { + type: SourceType; + name: string; + description: string; + content: string; + target: SourceScope; + /** + * Arbitrary key/value metadata. + */ + properties?: { + [key: string]: unknown; + }; }; /** - * Return provider configured statuses. Empty provider_ids means all providers. + * The type of source entity. + */ +export type SourceType = 'skill' | 'builtinSkill' | 'recipe' | 'subrecipe' | 'agent' | 'project'; + +/** + * Target scope for creating or importing sources. */ -export type ProviderConfigStatusRequest_unstable = { - providerIds?: Array; +export type SourceScope = { + scope: 'global'; +} | { + projectDir: string; + scope: 'projectDir'; +} | { + projectId: string; + scope: 'projectId'; }; -export type ProviderConfigStatusResponse_unstable = { - statuses: Array; +export type CreateSourceResponse_unstable = { + source: SourceEntry; }; /** - * Provider inventory entry. + * A source discovered by Goose. Filesystem sources use an on-disk path; + * built-in sources use a stable synthetic path. Sources may be either + * `global` (shared across all projects) or project-specific. */ -export type ProviderInventoryEntryDto = { - /** - * Whether this inventory entry represents an agent provider or a model provider. - */ - category: ProviderSetupCategoryDto; - /** - * Required configuration keys and setup metadata. - */ - configKeys: Array; - /** - * Whether Goose has enough configuration to use this provider. - */ - configured: boolean; - /** - * The default/recommended model for this provider. - */ - defaultModel: string; - /** - * Description of the provider's capabilities. - */ +export type SourceEntry = { + type: SourceType; + name: string; description: string; + content: string; /** - * When a refresh was most recently attempted (ISO 8601). - */ - lastRefreshAttemptAt?: string | null; - /** - * The last refresh failure message, if any. - */ - lastRefreshError?: string | null; - /** - * When this entry was last successfully refreshed (ISO 8601). - */ - lastUpdatedAt?: string | null; - /** - * Guidance message shown when this provider manages its own model selection externally. - */ - modelSelectionHint?: string | null; - /** - * The list of available models. - */ - models: Array; - /** - * Provider identifier. - */ - providerId: string; - /** - * Human-readable provider name. - */ - providerName: string; - /** - * Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`. + * Stable on-disk path identifying this source. Pass it back to + * update/delete/export to operate on this entry. Skills use the directory + * containing `SKILL.md`; projects use the project file path; built-in + * skills use `builtin://skills/` synthetic paths. */ - providerType: string; + path: string; /** - * Whether a refresh is currently in flight. + * True when the source lives in the user's global sources directory; false + * when it lives inside a specific project. */ - refreshing: boolean; + global: boolean; /** - * Step-by-step setup instructions, when present. + * True when this source can be modified through source CRUD methods. + * Client-provided bundled sources are returned as read-only. */ - setupSteps: Array; + writable?: boolean; /** - * Whether we believe this data may be outdated. + * Paths (absolute) of additional files that live alongside the source. + * Only skills currently populate this; empty for other source types. */ - stale: boolean; + supportingFiles?: Array; /** - * Whether this provider supports background inventory refresh. + * Arbitrary key/value pairs for type-specific metadata (e.g. icon, color, + * preferredProvider for projects). Stored in the frontmatter. */ - supportsRefresh: boolean; + properties?: { + [key: string]: unknown; + }; }; /** - * A single model in provider inventory. + * List discovered sources. + * + * If `type` is omitted or `skill`, this lists filesystem/plugin skills only. + * Both global and project-scoped skills are included when `project_dir` is + * set. If `type` is `builtinSkill`, this lists shipped read-only built-in + * skills. */ -export type ProviderInventoryModelDto = { - /** - * Context window size in tokens. - */ - contextLimit?: number | null; - /** - * Model family for grouping in UI. - */ - family?: string | null; - /** - * Model identifier as the provider knows it. - */ - id: string; - /** - * Human-readable display name. - */ - name: string; - /** - * Whether the model supports reasoning/extended thinking. - */ - reasoning?: boolean | null; +export type ListSourcesRequest_unstable = { + type?: SourceType | null; + projectDir?: string | null; /** - * Whether this model should appear in the compact recommended picker. + * When true, also scan the working directories of all known projects for + * project-scoped sources (e.g. skills stored under `{workingDir}/.agents/skills/`). */ - recommended?: boolean; + includeProjectSources?: boolean; }; -export type ProviderSetupCatalogEntryDto = { - aliases?: Array; - binaryName?: string | null; - category: ProviderSetupCategoryDto; - description: string; - docUrl?: string | null; - fields?: Array; - group: ProviderSetupGroupDto; - name: string; - nativeConnectQuery?: string | null; - providerId: string; - setupMethod: ProviderSetupMethodDto; - showOnlyWhenInstalled: boolean; - supportsAuth: boolean; - supportsAuthStatus: boolean; - supportsInstall: boolean; +export type ListSourcesResponse_unstable = { + sources: Array; }; /** - * List provider setup catalog entries + * Update an existing source's name, description, and content by absolute path. */ -export type ProviderSetupCatalogListRequest_unstable = { - [key: string]: unknown; -}; - -export type ProviderSetupCatalogListResponse_unstable = { - providers: Array; +export type UpdateSourceRequest_unstable = { + type: SourceType; + path: string; + name: string; + description: string; + content: string; + /** + * When `Some`, replaces all stored properties on the source. When + * `None` (or omitted), the source's existing properties are + * preserved. Callers that don't model the full property bag (e.g. + * the skills editor, which only edits name/description/content) + * should omit this so per-skill metadata isn't silently erased. + */ + properties?: { + [key: string]: unknown; + } | null; }; -export type ProviderSetupCategoryDto = 'agent' | 'model'; - -export type ProviderSetupFieldDto = { - defaultValue?: string | null; - key: string; - label: string; - placeholder?: string | null; - required: boolean; - secret: boolean; +export type UpdateSourceResponse_unstable = { + source: SourceEntry; }; -export type ProviderSetupGroupDto = 'default' | 'additional'; - -export type ProviderSetupMethodDto = 'none' | 'single_api_key' | 'config_fields' | 'host_with_oauth_fallback' | 'oauth_browser' | 'oauth_device_code' | 'cloud_credentials' | 'local' | 'cli_auth'; - /** - * List the raw model identifiers returned by a provider's live supported-models API. + * Delete a source and its on-disk directory by absolute path. */ -export type ProviderSupportedModelsListRequest_unstable = { - providerId: string; -}; - -export type ProviderSupportedModelsListResponse_unstable = { - models: Array; - providerId: string; -}; - -export type ProviderTemplateCapabilitiesDto = { - attachment: boolean; - reasoning: boolean; - temperature: boolean; - toolCall: boolean; -}; - -export type ProviderTemplateCatalogEntryDto = { - apiUrl: string; - docUrl: string; - envVar: string; - format: string; - modelCount: number; - name: string; - providerId: string; -}; - -export type ProviderTemplateDto = { - apiUrl: string; - docUrl: string; - envVar: string; - format: string; - models: Array; - name: string; - providerId: string; - supportsStreaming: boolean; -}; - -export type ProviderTemplateModelDto = { - capabilities: ProviderTemplateCapabilitiesDto; - contextLimit: number; - deprecated: boolean; - id: string; - name: string; +export type DeleteSourceRequest_unstable = { + type: SourceType; + path: string; }; /** - * Read a resource from an extension. + * Export a source at an absolute path as a portable JSON payload. */ -export type ReadResourceRequest_unstable = { - extensionName: string; - sessionId: string; - uri: string; +export type ExportSourceRequest_unstable = { + type: SourceType; + path: string; +}; + +export type ExportSourceResponse_unstable = { + json: string; + filename: string; }; /** - * Resource read response. + * Import a source from a JSON export payload produced by `_goose/unstable/sources/export`. + * The imported source is written into the explicit target scope; on name + * collisions a `-imported` suffix is appended. */ -export type ReadResourceResponse_unstable = { - /** - * The resource result from the extension (MCP ReadResourceResult). - */ - result?: unknown; +export type ImportSourcesRequest_unstable = { + data: string; + target: SourceScope; }; -/** - * Trigger a background refresh of provider inventories. - */ -export type RefreshProviderInventoryRequest_unstable = { - /** - * Which providers to refresh. Empty means all known providers. - */ - providerIds?: Array; +export type ImportSourcesResponse_unstable = { + sources: Array; }; /** - * Refresh acknowledgement. + * Transcribe audio via a dictation provider. */ -export type RefreshProviderInventoryResponse_unstable = { +export type DictationTranscribeRequest_unstable = { /** - * Which providers were skipped and why. + * Base64-encoded audio data */ - skipped?: Array; + audio: string; /** - * Which providers will be refreshed. + * MIME type (e.g. "audio/wav", "audio/webm") */ - started: Array; + mimeType: string; + /** + * Provider to use: "openai", "groq", "elevenlabs", or "local" + */ + provider: string; }; -export type RefreshProviderInventorySkipDto = { - providerId: string; - reason: RefreshProviderInventorySkipReasonDto; +/** + * Transcription result. + */ +export type DictationTranscribeResponse_unstable = { + text: string; }; -export type RefreshProviderInventorySkipReasonDto = 'unknown_provider' | 'not_configured' | 'does_not_support_refresh' | 'already_refreshing'; +/** + * Get the configuration status of all dictation providers. + */ +export type DictationConfigRequest_unstable = { + [key: string]: unknown; +}; /** - * Remove a persisted extension from the user's global goose config. + * Dictation config response — map of provider name to status. */ -export type RemoveConfigExtensionRequest_unstable = { - configKey: string; +export type DictationConfigResponse_unstable = { + providers: { + [key: string]: DictationProviderStatusEntry; + }; }; /** - * Remove an extension from an active session. + * Per-provider configuration status. */ -export type RemoveExtensionRequest_unstable = { - name: string; - sessionId: string; +export type DictationProviderStatusEntry = { + configured: boolean; + host?: string | null; + description: string; + usesProviderConfig: boolean; + settingsPath?: string | null; + configKey?: string | null; + modelConfigKey?: string | null; + defaultModel?: string | null; + selectedModel?: string | null; + availableModels?: Array; +}; + +export type DictationModelOption = { + id: string; + label: string; + description: string; }; /** - * Rename a session. + * Set a dictation provider secret value. */ -export type RenameSessionRequest_unstable = { - sessionId: string; - title: string; +export type DictationSecretSaveRequest_unstable = { + provider: string; + value: string; }; /** - * How a session system prompt update should be applied. + * Remove a dictation provider secret value. */ -export type SessionSystemPromptMode = 'set' | 'append'; +export type DictationSecretDeleteRequest_unstable = { + provider: string; +}; /** - * Set the `enabled` flag for a persisted extension in the user's global goose config. + * List available local Whisper models with their download status. */ -export type SetConfigExtensionEnabledRequest_unstable = { - configKey: string; - enabled: boolean; +export type DictationModelsListRequest_unstable = { + [key: string]: unknown; +}; + +export type DictationModelsListResponse_unstable = { + models: Array; +}; + +export type DictationLocalModelStatus = { + id: string; + label: string; + description: string; + sizeMb: number; + downloaded: boolean; + downloadInProgress: boolean; }; /** - * Set, append, or clear system prompt text for a session. - * - * `mode: "set"` replaces Goose's base system prompt. `mode: "append"` adds an - * instruction under "Additional Instructions". Reusing a key replaces the - * previous value for that mode/key; sending empty text clears it. + * Kick off a background download of a local Whisper model. */ -export type SetSessionSystemPromptRequest_unstable = { - key?: string | null; - mode?: SessionSystemPromptMode; - sessionId: string; - text: string; +export type DictationModelDownloadRequest_unstable = { + modelId: string; }; /** - * A source discovered by Goose. Filesystem sources use an on-disk path; - * built-in sources use a stable synthetic path. Sources may be either - * `global` (shared across all projects) or project-specific. + * Poll the progress of an in-flight download. */ -export type SourceEntry = { - content: string; - description: string; - /** - * True when the source lives in the user's global sources directory; false - * when it lives inside a specific project. - */ - global: boolean; - name: string; - /** - * Stable on-disk path identifying this source. Pass it back to - * update/delete/export to operate on this entry. Skills use the directory - * containing `SKILL.md`; projects use the project file path; built-in - * skills use `builtin://skills/` synthetic paths. - */ - path: string; - /** - * Arbitrary key/value pairs for type-specific metadata (e.g. icon, color, - * preferredProvider for projects). Stored in the frontmatter. - */ - properties?: { - [key: string]: unknown; - }; +export type DictationModelDownloadProgressRequest_unstable = { + modelId: string; +}; + +export type DictationModelDownloadProgressResponse_unstable = { /** - * Paths (absolute) of additional files that live alongside the source. - * Only skills currently populate this; empty for other source types. + * None when no download is active for this model id. */ - supportingFiles?: Array; - type: SourceType; + progress?: DictationDownloadProgress | null; +}; + +export type DictationDownloadProgress = { + bytesDownloaded: number; + totalBytes: number; + progressPercent: number; /** - * True when this source can be modified through source CRUD methods. - * Client-provided bundled sources are returned as read-only. + * serde lowercase of DownloadStatus: "downloading" | "completed" | "failed" | "cancelled" */ - writable?: boolean; + status: string; + error?: string | null; }; /** - * Target scope for creating or importing sources. + * Cancel an in-flight download. */ -export type SourceScope = { - scope: 'global'; -} | { - projectDir: string; - scope: 'projectDir'; -} | { - projectId: string; - scope: 'projectId'; +export type DictationModelCancelRequest_unstable = { + modelId: string; }; /** - * The type of source entity. - */ -export type SourceType = 'skill' | 'builtinSkill' | 'recipe' | 'subrecipe' | 'agent' | 'project'; - -/** - * Unarchive a previously archived session. + * Delete a downloaded local Whisper model from disk. */ -export type UnarchiveSessionRequest_unstable = { - sessionId: string; +export type DictationModelDeleteRequest_unstable = { + modelId: string; }; /** - * Update the project association for a session. + * Persist the user's model selection for a given provider. */ -export type UpdateSessionProjectRequest_unstable = { - projectId?: string | null; - sessionId: string; +export type DictationModelSelectRequest_unstable = { + provider: string; + modelId: string; }; -/** - * Update an existing source's name, description, and content by absolute path. - */ -export type UpdateSourceRequest_unstable = { - content: string; - description: string; - name: string; - path: string; - /** - * When `Some`, replaces all stored properties on the source. When - * `None` (or omitted), the source's existing properties are - * preserved. Callers that don't model the full property bag (e.g. - * the skills editor, which only edits name/description/content) - * should omit this so per-skill metadata isn't silently erased. - */ - properties?: { +export type ExtRequest = { + id: string; + method: string; + params?: AddExtensionRequest_unstable | RemoveExtensionRequest_unstable | GetToolsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | DeleteSessionRequest | GetConfigExtensionsRequest_unstable | GetAvailableExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | SetConfigExtensionEnabledRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | { [key: string]: unknown; } | null; - type: SourceType; -}; - -export type UpdateSourceResponse_unstable = { - source: SourceEntry; }; -/** - * Update the working directory for a session. - */ -export type UpdateWorkingDirRequest_unstable = { - sessionId: string; - workingDir: string; +export type ExtResponse = { + id: string; + result?: EmptyResponse | GetToolsResponse_unstable | GooseToolCallResponse_unstable | ReadResourceResponse_unstable | GetConfigExtensionsResponse_unstable | GetAvailableExtensionsResponse_unstable | GetSessionExtensionsResponse_unstable | ListProvidersResponse_unstable | ProviderSupportedModelsListResponse_unstable | ProviderCatalogListResponse_unstable | ProviderSetupCatalogListResponse_unstable | ProviderCatalogTemplateResponse_unstable | CustomProviderCreateResponse_unstable | CustomProviderReadResponse_unstable | CustomProviderUpdateResponse_unstable | CustomProviderDeleteResponse_unstable | RefreshProviderInventoryResponse_unstable | ProviderConfigReadResponse_unstable | ProviderConfigStatusResponse_unstable | ProviderConfigChangeResponse_unstable | PreferencesReadResponse_unstable | DefaultsReadResponse_unstable | OnboardingImportScanResponse_unstable | OnboardingImportApplyResponse_unstable | ExportSessionResponse_unstable | ImportSessionResponse_unstable | CreateSourceResponse_unstable | ListSourcesResponse_unstable | UpdateSourceResponse_unstable | ExportSourceResponse_unstable | ImportSourcesResponse_unstable | DictationTranscribeResponse_unstable | DictationConfigResponse_unstable | DictationModelsListResponse_unstable | DictationModelDownloadProgressResponse_unstable | unknown; +} | { + error: { + code: number; + message: string; + data?: unknown; + }; + id: string; }; diff --git a/ui/sdk/src/generated/zod.gen.ts b/ui/sdk/src/generated/zod.gen.ts index 9f0817213da5..57c5784e75e1 100644 --- a/ui/sdk/src/generated/zod.gen.ts +++ b/ui/sdk/src/generated/zod.gen.ts @@ -6,484 +6,183 @@ import { z } from 'zod'; * Add an extension to an active session. */ export const zAddExtensionRequest_unstable = z.object({ - config: z.unknown().optional().default(null), - sessionId: z.string() + sessionId: z.string(), + config: z.unknown().optional().default(null) }); /** - * Archive a session (soft delete). + * Empty success response for operations that return no data. */ -export const zArchiveSessionRequest_unstable = z.object({ - sessionId: z.string() -}); +export const zEmptyResponse = z.record(z.unknown()); -export const zCustomProviderConfigDto = z.object({ - apiKeyEnv: z.union([ - z.string(), - z.null() - ]).optional(), - apiKeySet: z.boolean(), - apiUrl: z.string(), - basePath: z.union([ - z.string(), - z.null() - ]).optional(), - catalogProviderId: z.union([ - z.string(), - z.null() - ]).optional(), - displayName: z.string(), - engine: z.string(), - headers: z.record(z.string()).optional().default({}), - models: z.array(z.string()).optional().default([]), - preservesThinking: z.boolean(), - providerId: z.string(), - requiresAuth: z.boolean(), - supportsStreaming: z.union([ - z.boolean(), - z.null() - ]).optional() +/** + * Remove an extension from an active session. + */ +export const zRemoveExtensionRequest_unstable = z.object({ + sessionId: z.string(), + name: z.string() }); /** - * Create a custom provider backed by Goose's declarative provider store. + * List all tools available in a session. */ -export const zCustomProviderCreateRequest_unstable = z.object({ - apiKey: z.union([ - z.string(), - z.null() - ]).optional(), - apiUrl: z.string(), - basePath: z.union([ - z.string(), - z.null() - ]).optional(), - catalogProviderId: z.union([ - z.string(), - z.null() - ]).optional(), - displayName: z.string(), - engine: z.string(), - headers: z.record(z.string()).optional().default({}), - models: z.array(z.string()).optional().default([]), - preservesThinking: z.union([ - z.boolean(), - z.null() - ]).optional(), - requiresAuth: z.boolean(), - supportsStreaming: z.union([ - z.boolean(), - z.null() - ]).optional() +export const zGetToolsRequest_unstable = z.object({ + sessionId: z.string() }); /** - * Delete a custom provider from Goose's declarative provider store. + * Tools response. */ -export const zCustomProviderDeleteRequest_unstable = z.object({ - providerId: z.string() +export const zGetToolsResponse_unstable = z.object({ + tools: z.array(z.unknown()) }); /** - * Read a declarative provider config. Custom configs are editable; bundled configs are read-only. + * Call a tool from an extension. */ -export const zCustomProviderReadRequest_unstable = z.object({ - providerId: z.string() +export const zGooseToolCallRequest_unstable = z.object({ + sessionId: z.string(), + name: z.string(), + arguments: z.unknown().optional().default(null) }); /** - * Update a custom provider backed by Goose's declarative provider store. + * Tool call response. */ -export const zCustomProviderUpdateRequest_unstable = z.object({ - apiKey: z.union([ - z.string(), - z.null() - ]).optional(), - apiUrl: z.string(), - basePath: z.union([ - z.string(), - z.null() - ]).optional(), - catalogProviderId: z.union([ - z.string(), - z.null() - ]).optional(), - displayName: z.string(), - engine: z.string(), - headers: z.record(z.string()).optional().default({}), - models: z.array(z.string()).optional().default([]), - preservesThinking: z.union([ - z.boolean(), - z.null() - ]).optional(), - providerId: z.string(), - requiresAuth: z.boolean(), - supportsStreaming: z.union([ - z.boolean(), - z.null() - ]).optional() +export const zGooseToolCallResponse_unstable = z.object({ + content: z.array(z.unknown()).optional().default([]), + structuredContent: z.unknown().optional(), + isError: z.boolean(), + _meta: z.unknown().optional() }); /** - * Read Goose default provider and model configuration. + * Read a resource from an extension. */ -export const zDefaultsReadRequest_unstable = z.record(z.unknown()); - -export const zDefaultsReadResponse_unstable = z.object({ - modelId: z.union([ - z.string(), - z.null() - ]).optional(), - providerId: z.union([ - z.string(), - z.null() - ]).optional() +export const zReadResourceRequest_unstable = z.object({ + sessionId: z.string(), + uri: z.string(), + extensionName: z.string() }); /** - * Save Goose default provider and model configuration. + * Resource read response. */ -export const zDefaultsSaveRequest_unstable = z.object({ - modelId: z.union([ - z.string(), - z.null() - ]).optional(), - providerId: z.string() +export const zReadResourceResponse_unstable = z.object({ + result: z.unknown().optional().default(null) }); /** - * Delete a session. + * Update the working directory for a session. */ -export const zDeleteSessionRequest = z.object({ - sessionId: z.string() +export const zUpdateWorkingDirRequest_unstable = z.object({ + sessionId: z.string(), + workingDir: z.string() }); /** - * Get the configuration status of all dictation providers. + * How a session system prompt update should be applied. */ -export const zDictationConfigRequest_unstable = z.record(z.unknown()); +export const zSessionSystemPromptMode = z.union([ + z.literal('set'), + z.literal('append') +]); -export const zDictationDownloadProgress = z.object({ - bytesDownloaded: z.number().int().gte(0), - error: z.union([ +/** + * Set, append, or clear system prompt text for a session. + * + * `mode: "set"` replaces Goose's base system prompt. `mode: "append"` adds an + * instruction under "Additional Instructions". Reusing a key replaces the + * previous value for that mode/key; sending empty text clears it. + */ +export const zSetSessionSystemPromptRequest_unstable = z.object({ + sessionId: z.string(), + mode: zSessionSystemPromptMode.optional().default('append'), + key: z.union([ z.string(), z.null() ]).optional(), - progressPercent: z.number(), - status: z.string(), - totalBytes: z.number().int().gte(0) -}); - -export const zDictationLocalModelStatus = z.object({ - description: z.string(), - downloadInProgress: z.boolean(), - downloaded: z.boolean(), - id: z.string(), - label: z.string(), - sizeMb: z.number().int().gte(0) + text: z.string() }); /** - * Cancel an in-flight download. + * Delete a session. */ -export const zDictationModelCancelRequest_unstable = z.object({ - modelId: z.string() +export const zDeleteSessionRequest = z.object({ + sessionId: z.string() }); /** - * Delete a downloaded local Whisper model from disk. + * List configured extensions and any warnings. */ -export const zDictationModelDeleteRequest_unstable = z.object({ - modelId: z.string() -}); +export const zGetConfigExtensionsRequest_unstable = z.record(z.unknown()); /** - * Poll the progress of an in-flight download. + * An HTTP header to set when making requests to the MCP server. */ -export const zDictationModelDownloadProgressRequest_unstable = z.object({ - modelId: z.string() -}); - -export const zDictationModelDownloadProgressResponse_unstable = z.object({ - progress: z.union([ - zDictationDownloadProgress, +export const zHttpHeader = z.object({ + name: z.string(), + value: z.string(), + _meta: z.union([ + z.record(z.unknown()), z.null() ]).optional() }); /** - * Kick off a background download of a local Whisper model. + * HTTP transport configuration for MCP. */ -export const zDictationModelDownloadRequest_unstable = z.object({ - modelId: z.string() -}); - -export const zDictationModelOption = z.object({ - description: z.string(), - id: z.string(), - label: z.string() +export const zMcpServerHttp = z.object({ + name: z.string(), + url: z.string(), + headers: z.array(zHttpHeader), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional(), + type: z.literal('http') }); /** - * Persist the user's model selection for a given provider. + * SSE transport configuration for MCP. */ -export const zDictationModelSelectRequest_unstable = z.object({ - modelId: z.string(), - provider: z.string() +export const zMcpServerSse = z.object({ + name: z.string(), + url: z.string(), + headers: z.array(zHttpHeader), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional(), + type: z.literal('sse') }); /** - * List available local Whisper models with their download status. + * An environment variable to set when launching an MCP server. */ -export const zDictationModelsListRequest_unstable = z.record(z.unknown()); - -export const zDictationModelsListResponse_unstable = z.object({ - models: z.array(zDictationLocalModelStatus) +export const zEnvVariable = z.object({ + name: z.string(), + value: z.string(), + _meta: z.union([ + z.record(z.unknown()), + z.null() + ]).optional() }); /** - * Per-provider configuration status. + * Stdio transport configuration for MCP. */ -export const zDictationProviderStatusEntry = z.object({ - availableModels: z.array(zDictationModelOption).optional().default([]), - configKey: z.union([ - z.string(), - z.null() - ]).optional(), - configured: z.boolean(), - defaultModel: z.union([ - z.string(), - z.null() - ]).optional(), - description: z.string(), - host: z.union([ - z.string(), - z.null() - ]).optional(), - modelConfigKey: z.union([ - z.string(), - z.null() - ]).optional(), - selectedModel: z.union([ - z.string(), - z.null() - ]).optional(), - settingsPath: z.union([ - z.string(), - z.null() - ]).optional(), - usesProviderConfig: z.boolean() -}); - -/** - * Dictation config response — map of provider name to status. - */ -export const zDictationConfigResponse_unstable = z.object({ - providers: z.record(zDictationProviderStatusEntry) -}); - -/** - * Remove a dictation provider secret value. - */ -export const zDictationSecretDeleteRequest_unstable = z.object({ - provider: z.string() -}); - -/** - * Set a dictation provider secret value. - */ -export const zDictationSecretSaveRequest_unstable = z.object({ - provider: z.string(), - value: z.string() -}); - -/** - * Transcribe audio via a dictation provider. - */ -export const zDictationTranscribeRequest_unstable = z.object({ - audio: z.string(), - mimeType: z.string(), - provider: z.string() -}); - -/** - * Transcription result. - */ -export const zDictationTranscribeResponse_unstable = z.object({ - text: z.string() -}); - -/** - * Empty success response for operations that return no data. - */ -export const zEmptyResponse = z.record(z.unknown()); - -/** - * An environment variable to set when launching an MCP server. - */ -export const zEnvVariable = z.object({ - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional(), - name: z.string(), - value: z.string() -}); - -/** - * Export a session as a JSON string. - */ -export const zExportSessionRequest_unstable = z.object({ - sessionId: z.string() -}); - -/** - * Export session response — raw JSON of the goose session with `conversation`. - */ -export const zExportSessionResponse_unstable = z.object({ - data: z.string() -}); - -export const zExportSourceResponse_unstable = z.object({ - filename: z.string(), - json: z.string() -}); - -/** - * List Goose-owned extension definitions available to configure or enable. - */ -export const zGetAvailableExtensionsRequest_unstable = z.record(z.unknown()); - -/** - * List configured extensions and any warnings. - */ -export const zGetConfigExtensionsRequest_unstable = z.record(z.unknown()); - -export const zGetSessionExtensionsRequest_unstable = z.object({ - sessionId: z.string() -}); - -export const zGetSessionExtensionsResponse_unstable = z.object({ - extensions: z.array(z.unknown()) -}); - -/** - * List all tools available in a session. - */ -export const zGetToolsRequest_unstable = z.object({ - sessionId: z.string() -}); - -/** - * Tools response. - */ -export const zGetToolsResponse_unstable = z.object({ - tools: z.array(z.unknown()) -}); - -/** - * Call a tool from an extension. - */ -export const zGooseToolCallRequest_unstable = z.object({ - arguments: z.unknown().optional().default(null), - name: z.string(), - sessionId: z.string() -}); - -/** - * Tool call response. - */ -export const zGooseToolCallResponse_unstable = z.object({ - _meta: z.unknown().optional(), - content: z.array(z.unknown()).optional().default([]), - isError: z.boolean(), - structuredContent: z.unknown().optional() -}); - -/** - * An HTTP header to set when making requests to the MCP server. - */ -export const zHttpHeader = z.object({ - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional(), - name: z.string(), - value: z.string() -}); - -/** - * Import a session from a JSON string. - */ -export const zImportSessionRequest_unstable = z.object({ - data: z.string() -}); - -/** - * Import session response — metadata about the newly created session. - */ -export const zImportSessionResponse_unstable = z.object({ - messageCount: z.number().int().gte(0), - sessionId: z.string(), - title: z.union([ - z.string(), - z.null() - ]).optional(), - updatedAt: z.union([ - z.string(), +export const zMcpServerStdio = z.object({ + name: z.string(), + command: z.string(), + args: z.array(z.string()), + env: z.array(zEnvVariable), + _meta: z.union([ + z.record(z.unknown()), z.null() ]).optional() }); -/** - * List providers with setup metadata and the current model inventory snapshot. - */ -export const zListProvidersRequest_unstable = z.object({ - providerIds: z.array(z.string()).optional().default([]) -}); - -/** - * HTTP transport configuration for MCP. - */ -export const zMcpServerHttp = z.object({ - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional(), - headers: z.array(zHttpHeader), - name: z.string(), - type: z.literal('http'), - url: z.string() -}); - -/** - * SSE transport configuration for MCP. - */ -export const zMcpServerSse = z.object({ - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional(), - headers: z.array(zHttpHeader), - name: z.string(), - type: z.literal('sse'), - url: z.string() -}); - -/** - * Stdio transport configuration for MCP. - */ -export const zMcpServerStdio = z.object({ - _meta: z.union([ - z.record(z.unknown()), - z.null() - ]).optional(), - args: z.array(z.string()), - command: z.string(), - env: z.array(zEnvVariable), - name: z.string() -}); - /** * Configuration for connecting to an MCP (Model Context Protocol) server. * @@ -500,10 +199,7 @@ export const zMcpServer = z.union([ export const zGooseExtension = z.union([ z.object({ - bundled: z.union([ - z.boolean(), - z.null() - ]).optional(), + name: z.string(), description: z.union([ z.string(), z.null() @@ -512,18 +208,18 @@ export const zGooseExtension = z.union([ z.string(), z.null() ]).optional(), - name: z.string(), timeout: z.union([ z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), z.null() ]).optional(), - type: z.literal('builtin') - }), - z.object({ bundled: z.union([ z.boolean(), z.null() ]).optional(), + type: z.literal('builtin') + }), + z.object({ + name: z.string(), description: z.union([ z.string(), z.null() @@ -532,21 +228,16 @@ export const zGooseExtension = z.union([ z.string(), z.null() ]).optional(), - name: z.string(), - type: z.literal('platform') - }), - z.object({ bundled: z.union([ z.boolean(), z.null() ]).optional(), - description: z.union([ - z.string(), - z.null() - ]).optional(), - envKeys: z.array(z.string()).optional(), + type: z.literal('platform') + }), + z.object({ server: zMcpServer, - socket: z.union([ + envKeys: z.array(z.string()).optional(), + description: z.union([ z.string(), z.null() ]).optional(), @@ -554,60 +245,25 @@ export const zGooseExtension = z.union([ z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), z.null() ]).optional(), - type: z.literal('mcp') - }), - z.object({ - code: z.string(), - dependencies: z.array(z.string()).optional(), - description: z.union([ + socket: z.union([ z.string(), z.null() ]).optional(), - name: z.string(), - timeout: z.union([ - z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), - z.null() - ]).optional(), - type: z.literal('inline_python') - }), - z.object({ bundled: z.union([ z.boolean(), z.null() ]).optional(), - description: z.union([ - z.string(), - z.null() - ]).optional(), - instructions: z.union([ - z.string(), - z.null() - ]).optional(), - name: z.string(), - tools: z.array(z.unknown()).optional(), - type: z.literal('frontend') + type: z.literal('mcp') }) ]); -/** - * Persist a new extension to the user's global goose config. - */ -export const zAddConfigExtensionRequest_unstable = z.object({ - enabled: z.boolean().optional().default(false), - extension: zGooseExtension -}); - -export const zGetAvailableExtensionsResponse_unstable = z.object({ - extensions: z.array(zGooseExtension) -}); - export const zGooseExtensionEntry = z.object({ + extension: zGooseExtension, + enabled: z.boolean(), configKey: z.union([ z.string(), z.null() - ]).optional(), - enabled: z.boolean(), - extension: zGooseExtension + ]).optional() }); /** @@ -619,92 +275,140 @@ export const zGetConfigExtensionsResponse_unstable = z.object({ }); /** - * Import selected onboarding candidates. + * List Goose-owned extension definitions available to configure or enable. */ -export const zOnboardingImportApplyRequest_unstable = z.object({ - candidateIds: z.array(z.string()).optional().default([]), - enableImportedExtensions: z.boolean().optional().default(false) -}); +export const zGetAvailableExtensionsRequest_unstable = z.record(z.unknown()); -export const zOnboardingImportCounts = z.object({ - extensions: z.number().int().gte(0), - preferences: z.number().int().gte(0), - projects: z.number().int().gte(0), - providers: z.number().int().gte(0), - sessions: z.number().int().gte(0), - skills: z.number().int().gte(0) +export const zGetAvailableExtensionsResponse_unstable = z.object({ + extensions: z.array(zGooseExtension) }); -export const zOnboardingImportApplyResponse_unstable = z.object({ - imported: zOnboardingImportCounts, - providerDefaults: z.union([ - zDefaultsReadResponse_unstable, - z.null() - ]).optional(), - skipped: zOnboardingImportCounts, - warnings: z.array(z.string()).optional().default([]) +/** + * Persist a new extension to the user's global goose config. + */ +export const zAddConfigExtensionRequest_unstable = z.object({ + extension: zGooseExtension, + enabled: z.boolean().optional().default(false) }); /** - * Sources that onboarding knows how to discover and import. + * Remove a persisted extension from the user's global goose config. */ -export const zOnboardingImportSourceKind = z.enum(['goose_config', 'claude_desktop']); - -export const zOnboardingImportCandidate = z.object({ - counts: zOnboardingImportCounts, - displayName: z.string(), - id: z.string(), - path: z.string(), - sourceKind: zOnboardingImportSourceKind, - warnings: z.array(z.string()).optional().default([]) +export const zRemoveConfigExtensionRequest_unstable = z.object({ + configKey: z.string() }); /** - * Scan for existing Goose and compatible app data that onboarding can import. + * Set the `enabled` flag for a persisted extension in the user's global goose config. */ -export const zOnboardingImportScanRequest_unstable = z.object({ - sources: z.array(zOnboardingImportSourceKind).optional().default([]) +export const zSetConfigExtensionEnabledRequest_unstable = z.object({ + configKey: z.string(), + enabled: z.boolean() }); -export const zOnboardingImportScanResponse_unstable = z.object({ - candidates: z.array(zOnboardingImportCandidate) +export const zGetSessionExtensionsRequest_unstable = z.object({ + sessionId: z.string() }); -export const zPreferenceKey = z.enum([ - 'autoCompactThreshold', - 'voiceAutoSubmitPhrases', - 'voiceDictationProvider', - 'voiceDictationPreferredMic' -]); +export const zGetSessionExtensionsResponse_unstable = z.object({ + extensions: z.array(z.unknown()) +}); -export const zPreferenceValue = z.object({ - key: zPreferenceKey, - value: z.unknown().optional().default(null) +/** + * List providers with setup metadata and the current model inventory snapshot. + */ +export const zListProvidersRequest_unstable = z.object({ + providerIds: z.array(z.string()).optional().default([]) +}); + +export const zProviderSetupCategoryDto = z.enum(['agent', 'model']); + +export const zProviderConfigKey = z.object({ + name: z.string(), + required: z.boolean(), + secret: z.boolean(), + default: z.union([ + z.string(), + z.null() + ]).optional().default(null), + oauthFlow: z.boolean().optional().default(false), + deviceCodeFlow: z.boolean().optional().default(false), + primary: z.boolean().optional().default(false) }); /** - * Read allowlisted user preferences. Empty `keys` means all supported preferences. + * A single model in provider inventory. */ -export const zPreferencesReadRequest_unstable = z.object({ - keys: z.array(zPreferenceKey).optional().default([]) +export const zProviderInventoryModelDto = z.object({ + id: z.string(), + name: z.string(), + family: z.union([ + z.string(), + z.null() + ]).optional(), + contextLimit: z.union([ + z.number().int().gte(0), + z.null() + ]).optional(), + reasoning: z.union([ + z.boolean(), + z.null() + ]).optional(), + recommended: z.boolean().optional().default(false) }); -export const zPreferencesReadResponse_unstable = z.object({ - values: z.array(zPreferenceValue) +/** + * Provider inventory entry. + */ +export const zProviderInventoryEntryDto = z.object({ + providerId: z.string(), + providerName: z.string(), + description: z.string(), + defaultModel: z.string(), + configured: z.boolean(), + providerType: z.string(), + category: zProviderSetupCategoryDto, + configKeys: z.array(zProviderConfigKey), + setupSteps: z.array(z.string()), + supportsRefresh: z.boolean(), + refreshing: z.boolean(), + models: z.array(zProviderInventoryModelDto), + lastUpdatedAt: z.union([ + z.string(), + z.null() + ]).optional(), + lastRefreshAttemptAt: z.union([ + z.string(), + z.null() + ]).optional(), + lastRefreshError: z.union([ + z.string(), + z.null() + ]).optional(), + stale: z.boolean(), + modelSelectionHint: z.union([ + z.string(), + z.null() + ]).optional() }); /** - * Remove allowlisted user preferences. + * Provider list response. */ -export const zPreferencesRemoveRequest_unstable = z.object({ - keys: z.array(zPreferenceKey).optional().default([]) +export const zListProvidersResponse_unstable = z.object({ + entries: z.array(zProviderInventoryEntryDto) }); /** - * Save allowlisted user preferences. + * List the raw model identifiers returned by a provider's live supported-models API. */ -export const zPreferencesSaveRequest_unstable = z.object({ - values: z.array(zPreferenceValue).optional().default([]) +export const zProviderSupportedModelsListRequest_unstable = z.object({ + providerId: z.string() +}); + +export const zProviderSupportedModelsListResponse_unstable = z.object({ + providerId: z.string(), + models: z.array(z.string()) }); /** @@ -717,6 +421,85 @@ export const zProviderCatalogListRequest_unstable = z.object({ ]).optional() }); +export const zProviderTemplateCatalogEntryDto = z.object({ + providerId: z.string(), + name: z.string(), + format: z.string(), + apiUrl: z.string(), + modelCount: z.number().int().gte(0), + docUrl: z.string(), + envVar: z.string() +}); + +export const zProviderCatalogListResponse_unstable = z.object({ + providers: z.array(zProviderTemplateCatalogEntryDto) +}); + +/** + * List provider setup catalog entries + */ +export const zProviderSetupCatalogListRequest_unstable = z.record(z.unknown()); + +export const zProviderSetupMethodDto = z.enum([ + 'none', + 'single_api_key', + 'config_fields', + 'host_with_oauth_fallback', + 'oauth_browser', + 'oauth_device_code', + 'cloud_credentials', + 'local', + 'cli_auth' +]); + +export const zProviderSetupFieldDto = z.object({ + key: z.string(), + label: z.string(), + secret: z.boolean(), + required: z.boolean(), + placeholder: z.union([ + z.string(), + z.null() + ]).optional(), + defaultValue: z.union([ + z.string(), + z.null() + ]).optional() +}); + +export const zProviderSetupGroupDto = z.enum(['default', 'additional']); + +export const zProviderSetupCatalogEntryDto = z.object({ + providerId: z.string(), + name: z.string(), + category: zProviderSetupCategoryDto, + description: z.string(), + setupMethod: zProviderSetupMethodDto, + nativeConnectQuery: z.union([ + z.string(), + z.null() + ]).optional(), + fields: z.array(zProviderSetupFieldDto).optional().default([]), + binaryName: z.union([ + z.string(), + z.null() + ]).optional(), + docUrl: z.union([ + z.string(), + z.null() + ]).optional(), + group: zProviderSetupGroupDto, + showOnlyWhenInstalled: z.boolean(), + aliases: z.array(z.string()).optional().default([]), + supportsInstall: z.boolean(), + supportsAuth: z.boolean(), + supportsAuthStatus: z.boolean() +}); + +export const zProviderSetupCatalogListResponse_unstable = z.object({ + providers: z.array(zProviderSetupCatalogEntryDto) +}); + /** * Return the editable template for one catalog provider. */ @@ -724,77 +507,218 @@ export const zProviderCatalogTemplateRequest_unstable = z.object({ providerId: z.string() }); +export const zProviderTemplateCapabilitiesDto = z.object({ + toolCall: z.boolean(), + reasoning: z.boolean(), + attachment: z.boolean(), + temperature: z.boolean() +}); + +export const zProviderTemplateModelDto = z.object({ + id: z.string(), + name: z.string(), + contextLimit: z.number().int().gte(0), + capabilities: zProviderTemplateCapabilitiesDto, + deprecated: z.boolean() +}); + +export const zProviderTemplateDto = z.object({ + providerId: z.string(), + name: z.string(), + format: z.string(), + apiUrl: z.string(), + models: z.array(zProviderTemplateModelDto), + supportsStreaming: z.boolean(), + envVar: z.string(), + docUrl: z.string() +}); + +export const zProviderCatalogTemplateResponse_unstable = z.object({ + template: zProviderTemplateDto +}); + /** - * Run a provider-owned native authentication flow and start an inventory refresh when supported. + * Create a custom provider backed by Goose's declarative provider store. */ -export const zProviderConfigAuthenticateRequest_unstable = z.object({ - providerId: z.string() +export const zCustomProviderCreateRequest_unstable = z.object({ + engine: z.string(), + displayName: z.string(), + apiUrl: z.string(), + apiKey: z.union([ + z.string(), + z.null() + ]).optional(), + models: z.array(z.string()).optional().default([]), + supportsStreaming: z.union([ + z.boolean(), + z.null() + ]).optional(), + headers: z.record(z.string()).optional().default({}), + requiresAuth: z.boolean(), + catalogProviderId: z.union([ + z.string(), + z.null() + ]).optional(), + basePath: z.union([ + z.string(), + z.null() + ]).optional(), + preservesThinking: z.union([ + z.boolean(), + z.null() + ]).optional() +}); + +export const zProviderConfigStatusDto = z.object({ + providerId: z.string(), + isConfigured: z.boolean() +}); + +export const zRefreshProviderInventorySkipReasonDto = z.enum([ + 'unknown_provider', + 'not_configured', + 'does_not_support_refresh', + 'already_refreshing' +]); + +export const zRefreshProviderInventorySkipDto = z.object({ + providerId: z.string(), + reason: zRefreshProviderInventorySkipReasonDto }); /** - * Delete provider configuration fields and start an inventory refresh when supported. + * Refresh acknowledgement. */ -export const zProviderConfigDeleteRequest_unstable = z.object({ +export const zRefreshProviderInventoryResponse_unstable = z.object({ + started: z.array(z.string()), + skipped: z.array(zRefreshProviderInventorySkipDto).optional().default([]) +}); + +export const zCustomProviderCreateResponse_unstable = z.object({ + providerId: z.string(), + status: zProviderConfigStatusDto, + refresh: zRefreshProviderInventoryResponse_unstable +}); + +/** + * Read a declarative provider config. Custom configs are editable; bundled configs are read-only. + */ +export const zCustomProviderReadRequest_unstable = z.object({ providerId: z.string() }); -export const zProviderConfigFieldUpdate = z.object({ - key: z.string(), - value: z.string() +export const zCustomProviderConfigDto = z.object({ + providerId: z.string(), + engine: z.string(), + displayName: z.string(), + apiUrl: z.string(), + models: z.array(z.string()).optional().default([]), + supportsStreaming: z.union([ + z.boolean(), + z.null() + ]).optional(), + headers: z.record(z.string()).optional().default({}), + requiresAuth: z.boolean(), + catalogProviderId: z.union([ + z.string(), + z.null() + ]).optional(), + basePath: z.union([ + z.string(), + z.null() + ]).optional(), + apiKeyEnv: z.union([ + z.string(), + z.null() + ]).optional(), + apiKeySet: z.boolean(), + preservesThinking: z.boolean() }); -export const zProviderConfigFieldValueDto = z.object({ - isSecret: z.boolean(), - isSet: z.boolean(), - key: z.string(), - required: z.boolean(), - value: z.union([ +export const zCustomProviderReadResponse_unstable = z.object({ + provider: zCustomProviderConfigDto, + editable: z.boolean(), + status: zProviderConfigStatusDto +}); + +/** + * Update a custom provider backed by Goose's declarative provider store. + */ +export const zCustomProviderUpdateRequest_unstable = z.object({ + providerId: z.string(), + engine: z.string(), + displayName: z.string(), + apiUrl: z.string(), + apiKey: z.union([ z.string(), z.null() - ]).optional().default(null) + ]).optional(), + models: z.array(z.string()).optional().default([]), + supportsStreaming: z.union([ + z.boolean(), + z.null() + ]).optional(), + headers: z.record(z.string()).optional().default({}), + requiresAuth: z.boolean(), + catalogProviderId: z.union([ + z.string(), + z.null() + ]).optional(), + basePath: z.union([ + z.string(), + z.null() + ]).optional(), + preservesThinking: z.union([ + z.boolean(), + z.null() + ]).optional() }); -export const zProviderConfigKey = z.object({ - default: z.union([ - z.string(), - z.null() - ]).optional().default(null), - deviceCodeFlow: z.boolean().optional().default(false), - name: z.string(), - oauthFlow: z.boolean().optional().default(false), - primary: z.boolean().optional().default(false), - required: z.boolean(), - secret: z.boolean() +export const zCustomProviderUpdateResponse_unstable = z.object({ + providerId: z.string(), + status: zProviderConfigStatusDto, + refresh: zRefreshProviderInventoryResponse_unstable }); /** - * Read saved configuration field values for one provider. + * Delete a custom provider from Goose's declarative provider store. */ -export const zProviderConfigReadRequest_unstable = z.object({ +export const zCustomProviderDeleteRequest_unstable = z.object({ providerId: z.string() }); -export const zProviderConfigReadResponse_unstable = z.object({ - fields: z.array(zProviderConfigFieldValueDto) +export const zCustomProviderDeleteResponse_unstable = z.object({ + providerId: z.string(), + refresh: zRefreshProviderInventoryResponse_unstable }); /** - * Save provider configuration fields and start an inventory refresh when supported. + * Trigger a background refresh of provider inventories. */ -export const zProviderConfigSaveRequest_unstable = z.object({ - fields: z.array(zProviderConfigFieldUpdate), - providerId: z.string() +export const zRefreshProviderInventoryRequest_unstable = z.object({ + providerIds: z.array(z.string()).optional().default([]) }); -export const zProviderConfigStatusDto = z.object({ - isConfigured: z.boolean(), +/** + * Read saved configuration field values for one provider. + */ +export const zProviderConfigReadRequest_unstable = z.object({ providerId: z.string() }); -export const zCustomProviderReadResponse_unstable = z.object({ - editable: z.boolean(), - provider: zCustomProviderConfigDto, - status: zProviderConfigStatusDto +export const zProviderConfigFieldValueDto = z.object({ + key: z.string(), + value: z.union([ + z.string(), + z.null() + ]).optional().default(null), + isSet: z.boolean(), + isSecret: z.boolean(), + required: z.boolean() +}); + +export const zProviderConfigReadResponse_unstable = z.object({ + fields: z.array(zProviderConfigFieldValueDto) }); /** @@ -808,270 +732,200 @@ export const zProviderConfigStatusResponse_unstable = z.object({ statuses: z.array(zProviderConfigStatusDto) }); -/** - * A single model in provider inventory. - */ -export const zProviderInventoryModelDto = z.object({ - contextLimit: z.union([ - z.number().int().gte(0), - z.null() - ]).optional(), - family: z.union([ - z.string(), - z.null() - ]).optional(), - id: z.string(), - name: z.string(), - reasoning: z.union([ - z.boolean(), - z.null() - ]).optional(), - recommended: z.boolean().optional().default(false) +export const zProviderConfigFieldUpdate = z.object({ + key: z.string(), + value: z.string() }); /** - * List provider setup catalog entries + * Save provider configuration fields and start an inventory refresh when supported. */ -export const zProviderSetupCatalogListRequest_unstable = z.record(z.unknown()); +export const zProviderConfigSaveRequest_unstable = z.object({ + providerId: z.string(), + fields: z.array(zProviderConfigFieldUpdate) +}); -export const zProviderSetupCategoryDto = z.enum(['agent', 'model']); +export const zProviderConfigChangeResponse_unstable = z.object({ + status: zProviderConfigStatusDto, + refresh: zRefreshProviderInventoryResponse_unstable +}); /** - * Provider inventory entry. + * Delete provider configuration fields and start an inventory refresh when supported. */ -export const zProviderInventoryEntryDto = z.object({ - category: zProviderSetupCategoryDto, - configKeys: z.array(zProviderConfigKey), - configured: z.boolean(), - defaultModel: z.string(), - description: z.string(), - lastRefreshAttemptAt: z.union([ - z.string(), - z.null() - ]).optional(), - lastRefreshError: z.union([ - z.string(), - z.null() - ]).optional(), - lastUpdatedAt: z.union([ - z.string(), - z.null() - ]).optional(), - modelSelectionHint: z.union([ - z.string(), - z.null() - ]).optional(), - models: z.array(zProviderInventoryModelDto), - providerId: z.string(), - providerName: z.string(), - providerType: z.string(), - refreshing: z.boolean(), - setupSteps: z.array(z.string()), - stale: z.boolean(), - supportsRefresh: z.boolean() +export const zProviderConfigDeleteRequest_unstable = z.object({ + providerId: z.string() }); /** - * Provider list response. + * Run a provider-owned native authentication flow and start an inventory refresh when supported. */ -export const zListProvidersResponse_unstable = z.object({ - entries: z.array(zProviderInventoryEntryDto) -}); - -export const zProviderSetupFieldDto = z.object({ - defaultValue: z.union([ - z.string(), - z.null() - ]).optional(), - key: z.string(), - label: z.string(), - placeholder: z.union([ - z.string(), - z.null() - ]).optional(), - required: z.boolean(), - secret: z.boolean() +export const zProviderConfigAuthenticateRequest_unstable = z.object({ + providerId: z.string() }); -export const zProviderSetupGroupDto = z.enum(['default', 'additional']); - -export const zProviderSetupMethodDto = z.enum([ - 'none', - 'single_api_key', - 'config_fields', - 'host_with_oauth_fallback', - 'oauth_browser', - 'oauth_device_code', - 'cloud_credentials', - 'local', - 'cli_auth' +export const zPreferenceKey = z.enum([ + 'autoCompactThreshold', + 'voiceAutoSubmitPhrases', + 'voiceDictationProvider', + 'voiceDictationPreferredMic' ]); -export const zProviderSetupCatalogEntryDto = z.object({ - aliases: z.array(z.string()).optional().default([]), - binaryName: z.union([ - z.string(), - z.null() - ]).optional(), - category: zProviderSetupCategoryDto, - description: z.string(), - docUrl: z.union([ - z.string(), - z.null() - ]).optional(), - fields: z.array(zProviderSetupFieldDto).optional().default([]), - group: zProviderSetupGroupDto, - name: z.string(), - nativeConnectQuery: z.union([ - z.string(), - z.null() - ]).optional(), - providerId: z.string(), - setupMethod: zProviderSetupMethodDto, - showOnlyWhenInstalled: z.boolean(), - supportsAuth: z.boolean(), - supportsAuthStatus: z.boolean(), - supportsInstall: z.boolean() -}); - -export const zProviderSetupCatalogListResponse_unstable = z.object({ - providers: z.array(zProviderSetupCatalogEntryDto) -}); - /** - * List the raw model identifiers returned by a provider's live supported-models API. + * Read allowlisted user preferences. Empty `keys` means all supported preferences. */ -export const zProviderSupportedModelsListRequest_unstable = z.object({ - providerId: z.string() -}); - -export const zProviderSupportedModelsListResponse_unstable = z.object({ - models: z.array(z.string()), - providerId: z.string() +export const zPreferencesReadRequest_unstable = z.object({ + keys: z.array(zPreferenceKey).optional().default([]) }); -export const zProviderTemplateCapabilitiesDto = z.object({ - attachment: z.boolean(), - reasoning: z.boolean(), - temperature: z.boolean(), - toolCall: z.boolean() +export const zPreferenceValue = z.object({ + key: zPreferenceKey, + value: z.unknown().optional().default(null) }); -export const zProviderTemplateCatalogEntryDto = z.object({ - apiUrl: z.string(), - docUrl: z.string(), - envVar: z.string(), - format: z.string(), - modelCount: z.number().int().gte(0), - name: z.string(), - providerId: z.string() +export const zPreferencesReadResponse_unstable = z.object({ + values: z.array(zPreferenceValue) }); -export const zProviderCatalogListResponse_unstable = z.object({ - providers: z.array(zProviderTemplateCatalogEntryDto) +/** + * Save allowlisted user preferences. + */ +export const zPreferencesSaveRequest_unstable = z.object({ + values: z.array(zPreferenceValue).optional().default([]) }); -export const zProviderTemplateModelDto = z.object({ - capabilities: zProviderTemplateCapabilitiesDto, - contextLimit: z.number().int().gte(0), - deprecated: z.boolean(), - id: z.string(), - name: z.string() +/** + * Remove allowlisted user preferences. + */ +export const zPreferencesRemoveRequest_unstable = z.object({ + keys: z.array(zPreferenceKey).optional().default([]) }); -export const zProviderTemplateDto = z.object({ - apiUrl: z.string(), - docUrl: z.string(), - envVar: z.string(), - format: z.string(), - models: z.array(zProviderTemplateModelDto), - name: z.string(), - providerId: z.string(), - supportsStreaming: z.boolean() -}); +/** + * Read Goose default provider and model configuration. + */ +export const zDefaultsReadRequest_unstable = z.record(z.unknown()); -export const zProviderCatalogTemplateResponse_unstable = z.object({ - template: zProviderTemplateDto +export const zDefaultsReadResponse_unstable = z.object({ + providerId: z.union([ + z.string(), + z.null() + ]).optional(), + modelId: z.union([ + z.string(), + z.null() + ]).optional() }); /** - * Read a resource from an extension. + * Save Goose default provider and model configuration. */ -export const zReadResourceRequest_unstable = z.object({ - extensionName: z.string(), - sessionId: z.string(), - uri: z.string() +export const zDefaultsSaveRequest_unstable = z.object({ + providerId: z.string(), + modelId: z.union([ + z.string(), + z.null() + ]).optional() }); /** - * Resource read response. + * Sources that onboarding knows how to discover and import. */ -export const zReadResourceResponse_unstable = z.object({ - result: z.unknown().optional().default(null) -}); +export const zOnboardingImportSourceKind = z.enum(['goose_config', 'claude_desktop']); /** - * Trigger a background refresh of provider inventories. + * Scan for existing Goose and compatible app data that onboarding can import. */ -export const zRefreshProviderInventoryRequest_unstable = z.object({ - providerIds: z.array(z.string()).optional().default([]) +export const zOnboardingImportScanRequest_unstable = z.object({ + sources: z.array(zOnboardingImportSourceKind).optional().default([]) }); -export const zRefreshProviderInventorySkipReasonDto = z.enum([ - 'unknown_provider', - 'not_configured', - 'does_not_support_refresh', - 'already_refreshing' -]); +export const zOnboardingImportCounts = z.object({ + providers: z.number().int().gte(0), + extensions: z.number().int().gte(0), + sessions: z.number().int().gte(0), + skills: z.number().int().gte(0), + projects: z.number().int().gte(0), + preferences: z.number().int().gte(0) +}); -export const zRefreshProviderInventorySkipDto = z.object({ - providerId: z.string(), - reason: zRefreshProviderInventorySkipReasonDto +export const zOnboardingImportCandidate = z.object({ + id: z.string(), + sourceKind: zOnboardingImportSourceKind, + displayName: z.string(), + path: z.string(), + counts: zOnboardingImportCounts, + warnings: z.array(z.string()).optional().default([]) +}); + +export const zOnboardingImportScanResponse_unstable = z.object({ + candidates: z.array(zOnboardingImportCandidate) }); /** - * Refresh acknowledgement. + * Import selected onboarding candidates. */ -export const zRefreshProviderInventoryResponse_unstable = z.object({ - skipped: z.array(zRefreshProviderInventorySkipDto).optional().default([]), - started: z.array(z.string()) +export const zOnboardingImportApplyRequest_unstable = z.object({ + candidateIds: z.array(z.string()).optional().default([]), + enableImportedExtensions: z.boolean().optional().default(false) }); -export const zCustomProviderCreateResponse_unstable = z.object({ - providerId: z.string(), - refresh: zRefreshProviderInventoryResponse_unstable, - status: zProviderConfigStatusDto +export const zOnboardingImportApplyResponse_unstable = z.object({ + imported: zOnboardingImportCounts, + skipped: zOnboardingImportCounts, + warnings: z.array(z.string()).optional().default([]), + providerDefaults: z.union([ + zDefaultsReadResponse_unstable, + z.null() + ]).optional() }); -export const zCustomProviderDeleteResponse_unstable = z.object({ - providerId: z.string(), - refresh: zRefreshProviderInventoryResponse_unstable +/** + * Export a session as a JSON string. + */ +export const zExportSessionRequest_unstable = z.object({ + sessionId: z.string() }); -export const zCustomProviderUpdateResponse_unstable = z.object({ - providerId: z.string(), - refresh: zRefreshProviderInventoryResponse_unstable, - status: zProviderConfigStatusDto +/** + * Export session response — raw JSON of the goose session with `conversation`. + */ +export const zExportSessionResponse_unstable = z.object({ + data: z.string() }); -export const zProviderConfigChangeResponse_unstable = z.object({ - refresh: zRefreshProviderInventoryResponse_unstable, - status: zProviderConfigStatusDto +/** + * Import a session from a JSON string. + */ +export const zImportSessionRequest_unstable = z.object({ + data: z.string() }); /** - * Remove a persisted extension from the user's global goose config. + * Import session response — metadata about the newly created session. */ -export const zRemoveConfigExtensionRequest_unstable = z.object({ - configKey: z.string() +export const zImportSessionResponse_unstable = z.object({ + sessionId: z.string(), + title: z.union([ + z.string(), + z.null() + ]).optional(), + updatedAt: z.union([ + z.string(), + z.null() + ]).optional(), + messageCount: z.number().int().gte(0) }); /** - * Remove an extension from an active session. + * Update the project association for a session. */ -export const zRemoveExtensionRequest_unstable = z.object({ - name: z.string(), - sessionId: z.string() +export const zUpdateSessionProjectRequest_unstable = z.object({ + sessionId: z.string(), + projectId: z.union([ + z.string(), + z.null() + ]).optional() }); /** @@ -1083,37 +937,30 @@ export const zRenameSessionRequest_unstable = z.object({ }); /** - * How a session system prompt update should be applied. + * Archive a session (soft delete). */ -export const zSessionSystemPromptMode = z.union([ - z.literal('set'), - z.literal('append') -]); +export const zArchiveSessionRequest_unstable = z.object({ + sessionId: z.string() +}); /** - * Set the `enabled` flag for a persisted extension in the user's global goose config. + * Unarchive a previously archived session. */ -export const zSetConfigExtensionEnabledRequest_unstable = z.object({ - configKey: z.string(), - enabled: z.boolean() +export const zUnarchiveSessionRequest_unstable = z.object({ + sessionId: z.string() }); /** - * Set, append, or clear system prompt text for a session. - * - * `mode: "set"` replaces Goose's base system prompt. `mode: "append"` adds an - * instruction under "Additional Instructions". Reusing a key replaces the - * previous value for that mode/key; sending empty text clears it. + * The type of source entity. */ -export const zSetSessionSystemPromptRequest_unstable = z.object({ - key: z.union([ - z.string(), - z.null() - ]).optional(), - mode: zSessionSystemPromptMode.optional().default('append'), - sessionId: z.string(), - text: z.string() -}); +export const zSourceType = z.enum([ + 'skill', + 'builtinSkill', + 'recipe', + 'subrecipe', + 'agent', + 'project' +]); /** * Target scope for creating or importing sources. @@ -1132,6 +979,103 @@ export const zSourceScope = z.union([ }) ]); +/** + * Create a new source in an explicit target scope (global or project-scoped). + */ +export const zCreateSourceRequest_unstable = z.object({ + type: zSourceType, + name: z.string(), + description: z.string(), + content: z.string(), + target: zSourceScope, + properties: z.record(z.unknown()).optional() +}); + +/** + * A source discovered by Goose. Filesystem sources use an on-disk path; + * built-in sources use a stable synthetic path. Sources may be either + * `global` (shared across all projects) or project-specific. + */ +export const zSourceEntry = z.object({ + type: zSourceType, + name: z.string(), + description: z.string(), + content: z.string(), + path: z.string(), + global: z.boolean(), + writable: z.boolean().optional().default(false), + supportingFiles: z.array(z.string()).optional(), + properties: z.record(z.unknown()).optional() +}); + +export const zCreateSourceResponse_unstable = z.object({ + source: zSourceEntry +}); + +/** + * List discovered sources. + * + * If `type` is omitted or `skill`, this lists filesystem/plugin skills only. + * Both global and project-scoped skills are included when `project_dir` is + * set. If `type` is `builtinSkill`, this lists shipped read-only built-in + * skills. + */ +export const zListSourcesRequest_unstable = z.object({ + type: z.union([ + zSourceType, + z.null() + ]).optional(), + projectDir: z.union([ + z.string(), + z.null() + ]).optional(), + includeProjectSources: z.boolean().optional().default(false) +}); + +export const zListSourcesResponse_unstable = z.object({ + sources: z.array(zSourceEntry) +}); + +/** + * Update an existing source's name, description, and content by absolute path. + */ +export const zUpdateSourceRequest_unstable = z.object({ + type: zSourceType, + path: z.string(), + name: z.string(), + description: z.string(), + content: z.string(), + properties: z.union([ + z.record(z.unknown()), + z.null() + ]).optional() +}); + +export const zUpdateSourceResponse_unstable = z.object({ + source: zSourceEntry +}); + +/** + * Delete a source and its on-disk directory by absolute path. + */ +export const zDeleteSourceRequest_unstable = z.object({ + type: zSourceType, + path: z.string() +}); + +/** + * Export a source at an absolute path as a portable JSON payload. + */ +export const zExportSourceRequest_unstable = z.object({ + type: zSourceType, + path: z.string() +}); + +export const zExportSourceResponse_unstable = z.object({ + json: z.string(), + filename: z.string() +}); + /** * Import a source from a JSON export payload produced by `_goose/unstable/sources/export`. * The imported source is written into the explicit target scope; on name @@ -1142,192 +1086,163 @@ export const zImportSourcesRequest_unstable = z.object({ target: zSourceScope }); -/** - * The type of source entity. - */ -export const zSourceType = z.enum([ - 'skill', - 'builtinSkill', - 'recipe', - 'subrecipe', - 'agent', - 'project' -]); +export const zImportSourcesResponse_unstable = z.object({ + sources: z.array(zSourceEntry) +}); /** - * Create a new source in an explicit target scope (global or project-scoped). + * Transcribe audio via a dictation provider. */ -export const zCreateSourceRequest_unstable = z.object({ - content: z.string(), - description: z.string(), - name: z.string(), - properties: z.record(z.unknown()).optional(), - target: zSourceScope, - type: zSourceType +export const zDictationTranscribeRequest_unstable = z.object({ + audio: z.string(), + mimeType: z.string(), + provider: z.string() }); /** - * Delete a source and its on-disk directory by absolute path. + * Transcription result. */ -export const zDeleteSourceRequest_unstable = z.object({ - path: z.string(), - type: zSourceType +export const zDictationTranscribeResponse_unstable = z.object({ + text: z.string() }); /** - * Export a source at an absolute path as a portable JSON payload. + * Get the configuration status of all dictation providers. */ -export const zExportSourceRequest_unstable = z.object({ - path: z.string(), - type: zSourceType +export const zDictationConfigRequest_unstable = z.record(z.unknown()); + +export const zDictationModelOption = z.object({ + id: z.string(), + label: z.string(), + description: z.string() }); /** - * List discovered sources. - * - * If `type` is omitted or `skill`, this lists filesystem/plugin skills only. - * Both global and project-scoped skills are included when `project_dir` is - * set. If `type` is `builtinSkill`, this lists shipped read-only built-in - * skills. + * Per-provider configuration status. */ -export const zListSourcesRequest_unstable = z.object({ - includeProjectSources: z.boolean().optional().default(false), - projectDir: z.union([ +export const zDictationProviderStatusEntry = z.object({ + configured: z.boolean(), + host: z.union([ z.string(), z.null() ]).optional(), - type: z.union([ - zSourceType, + description: z.string(), + usesProviderConfig: z.boolean(), + settingsPath: z.union([ + z.string(), z.null() - ]).optional() + ]).optional(), + configKey: z.union([ + z.string(), + z.null() + ]).optional(), + modelConfigKey: z.union([ + z.string(), + z.null() + ]).optional(), + defaultModel: z.union([ + z.string(), + z.null() + ]).optional(), + selectedModel: z.union([ + z.string(), + z.null() + ]).optional(), + availableModels: z.array(zDictationModelOption).optional().default([]) }); /** - * A source discovered by Goose. Filesystem sources use an on-disk path; - * built-in sources use a stable synthetic path. Sources may be either - * `global` (shared across all projects) or project-specific. + * Dictation config response — map of provider name to status. */ -export const zSourceEntry = z.object({ - content: z.string(), - description: z.string(), - global: z.boolean(), - name: z.string(), - path: z.string(), - properties: z.record(z.unknown()).optional(), - supportingFiles: z.array(z.string()).optional(), - type: zSourceType, - writable: z.boolean().optional().default(false) +export const zDictationConfigResponse_unstable = z.object({ + providers: z.record(zDictationProviderStatusEntry) }); -export const zCreateSourceResponse_unstable = z.object({ - source: zSourceEntry +/** + * Set a dictation provider secret value. + */ +export const zDictationSecretSaveRequest_unstable = z.object({ + provider: z.string(), + value: z.string() }); -export const zImportSourcesResponse_unstable = z.object({ - sources: z.array(zSourceEntry) +/** + * Remove a dictation provider secret value. + */ +export const zDictationSecretDeleteRequest_unstable = z.object({ + provider: z.string() }); -export const zListSourcesResponse_unstable = z.object({ - sources: z.array(zSourceEntry) +/** + * List available local Whisper models with their download status. + */ +export const zDictationModelsListRequest_unstable = z.record(z.unknown()); + +export const zDictationLocalModelStatus = z.object({ + id: z.string(), + label: z.string(), + description: z.string(), + sizeMb: z.number().int().gte(0), + downloaded: z.boolean(), + downloadInProgress: z.boolean() +}); + +export const zDictationModelsListResponse_unstable = z.object({ + models: z.array(zDictationLocalModelStatus) }); /** - * Unarchive a previously archived session. + * Kick off a background download of a local Whisper model. */ -export const zUnarchiveSessionRequest_unstable = z.object({ - sessionId: z.string() +export const zDictationModelDownloadRequest_unstable = z.object({ + modelId: z.string() }); /** - * Update the project association for a session. + * Poll the progress of an in-flight download. */ -export const zUpdateSessionProjectRequest_unstable = z.object({ - projectId: z.union([ +export const zDictationModelDownloadProgressRequest_unstable = z.object({ + modelId: z.string() +}); + +export const zDictationDownloadProgress = z.object({ + bytesDownloaded: z.number().int().gte(0), + totalBytes: z.number().int().gte(0), + progressPercent: z.number(), + status: z.string(), + error: z.union([ z.string(), z.null() - ]).optional(), - sessionId: z.string() + ]).optional() }); -/** - * Update an existing source's name, description, and content by absolute path. - */ -export const zUpdateSourceRequest_unstable = z.object({ - content: z.string(), - description: z.string(), - name: z.string(), - path: z.string(), - properties: z.union([ - z.record(z.unknown()), +export const zDictationModelDownloadProgressResponse_unstable = z.object({ + progress: z.union([ + zDictationDownloadProgress, z.null() - ]).optional(), - type: zSourceType + ]).optional() }); -export const zUpdateSourceResponse_unstable = z.object({ - source: zSourceEntry +/** + * Cancel an in-flight download. + */ +export const zDictationModelCancelRequest_unstable = z.object({ + modelId: z.string() }); -export const zExtResponse = z.union([ - z.object({ - id: z.string(), - result: z.union([ - z.union([ - zEmptyResponse, - zGetToolsResponse_unstable, - zGooseToolCallResponse_unstable, - zReadResourceResponse_unstable, - zGetConfigExtensionsResponse_unstable, - zGetAvailableExtensionsResponse_unstable, - zGetSessionExtensionsResponse_unstable, - zListProvidersResponse_unstable, - zProviderSupportedModelsListResponse_unstable, - zProviderCatalogListResponse_unstable, - zProviderSetupCatalogListResponse_unstable, - zProviderCatalogTemplateResponse_unstable, - zCustomProviderCreateResponse_unstable, - zCustomProviderReadResponse_unstable, - zCustomProviderUpdateResponse_unstable, - zCustomProviderDeleteResponse_unstable, - zRefreshProviderInventoryResponse_unstable, - zProviderConfigReadResponse_unstable, - zProviderConfigStatusResponse_unstable, - zProviderConfigChangeResponse_unstable, - zPreferencesReadResponse_unstable, - zDefaultsReadResponse_unstable, - zOnboardingImportScanResponse_unstable, - zOnboardingImportApplyResponse_unstable, - zExportSessionResponse_unstable, - zImportSessionResponse_unstable, - zCreateSourceResponse_unstable, - zListSourcesResponse_unstable, - zUpdateSourceResponse_unstable, - zExportSourceResponse_unstable, - zImportSourcesResponse_unstable, - zDictationTranscribeResponse_unstable, - zDictationConfigResponse_unstable, - zDictationModelsListResponse_unstable, - zDictationModelDownloadProgressResponse_unstable - ]), - z.unknown() - ]).optional() - }), - z.object({ - error: z.object({ - code: z.number().int(), - data: z.unknown().optional(), - message: z.string() - }), - id: z.string() - }) -]); +/** + * Delete a downloaded local Whisper model from disk. + */ +export const zDictationModelDeleteRequest_unstable = z.object({ + modelId: z.string() +}); /** - * Update the working directory for a session. + * Persist the user's model selection for a given provider. */ -export const zUpdateWorkingDirRequest_unstable = z.object({ - sessionId: z.string(), - workingDir: z.string() +export const zDictationModelSelectRequest_unstable = z.object({ + provider: z.string(), + modelId: z.string() }); export const zExtRequest = z.object({ @@ -1400,3 +1315,57 @@ export const zExtRequest = z.object({ ]) ]).optional() }); + +export const zExtResponse = z.union([ + z.object({ + id: z.string(), + result: z.union([ + z.union([ + zEmptyResponse, + zGetToolsResponse_unstable, + zGooseToolCallResponse_unstable, + zReadResourceResponse_unstable, + zGetConfigExtensionsResponse_unstable, + zGetAvailableExtensionsResponse_unstable, + zGetSessionExtensionsResponse_unstable, + zListProvidersResponse_unstable, + zProviderSupportedModelsListResponse_unstable, + zProviderCatalogListResponse_unstable, + zProviderSetupCatalogListResponse_unstable, + zProviderCatalogTemplateResponse_unstable, + zCustomProviderCreateResponse_unstable, + zCustomProviderReadResponse_unstable, + zCustomProviderUpdateResponse_unstable, + zCustomProviderDeleteResponse_unstable, + zRefreshProviderInventoryResponse_unstable, + zProviderConfigReadResponse_unstable, + zProviderConfigStatusResponse_unstable, + zProviderConfigChangeResponse_unstable, + zPreferencesReadResponse_unstable, + zDefaultsReadResponse_unstable, + zOnboardingImportScanResponse_unstable, + zOnboardingImportApplyResponse_unstable, + zExportSessionResponse_unstable, + zImportSessionResponse_unstable, + zCreateSourceResponse_unstable, + zListSourcesResponse_unstable, + zUpdateSourceResponse_unstable, + zExportSourceResponse_unstable, + zImportSourcesResponse_unstable, + zDictationTranscribeResponse_unstable, + zDictationConfigResponse_unstable, + zDictationModelsListResponse_unstable, + zDictationModelDownloadProgressResponse_unstable + ]), + z.unknown() + ]).optional() + }), + z.object({ + error: z.object({ + code: z.number().int(), + message: z.string(), + data: z.unknown().optional() + }), + id: z.string() + }) +]); From 6150a4cbefb47a4ffcaf1763308ab1762d6f9ff7 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Thu, 4 Jun 2026 08:30:34 +1000 Subject: [PATCH 13/16] handled nullable timeout --- crates/goose/acp-schema.json | 7 +-- crates/goose/src/bin/generate_acp_schema.rs | 51 ++++++++++++++++++++- ui/sdk/src/generated/zod.gen.ts | 4 +- 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/crates/goose/acp-schema.json b/crates/goose/acp-schema.json index 62898ac0d67b..082c31931bde 100644 --- a/crates/goose/acp-schema.json +++ b/crates/goose/acp-schema.json @@ -300,7 +300,6 @@ "integer", "null" ], - "format": "uint64", "minimum": 0 }, "bundled": { @@ -376,7 +375,6 @@ "integer", "null" ], - "format": "uint64", "minimum": 0 }, "socket": { @@ -922,9 +920,8 @@ "integer", "null" ], - "format": "uint", - "minimum": 0, - "description": "Context window size in tokens." + "description": "Context window size in tokens.", + "minimum": 0 }, "reasoning": { "type": [ diff --git a/crates/goose/src/bin/generate_acp_schema.rs b/crates/goose/src/bin/generate_acp_schema.rs index c7f785c96bf0..beb09db9569f 100644 --- a/crates/goose/src/bin/generate_acp_schema.rs +++ b/crates/goose/src/bin/generate_acp_schema.rs @@ -308,7 +308,15 @@ fn add_object_discriminant(defs: &mut Map, def_name: &str, tag: & fn strip_integer_formats(value: &mut Value) { match value { Value::Object(map) => { - let is_integer = map.get("type").and_then(|v| v.as_str()) == Some("integer"); + let is_integer = match map.get("type") { + Some(Value::String(schema_type)) => schema_type == "integer", + Some(Value::Array(schema_types)) => schema_types.iter().any(|schema_type| { + schema_type + .as_str() + .is_some_and(|schema_type| schema_type == "integer") + }), + _ => false, + }; if is_integer { map.remove("format"); } @@ -412,4 +420,45 @@ mod tests { .unwrap() .contains(&json!("type"))); } + + #[test] + fn strips_integer_formats_from_nullable_integer_schemas() { + let mut schema = json!({ + "type": "object", + "properties": { + "timeout": { + "type": ["integer", "null"], + "format": "uint64", + "minimum": 0 + }, + "count": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "name": { + "type": "string", + "format": "custom" + } + } + }); + + strip_integer_formats(&mut schema); + + assert_eq!( + schema["properties"]["timeout"].get("format"), + None, + "nullable integer formats should be stripped" + ); + assert_eq!( + schema["properties"]["count"].get("format"), + None, + "integer formats should be stripped" + ); + assert_eq!( + schema["properties"]["name"]["format"], + json!("custom"), + "non-integer formats should be preserved" + ); + } } diff --git a/ui/sdk/src/generated/zod.gen.ts b/ui/sdk/src/generated/zod.gen.ts index 57c5784e75e1..df18445a58a5 100644 --- a/ui/sdk/src/generated/zod.gen.ts +++ b/ui/sdk/src/generated/zod.gen.ts @@ -209,7 +209,7 @@ export const zGooseExtension = z.union([ z.null() ]).optional(), timeout: z.union([ - z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), + z.number().int().gte(0), z.null() ]).optional(), bundled: z.union([ @@ -242,7 +242,7 @@ export const zGooseExtension = z.union([ z.null() ]).optional(), timeout: z.union([ - z.coerce.bigint().gte(BigInt(0)).max(BigInt('18446744073709551615'), { message: 'Invalid value: Expected uint64 to be <= 18446744073709551615' }), + z.number().int().gte(0), z.null() ]).optional(), socket: z.union([ From 03bf4256273fc22e6aaacd0bdba4a38dc647b86d Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Thu, 4 Jun 2026 19:07:11 +1000 Subject: [PATCH 14/16] regenerate ts --- ui/sdk/src/generated/index.ts | 2 +- ui/sdk/src/generated/types.gen.ts | 209 +++++++++++++++++++++++++++--- 2 files changed, 195 insertions(+), 16 deletions(-) diff --git a/ui/sdk/src/generated/index.ts b/ui/sdk/src/generated/index.ts index 855e8b4dc3cc..ea3d436b478d 100644 --- a/ui/sdk/src/generated/index.ts +++ b/ui/sdk/src/generated/index.ts @@ -1,6 +1,6 @@ // This file is auto-generated by @hey-api/openapi-ts -export type { AddConfigExtensionRequest_unstable, AddExtensionRequest_unstable, ArchiveSessionRequest_unstable, CreateSourceRequest_unstable, CreateSourceResponse_unstable, CustomProviderConfigDto, CustomProviderCreateRequest_unstable, CustomProviderCreateResponse_unstable, CustomProviderDeleteRequest_unstable, CustomProviderDeleteResponse_unstable, CustomProviderReadRequest_unstable, CustomProviderReadResponse_unstable, CustomProviderUpdateRequest_unstable, CustomProviderUpdateResponse_unstable, DefaultsReadRequest_unstable, DefaultsReadResponse_unstable, DefaultsSaveRequest_unstable, DeleteSessionRequest, DeleteSourceRequest_unstable, DictationConfigRequest_unstable, DictationConfigResponse_unstable, DictationDownloadProgress, DictationLocalModelStatus, DictationModelCancelRequest_unstable, DictationModelDeleteRequest_unstable, DictationModelDownloadProgressRequest_unstable, DictationModelDownloadProgressResponse_unstable, DictationModelDownloadRequest_unstable, DictationModelOption, DictationModelSelectRequest_unstable, DictationModelsListRequest_unstable, DictationModelsListResponse_unstable, DictationProviderStatusEntry, DictationSecretDeleteRequest_unstable, DictationSecretSaveRequest_unstable, DictationTranscribeRequest_unstable, DictationTranscribeResponse_unstable, ElicitationRespondRequest_unstable, EmptyResponse, EnvVariable, ExportSessionRequest_unstable, ExportSessionResponse_unstable, ExportSourceRequest_unstable, ExportSourceResponse_unstable, ExtNotification, ExtRequest, ExtResponse, GetAvailableExtensionsRequest_unstable, GetAvailableExtensionsResponse_unstable, GetConfigExtensionsRequest_unstable, GetConfigExtensionsResponse_unstable, GetSessionExtensionsRequest_unstable, GetSessionExtensionsResponse_unstable, GetToolsRequest_unstable, GetToolsResponse_unstable, GooseExtension, GooseExtensionEntry, GooseSessionNotification_unstable, GooseSessionUpdate, GooseToolCallRequest_unstable, GooseToolCallResponse_unstable, HttpHeader, ImportSessionRequest_unstable, ImportSessionResponse_unstable, ImportSourcesRequest_unstable, ImportSourcesResponse_unstable, Interaction, InteractionState, InteractionUpdate, ListProvidersRequest_unstable, ListProvidersResponse_unstable, ListSourcesRequest_unstable, ListSourcesResponse_unstable, McpServer, McpServerHttp, McpServerSse, McpServerStdio, OnboardingImportApplyRequest_unstable, OnboardingImportApplyResponse_unstable, OnboardingImportCandidate, OnboardingImportCounts, OnboardingImportScanRequest_unstable, OnboardingImportScanResponse_unstable, OnboardingImportSourceKind, PreferenceKey, PreferencesReadRequest_unstable, PreferencesReadResponse_unstable, PreferencesRemoveRequest_unstable, PreferencesSaveRequest_unstable, PreferenceValue, ProviderCatalogListRequest_unstable, ProviderCatalogListResponse_unstable, ProviderCatalogTemplateRequest_unstable, ProviderCatalogTemplateResponse_unstable, ProviderConfigAuthenticateRequest_unstable, ProviderConfigChangeResponse_unstable, ProviderConfigDeleteRequest_unstable, ProviderConfigFieldUpdate, ProviderConfigFieldValueDto, ProviderConfigKey, ProviderConfigReadRequest_unstable, ProviderConfigReadResponse_unstable, ProviderConfigSaveRequest_unstable, ProviderConfigStatusDto, ProviderConfigStatusRequest_unstable, ProviderConfigStatusResponse_unstable, ProviderInventoryEntryDto, ProviderInventoryModelDto, ProviderSetupCatalogEntryDto, ProviderSetupCatalogListRequest_unstable, ProviderSetupCatalogListResponse_unstable, ProviderSetupCategoryDto, ProviderSetupFieldDto, ProviderSetupGroupDto, ProviderSetupMethodDto, ProviderSupportedModelsListRequest_unstable, ProviderSupportedModelsListResponse_unstable, ProviderTemplateCapabilitiesDto, ProviderTemplateCatalogEntryDto, ProviderTemplateDto, ProviderTemplateModelDto, ReadResourceRequest_unstable, ReadResourceResponse_unstable, RefreshProviderInventoryRequest_unstable, RefreshProviderInventoryResponse_unstable, RefreshProviderInventorySkipDto, RefreshProviderInventorySkipReasonDto, RemoveConfigExtensionRequest_unstable, RemoveExtensionRequest_unstable, RenameSessionRequest_unstable, SessionSystemPromptMode, SetConfigExtensionEnabledRequest_unstable, SessionUsageUpdate, SetSessionSystemPromptRequest_unstable, SourceEntry, SourceScope, SourceType, StatusMessage, StatusMessageUpdate, UnarchiveSessionRequest_unstable, UpdateSessionProjectRequest_unstable, UpdateSourceRequest_unstable, UpdateSourceResponse_unstable, UpdateWorkingDirRequest_unstable } from './types.gen.js'; +export type { AddConfigExtensionRequest_unstable, AddExtensionRequest_unstable, ArchiveSessionRequest_unstable, CreateSourceRequest_unstable, CreateSourceResponse_unstable, CustomProviderConfigDto, CustomProviderCreateRequest_unstable, CustomProviderCreateResponse_unstable, CustomProviderDeleteRequest_unstable, CustomProviderDeleteResponse_unstable, CustomProviderReadRequest_unstable, CustomProviderReadResponse_unstable, CustomProviderUpdateRequest_unstable, CustomProviderUpdateResponse_unstable, DefaultsReadRequest_unstable, DefaultsReadResponse_unstable, DefaultsSaveRequest_unstable, DeleteSessionRequest, DeleteSourceRequest_unstable, DictationConfigRequest_unstable, DictationConfigResponse_unstable, DictationDownloadProgress, DictationLocalModelStatus, DictationModelCancelRequest_unstable, DictationModelDeleteRequest_unstable, DictationModelDownloadProgressRequest_unstable, DictationModelDownloadProgressResponse_unstable, DictationModelDownloadRequest_unstable, DictationModelOption, DictationModelSelectRequest_unstable, DictationModelsListRequest_unstable, DictationModelsListResponse_unstable, DictationProviderStatusEntry, DictationSecretDeleteRequest_unstable, DictationSecretSaveRequest_unstable, DictationTranscribeRequest_unstable, DictationTranscribeResponse_unstable, ElicitationRespondRequest_unstable, EmptyResponse, EnvVariable, ExportSessionRequest_unstable, ExportSessionResponse_unstable, ExportSourceRequest_unstable, ExportSourceResponse_unstable, ExtNotification, ExtRequest, ExtResponse, GetAvailableExtensionsRequest_unstable, GetAvailableExtensionsResponse_unstable, GetConfigExtensionsRequest_unstable, GetConfigExtensionsResponse_unstable, GetSessionExtensionsRequest_unstable, GetSessionExtensionsResponse_unstable, GetToolsRequest_unstable, GetToolsResponse_unstable, GooseExtension, GooseExtensionEntry, GooseSessionNotification_unstable, GooseSessionUpdate, GooseToolCallRequest_unstable, GooseToolCallResponse_unstable, HttpHeader, ImportSessionRequest_unstable, ImportSessionResponse_unstable, ImportSourcesRequest_unstable, ImportSourcesResponse_unstable, Interaction, InteractionState, InteractionUpdate, ListProvidersRequest_unstable, ListProvidersResponse_unstable, ListSourcesRequest_unstable, ListSourcesResponse_unstable, McpServer, McpServerHttp, McpServerSse, McpServerStdio, OnboardingImportApplyRequest_unstable, OnboardingImportApplyResponse_unstable, OnboardingImportCandidate, OnboardingImportCounts, OnboardingImportScanRequest_unstable, OnboardingImportScanResponse_unstable, OnboardingImportSourceKind, PreferenceKey, PreferencesReadRequest_unstable, PreferencesReadResponse_unstable, PreferencesRemoveRequest_unstable, PreferencesSaveRequest_unstable, PreferenceValue, ProviderCatalogListRequest_unstable, ProviderCatalogListResponse_unstable, ProviderCatalogTemplateRequest_unstable, ProviderCatalogTemplateResponse_unstable, ProviderConfigAuthenticateRequest_unstable, ProviderConfigChangeResponse_unstable, ProviderConfigDeleteRequest_unstable, ProviderConfigFieldUpdate, ProviderConfigFieldValueDto, ProviderConfigKey, ProviderConfigReadRequest_unstable, ProviderConfigReadResponse_unstable, ProviderConfigSaveRequest_unstable, ProviderConfigStatusDto, ProviderConfigStatusRequest_unstable, ProviderConfigStatusResponse_unstable, ProviderInventoryEntryDto, ProviderInventoryModelDto, ProviderSetupCatalogEntryDto, ProviderSetupCatalogListRequest_unstable, ProviderSetupCatalogListResponse_unstable, ProviderSetupCategoryDto, ProviderSetupFieldDto, ProviderSetupGroupDto, ProviderSetupMethodDto, ProviderSupportedModelsListRequest_unstable, ProviderSupportedModelsListResponse_unstable, ProviderTemplateCapabilitiesDto, ProviderTemplateCatalogEntryDto, ProviderTemplateDto, ProviderTemplateModelDto, ReadResourceRequest_unstable, ReadResourceResponse_unstable, RefreshProviderInventoryRequest_unstable, RefreshProviderInventoryResponse_unstable, RefreshProviderInventorySkipDto, RefreshProviderInventorySkipReasonDto, RemoveConfigExtensionRequest_unstable, RemoveExtensionRequest_unstable, RenameSessionRequest_unstable, SessionSystemPromptMode, SessionUsageUpdate, SetConfigExtensionEnabledRequest_unstable, SetSessionSystemPromptRequest_unstable, SourceEntry, SourceScope, SourceType, StatusMessage, StatusMessageUpdate, UnarchiveSessionRequest_unstable, UpdateSessionProjectRequest_unstable, UpdateSourceRequest_unstable, UpdateSourceResponse_unstable, UpdateWorkingDirRequest_unstable } from './types.gen.js'; export const GOOSE_EXT_METHODS = [ { diff --git a/ui/sdk/src/generated/types.gen.ts b/ui/sdk/src/generated/types.gen.ts index cfec115f598e..bf7bf3112e2a 100644 --- a/ui/sdk/src/generated/types.gen.ts +++ b/ui/sdk/src/generated/types.gen.ts @@ -119,32 +119,211 @@ export type DeleteSessionRequest = { /** * List configured extensions and any warnings. */ -export type GetExtensionsRequest_unstable = { +export type GetConfigExtensionsRequest_unstable = { [key: string]: unknown; }; /** * List configured extensions and any warnings. */ -export type GetExtensionsResponse_unstable = { +export type GetConfigExtensionsResponse_unstable = { + extensions: Array; + warnings?: Array; +}; + +export type GooseExtensionEntry = { + extension: GooseExtension; + enabled: boolean; + configKey?: string | null; +}; + +export type GooseExtension = { + name: string; + description?: string | null; + display_name?: string | null; + timeout?: number | null; + bundled?: boolean | null; + type: 'builtin'; +} | { + name: string; + description?: string | null; + display_name?: string | null; + bundled?: boolean | null; + type: 'platform'; +} | { + server: McpServer; + envKeys?: Array; + description?: string | null; + timeout?: number | null; + socket?: string | null; + bundled?: boolean | null; + type: 'mcp'; +}; + +/** + * Configuration for connecting to an MCP (Model Context Protocol) server. + * + * MCP servers provide tools and context that the agent can use when + * processing prompts. + * + * See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers) + */ +export type McpServer = McpServerHttp | McpServerSse | McpServerStdio; + +/** + * An HTTP header to set when making requests to the MCP server. + */ +export type HttpHeader = { /** - * Array of ExtensionEntry objects with `enabled` flag, `configKey`, and flattened config details. + * The name of the HTTP header. */ - extensions: Array; - warnings: Array; + name: string; + /** + * The value to set for the HTTP header. + */ + value: string; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; }; /** - * Persist a new extension to the user's global goose config. + * HTTP transport configuration for MCP. */ -export type AddConfigExtensionRequest_unstable = { +export type McpServerHttp = { + /** + * Human-readable name identifying this MCP server. + */ + name: string; + /** + * URL to the MCP server. + */ + url: string; + /** + * HTTP headers to set when making requests to the MCP server. + */ + headers: Array; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + type: 'http'; +}; + +/** + * SSE transport configuration for MCP. + */ +export type McpServerSse = { + /** + * Human-readable name identifying this MCP server. + */ + name: string; + /** + * URL to the MCP server. + */ + url: string; + /** + * HTTP headers to set when making requests to the MCP server. + */ + headers: Array; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + type: 'sse'; +}; + +/** + * Stdio transport configuration for MCP. + */ +export type McpServerStdio = { + /** + * Human-readable name identifying this MCP server. + */ name: string; /** - * Extension configuration. Must be a JSON object matching one of the - * `ExtensionConfig` variants (e.g. `stdio`, `streamable_http`, `builtin`). - * `name` and `enabled` are injected server-side. + * Path to the MCP server executable. + */ + command: string; + /** + * Command-line arguments to pass to the MCP server. + */ + args: Array; + /** + * Environment variables to set when launching the MCP server. + */ + env: Array; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) */ - extensionConfig?: unknown; + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * An environment variable to set when launching an MCP server. + */ +export type EnvVariable = { + /** + * The name of the environment variable. + */ + name: string; + /** + * The value to set for the environment variable. + */ + value: string; + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * List Goose-owned extension definitions available to configure or enable. + */ +export type GetAvailableExtensionsRequest_unstable = { + [key: string]: unknown; +}; + +export type GetAvailableExtensionsResponse_unstable = { + extensions: Array; +}; + +/** + * Persist a new extension to the user's global goose config. + */ +export type AddConfigExtensionRequest_unstable = { + extension: GooseExtension; enabled?: boolean; }; @@ -156,9 +335,9 @@ export type RemoveConfigExtensionRequest_unstable = { }; /** - * Toggle the `enabled` flag for a persisted extension in the user's global goose config. + * Set the `enabled` flag for a persisted extension in the user's global goose config. */ -export type ToggleConfigExtensionRequest_unstable = { +export type SetConfigExtensionEnabledRequest_unstable = { configKey: string; enabled: boolean; }; @@ -1166,14 +1345,14 @@ export type InteractionUpdate = { export type ExtRequest = { id: string; method: string; - params?: AddExtensionRequest_unstable | RemoveExtensionRequest_unstable | GetToolsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | DeleteSessionRequest | GetExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | ToggleConfigExtensionRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | ElicitationRespondRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | { + params?: AddExtensionRequest_unstable | RemoveExtensionRequest_unstable | GetToolsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | DeleteSessionRequest | GetConfigExtensionsRequest_unstable | GetAvailableExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | SetConfigExtensionEnabledRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | ElicitationRespondRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | { [key: string]: unknown; } | null; }; export type ExtResponse = { id: string; - result?: EmptyResponse | GetToolsResponse_unstable | GooseToolCallResponse_unstable | ReadResourceResponse_unstable | GetExtensionsResponse_unstable | GetSessionExtensionsResponse_unstable | ListProvidersResponse_unstable | ProviderSupportedModelsListResponse_unstable | ProviderCatalogListResponse_unstable | ProviderSetupCatalogListResponse_unstable | ProviderCatalogTemplateResponse_unstable | CustomProviderCreateResponse_unstable | CustomProviderReadResponse_unstable | CustomProviderUpdateResponse_unstable | CustomProviderDeleteResponse_unstable | RefreshProviderInventoryResponse_unstable | ProviderConfigReadResponse_unstable | ProviderConfigStatusResponse_unstable | ProviderConfigChangeResponse_unstable | PreferencesReadResponse_unstable | DefaultsReadResponse_unstable | OnboardingImportScanResponse_unstable | OnboardingImportApplyResponse_unstable | ExportSessionResponse_unstable | ImportSessionResponse_unstable | CreateSourceResponse_unstable | ListSourcesResponse_unstable | UpdateSourceResponse_unstable | ExportSourceResponse_unstable | ImportSourcesResponse_unstable | DictationTranscribeResponse_unstable | DictationConfigResponse_unstable | DictationModelsListResponse_unstable | DictationModelDownloadProgressResponse_unstable | unknown; + result?: EmptyResponse | GetToolsResponse_unstable | GooseToolCallResponse_unstable | ReadResourceResponse_unstable | GetConfigExtensionsResponse_unstable | GetAvailableExtensionsResponse_unstable | GetSessionExtensionsResponse_unstable | ListProvidersResponse_unstable | ProviderSupportedModelsListResponse_unstable | ProviderCatalogListResponse_unstable | ProviderSetupCatalogListResponse_unstable | ProviderCatalogTemplateResponse_unstable | CustomProviderCreateResponse_unstable | CustomProviderReadResponse_unstable | CustomProviderUpdateResponse_unstable | CustomProviderDeleteResponse_unstable | RefreshProviderInventoryResponse_unstable | ProviderConfigReadResponse_unstable | ProviderConfigStatusResponse_unstable | ProviderConfigChangeResponse_unstable | PreferencesReadResponse_unstable | DefaultsReadResponse_unstable | OnboardingImportScanResponse_unstable | OnboardingImportApplyResponse_unstable | ExportSessionResponse_unstable | ImportSessionResponse_unstable | CreateSourceResponse_unstable | ListSourcesResponse_unstable | UpdateSourceResponse_unstable | ExportSourceResponse_unstable | ImportSourcesResponse_unstable | DictationTranscribeResponse_unstable | DictationConfigResponse_unstable | DictationModelsListResponse_unstable | DictationModelDownloadProgressResponse_unstable | unknown; } | { error: { code: number; From 575baf1d4cb7dbbe7e9c5f98d8922aaa11626409 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Thu, 4 Jun 2026 19:45:18 +1000 Subject: [PATCH 15/16] fixed test --- .../goose/tests/acp_custom_requests_test.rs | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/crates/goose/tests/acp_custom_requests_test.rs b/crates/goose/tests/acp_custom_requests_test.rs index 4838c777fd14..52983a2fe9f5 100644 --- a/crates/goose/tests/acp_custom_requests_test.rs +++ b/crates/goose/tests/acp_custom_requests_test.rs @@ -7,13 +7,11 @@ use common_tests::fixtures::{ run_test, send_custom, Connection, PermissionDecision, Session, SessionData, TestConnectionConfig, }; -use fs_err as fs; use goose::acp::server::AcpProviderFactory; -use goose::config::base::CONFIG_YAML_NAME; use goose::model::ModelConfig; use goose::providers::base::{MessageStream, Provider}; use goose::providers::errors::ProviderError; -use goose_test_support::{EnforceSessionId, IgnoreSessionId, TEST_MODEL}; +use goose_test_support::{EnforceSessionId, IgnoreSessionId}; use serial_test::serial; use std::path::PathBuf; use std::sync::{Arc, LazyLock, Mutex}; @@ -123,20 +121,8 @@ fn test_custom_get_tools() { #[serial] fn test_custom_get_extensions() { let config_key = "test-stdio-acp-mutation-flow"; - let temp_dir = tempfile::tempdir().unwrap(); - let temp_root = temp_dir.path().to_string_lossy().to_string(); - let _guard = env_lock::lock_env([ - ("GOOSE_PATH_ROOT", Some(temp_root.as_str())), - ("EXTENSIONS", None::<&str>), - ]); - let config_dir = temp_dir.path().join("config"); - fs::create_dir_all(&config_dir).unwrap(); - let config_yaml = format!( - r#"GOOSE_MODEL: {TEST_MODEL} -GOOSE_PROVIDER: openai -"# - ); - fs::write(config_dir.join(CONFIG_YAML_NAME), config_yaml).unwrap(); + let _guard = env_lock::lock_env([("EXTENSIONS", None::<&str>)]); + write_acp_global_config(DEFAULT_ACP_TEST_CONFIG); run_test(async move { let openai = OpenAiFixture::new(vec![], Arc::new(EnforceSessionId::default())).await; @@ -246,6 +232,7 @@ GOOSE_PROVIDER: openai } #[test] +#[serial] fn test_custom_get_available_extensions() { run_test(async move { let openai = OpenAiFixture::new(vec![], Arc::new(EnforceSessionId::default())).await; From 8176800f6a61d359ada1c9d060e9413955cc66fb Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Fri, 5 Jun 2026 17:53:32 +1000 Subject: [PATCH 16/16] save inline env to secret --- crates/goose/src/acp/server/extensions.rs | 80 ++++++++++++++----- .../goose/tests/acp_custom_requests_test.rs | 25 +++++- 2 files changed, 84 insertions(+), 21 deletions(-) diff --git a/crates/goose/src/acp/server/extensions.rs b/crates/goose/src/acp/server/extensions.rs index c4ff4937c774..ff58cb21d358 100644 --- a/crates/goose/src/acp/server/extensions.rs +++ b/crates/goose/src/acp/server/extensions.rs @@ -74,11 +74,15 @@ impl GooseAcpAgent { &self, req: AddConfigExtensionRequest, ) -> Result { - let config = goose_extension_to_config(req.extension)?; + let conversion = goose_extension_to_config(req.extension)?; + + Config::global() + .set_secret_values(&conversion.secret_updates) + .internal_err_ctx("Failed to save extension env secrets")?; crate::config::extensions::set_extension(ExtensionEntry { enabled: req.enabled, - config, + config: conversion.config, }); Ok(EmptyResponse {}) } @@ -211,9 +215,15 @@ fn config_to_goose_extension( Ok(Some(extension)) } +struct ConfigExtensionConversion { + config: ExtensionConfig, + secret_updates: Vec<(String, serde_json::Value)>, +} + fn goose_extension_to_config( extension: GooseExtension, -) -> Result { +) -> Result { + let mut secret_updates = Vec::new(); let config = match extension { GooseExtension::Builtin { name, @@ -254,10 +264,12 @@ fn goose_extension_to_config( return Err(agent_client_protocol::Error::invalid_params() .data("socket is only supported for streamable_http MCP extensions")); } - if !stdio.env.is_empty() { - return Err(agent_client_protocol::Error::invalid_params().data( - "literal env values are unsupported for config extensions; use envKeys", - )); + let mut env_keys = env_keys; + for env in stdio.env { + if !env_keys.contains(&env.name) { + env_keys.push(env.name.clone()); + } + secret_updates.push((env.name, serde_json::Value::String(env.value))); } ExtensionConfig::Stdio { name: stdio.name, @@ -298,7 +310,10 @@ fn goose_extension_to_config( } }, }; - Ok(config) + Ok(ConfigExtensionConversion { + config, + secret_updates, + }) } fn config_entry_to_goose_entry( @@ -568,7 +583,8 @@ mod tests { bundled: Some(true), }; - let config = goose_extension_to_config(extension).expect("conversion should succeed"); + let conversion = goose_extension_to_config(extension).expect("conversion should succeed"); + assert!(conversion.secret_updates.is_empty()); let ExtensionConfig::Stdio { name, @@ -580,7 +596,7 @@ mod tests { timeout, bundled, available_tools, - } = config + } = conversion.config else { panic!("expected stdio config"); }; @@ -600,10 +616,11 @@ mod tests { } #[test] - fn goose_mcp_stdio_extension_rejects_literal_envs_for_config_add() { + fn goose_mcp_stdio_extension_extracts_literal_envs_for_config_add() { let extension = GooseExtension::Mcp { server: McpServer::Stdio(McpServerStdio::new("test-stdio", "test-command").env(vec![ agent_client_protocol::schema::EnvVariable::new("SECRET_TOKEN", "literal-secret"), + agent_client_protocol::schema::EnvVariable::new("OTHER_TOKEN", "other-secret"), ])), env_keys: vec!["SECRET_TOKEN".to_string()], description: Some("Test stdio".to_string()), @@ -612,7 +629,31 @@ mod tests { bundled: Some(true), }; - assert!(goose_extension_to_config(extension).is_err()); + let conversion = goose_extension_to_config(extension).expect("conversion should succeed"); + + assert_eq!( + conversion.secret_updates, + vec![ + ( + "SECRET_TOKEN".to_string(), + serde_json::Value::String("literal-secret".to_string()) + ), + ( + "OTHER_TOKEN".to_string(), + serde_json::Value::String("other-secret".to_string()) + ) + ] + ); + + let ExtensionConfig::Stdio { envs, env_keys, .. } = conversion.config else { + panic!("expected stdio config"); + }; + + assert!( + envs.get_env().is_empty(), + "literal envs should not be persisted" + ); + assert_eq!(env_keys, vec!["SECRET_TOKEN", "OTHER_TOKEN"]); } #[test] @@ -630,7 +671,8 @@ mod tests { bundled: Some(true), }; - let config = goose_extension_to_config(extension).expect("conversion should succeed"); + let conversion = goose_extension_to_config(extension).expect("conversion should succeed"); + assert!(conversion.secret_updates.is_empty()); let ExtensionConfig::StreamableHttp { name, @@ -643,7 +685,7 @@ mod tests { socket, bundled, available_tools, - } = config + } = conversion.config else { panic!("expected streamable http config"); }; @@ -679,7 +721,8 @@ mod tests { bundled: Some(true), }; - let config = goose_extension_to_config(builtin).expect("conversion should succeed"); + let conversion = goose_extension_to_config(builtin).expect("conversion should succeed"); + assert!(conversion.secret_updates.is_empty()); let ExtensionConfig::Builtin { name, @@ -688,7 +731,7 @@ mod tests { timeout, bundled, available_tools, - } = config + } = conversion.config else { panic!("expected builtin config"); }; @@ -710,7 +753,8 @@ mod tests { bundled: Some(true), }; - let config = goose_extension_to_config(platform).expect("conversion should succeed"); + let conversion = goose_extension_to_config(platform).expect("conversion should succeed"); + assert!(conversion.secret_updates.is_empty()); let ExtensionConfig::Platform { name, @@ -718,7 +762,7 @@ mod tests { display_name, bundled, available_tools, - } = config + } = conversion.config else { panic!("expected platform config"); }; diff --git a/crates/goose/tests/acp_custom_requests_test.rs b/crates/goose/tests/acp_custom_requests_test.rs index 52983a2fe9f5..9db97bc817d6 100644 --- a/crates/goose/tests/acp_custom_requests_test.rs +++ b/crates/goose/tests/acp_custom_requests_test.rs @@ -18,15 +18,21 @@ use std::sync::{Arc, LazyLock, Mutex}; use common_tests::fixtures::OpenAiFixture; -const DEFAULT_ACP_TEST_CONFIG: &str = "GOOSE_MODEL: gpt-4o\nGOOSE_PROVIDER: openai\n"; +const DEFAULT_ACP_TEST_CONFIG: &str = + "GOOSE_MODEL: gpt-4o\nGOOSE_PROVIDER: openai\nGOOSE_DISABLE_KEYRING: true\n"; static ACP_CONFIG_ROOT: LazyLock = LazyLock::new(|| tempfile::tempdir().unwrap()); fn write_acp_global_config(contents: &str) -> PathBuf { std::env::set_var("GOOSE_PATH_ROOT", ACP_CONFIG_ROOT.path()); + std::env::set_var("GOOSE_DISABLE_KEYRING", "1"); let config_dir = goose::config::paths::Paths::config_dir(); std::fs::create_dir_all(&config_dir).unwrap(); + let mut contents = contents.to_string(); + if !contents.contains("GOOSE_DISABLE_KEYRING") { + contents.push_str("GOOSE_DISABLE_KEYRING: true\n"); + } std::fs::write( config_dir.join(goose::config::base::CONFIG_YAML_NAME), contents, @@ -143,13 +149,22 @@ fn test_custom_get_extensions() { "name": config_key, "command": "test-command", "args": ["--flag", "value"], - "env": [] + "env": [ + { "name": "INLINE_TOKEN", "value": "inline-secret" } + ] } } }), ) .await; assert!(add_result.is_ok(), "expected ok, got: {:?}", add_result); + let stored_inline_token = goose::config::Config::global() + .get_secret::("INLINE_TOKEN") + .expect("inline env should be saved as a secret"); + assert!( + stored_inline_token == "inline-secret", + "inline env secret was not saved correctly" + ); let list_extension = || async { let result = send_custom( @@ -179,7 +194,10 @@ fn test_custom_get_extensions() { let extension = &entry["extension"]; assert_eq!(extension["type"], "mcp"); - assert_eq!(extension["envKeys"], serde_json::json!(["SECRET_TOKEN"])); + assert_eq!( + extension["envKeys"], + serde_json::json!(["SECRET_TOKEN", "INLINE_TOKEN"]) + ); assert_eq!(extension["description"], "Test stdio"); assert_eq!(extension["timeout"], 42); assert!(extension.get("socket").is_none()); @@ -234,6 +252,7 @@ fn test_custom_get_extensions() { #[test] #[serial] fn test_custom_get_available_extensions() { + write_acp_global_config(DEFAULT_ACP_TEST_CONFIG); run_test(async move { let openai = OpenAiFixture::new(vec![], Arc::new(EnforceSessionId::default())).await; let conn = AcpServerConnection::new(TestConnectionConfig::default(), openai).await;