Move platform extensions into their own folder (#7210)
Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
@@ -1,18 +1,9 @@
|
||||
use crate::agents::apps_extension;
|
||||
use crate::agents::chatrecall_extension;
|
||||
use crate::agents::code_execution_extension;
|
||||
use crate::agents::extension_manager_extension;
|
||||
use crate::agents::summon_extension;
|
||||
use crate::agents::todo_extension;
|
||||
use crate::agents::tom_extension;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::agents::mcp_client::McpClientTrait;
|
||||
use crate::config;
|
||||
use crate::config::extensions::name_to_key;
|
||||
use crate::config::permission::PermissionLevel;
|
||||
use crate::config::Config;
|
||||
use once_cell::sync::Lazy;
|
||||
use rmcp::model::Tool;
|
||||
use rmcp::service::ClientInitializeError;
|
||||
use rmcp::ServiceError as ClientError;
|
||||
@@ -22,6 +13,10 @@ use thiserror::Error;
|
||||
use tracing::warn;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub use crate::agents::platform_extensions::{
|
||||
PlatformExtensionContext, PlatformExtensionDef, PLATFORM_EXTENSIONS,
|
||||
};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("process quit before initialization: stderr = {stderr}")]
|
||||
pub struct ProcessExit {
|
||||
@@ -42,159 +37,6 @@ impl ProcessExit {
|
||||
}
|
||||
}
|
||||
|
||||
pub static PLATFORM_EXTENSIONS: Lazy<HashMap<&'static str, PlatformExtensionDef>> = Lazy::new(
|
||||
|| {
|
||||
let mut map = HashMap::new();
|
||||
|
||||
map.insert(
|
||||
todo_extension::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: todo_extension::EXTENSION_NAME,
|
||||
display_name: "Todo",
|
||||
description:
|
||||
"Enable a todo list for goose so it can keep track of what it is doing",
|
||||
default_enabled: true,
|
||||
unprefixed_tools: false,
|
||||
client_factory: |ctx| Box::new(todo_extension::TodoClient::new(ctx).unwrap()),
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
apps_extension::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: apps_extension::EXTENSION_NAME,
|
||||
display_name: "Apps",
|
||||
description:
|
||||
"Create and manage custom Goose apps through chat. Apps are HTML/CSS/JavaScript and run in sandboxed windows.",
|
||||
default_enabled: true,
|
||||
unprefixed_tools: false,
|
||||
client_factory: |ctx| Box::new(apps_extension::AppsManagerClient::new(ctx).unwrap()),
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
chatrecall_extension::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: chatrecall_extension::EXTENSION_NAME,
|
||||
display_name: "Chat Recall",
|
||||
description:
|
||||
"Search past conversations and load session summaries for contextual memory",
|
||||
default_enabled: false,
|
||||
unprefixed_tools: false,
|
||||
client_factory: |ctx| {
|
||||
Box::new(chatrecall_extension::ChatRecallClient::new(ctx).unwrap())
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
"extensionmanager",
|
||||
PlatformExtensionDef {
|
||||
name: extension_manager_extension::EXTENSION_NAME,
|
||||
display_name: "Extension Manager",
|
||||
description:
|
||||
"Enable extension management tools for discovering, enabling, and disabling extensions",
|
||||
default_enabled: true,
|
||||
unprefixed_tools: false,
|
||||
client_factory: |ctx| Box::new(extension_manager_extension::ExtensionManagerClient::new(ctx).unwrap()),
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
summon_extension::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: summon_extension::EXTENSION_NAME,
|
||||
display_name: "Summon",
|
||||
description: "Load knowledge and delegate tasks to subagents",
|
||||
default_enabled: true,
|
||||
unprefixed_tools: true,
|
||||
client_factory: |ctx| Box::new(summon_extension::SummonClient::new(ctx).unwrap()),
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
code_execution_extension::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: code_execution_extension::EXTENSION_NAME,
|
||||
display_name: "Code Mode",
|
||||
description:
|
||||
"Goose will make extension calls through code execution, saving tokens",
|
||||
default_enabled: false,
|
||||
unprefixed_tools: true,
|
||||
client_factory: |ctx| {
|
||||
Box::new(code_execution_extension::CodeExecutionClient::new(ctx).unwrap())
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
tom_extension::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: tom_extension::EXTENSION_NAME,
|
||||
display_name: "Top Of Mind",
|
||||
description:
|
||||
"Inject custom context into every turn via GOOSE_MOIM_MESSAGE_TEXT and GOOSE_MOIM_MESSAGE_FILE environment variables",
|
||||
default_enabled: true,
|
||||
unprefixed_tools: false,
|
||||
client_factory: |ctx| Box::new(tom_extension::TomClient::new(ctx).unwrap()),
|
||||
},
|
||||
);
|
||||
|
||||
map
|
||||
},
|
||||
);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PlatformExtensionContext {
|
||||
pub extension_manager:
|
||||
Option<std::sync::Weak<crate::agents::extension_manager::ExtensionManager>>,
|
||||
pub session_manager: std::sync::Arc<crate::session::SessionManager>,
|
||||
}
|
||||
|
||||
impl PlatformExtensionContext {
|
||||
pub fn result_with_platform_notification(
|
||||
&self,
|
||||
mut result: rmcp::model::CallToolResult,
|
||||
extension_name: impl Into<String>,
|
||||
event_type: impl Into<String>,
|
||||
mut additional_params: serde_json::Map<String, serde_json::Value>,
|
||||
) -> rmcp::model::CallToolResult {
|
||||
additional_params.insert("extension".to_string(), extension_name.into().into());
|
||||
additional_params.insert("event_type".to_string(), event_type.into().into());
|
||||
|
||||
let meta_value = serde_json::json!({
|
||||
"platform_notification": {
|
||||
"method": "platform_event",
|
||||
"params": additional_params
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(ref mut meta) = result.meta {
|
||||
if let Some(obj) = meta_value.as_object() {
|
||||
for (k, v) in obj {
|
||||
meta.0.insert(k.clone(), v.clone());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.meta = Some(rmcp::model::Meta(meta_value.as_object().unwrap().clone()));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
/// Definition for a platform extension that runs in-process with direct agent access.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PlatformExtensionDef {
|
||||
pub name: &'static str,
|
||||
pub display_name: &'static str,
|
||||
pub description: &'static str,
|
||||
pub default_enabled: bool,
|
||||
/// If true, tools are exposed without extension prefix for intuitive first-class use.
|
||||
pub unprefixed_tools: bool,
|
||||
pub client_factory: fn(PlatformExtensionContext) -> Box<dyn McpClientTrait>,
|
||||
}
|
||||
|
||||
/// Errors from Extension operation
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ExtensionError {
|
||||
|
||||
Reference in New Issue
Block a user