mirror of
https://github.com/aaif-goose/goose.git
synced 2026-07-03 14:10:03 +02:00
Move platform extensions into their own folder (#7210)
Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
@@ -15,8 +15,8 @@ use super::tool_execution::{ToolCallResult, CHAT_MODE_TOOL_SKIPPED_RESPONSE, DEC
|
||||
use crate::action_required_manager::ActionRequiredManager;
|
||||
use crate::agents::extension::{ExtensionConfig, ExtensionResult, ToolInfo};
|
||||
use crate::agents::extension_manager::{get_parameter_names, ExtensionManager};
|
||||
use crate::agents::extension_manager_extension::MANAGE_EXTENSIONS_TOOL_NAME_COMPLETE;
|
||||
use crate::agents::final_output_tool::{FINAL_OUTPUT_CONTINUATION_MESSAGE, FINAL_OUTPUT_TOOL_NAME};
|
||||
use crate::agents::platform_extensions::MANAGE_EXTENSIONS_TOOL_NAME_COMPLETE;
|
||||
use crate::agents::platform_tools::PLATFORM_MANAGE_SCHEDULE_TOOL_NAME;
|
||||
use crate::agents::prompt_manager::PromptManager;
|
||||
use crate::agents::retry::{RetryManager, RetryResult};
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
mod agent;
|
||||
pub(crate) mod apps_extension;
|
||||
pub(crate) mod builtin_skills;
|
||||
pub(crate) mod chatrecall_extension;
|
||||
pub(crate) mod code_execution_extension;
|
||||
pub mod container;
|
||||
pub mod execute_commands;
|
||||
pub mod extension;
|
||||
pub mod extension_malware_check;
|
||||
pub mod extension_manager;
|
||||
pub mod extension_manager_extension;
|
||||
pub mod final_output_tool;
|
||||
mod large_response_handler;
|
||||
pub mod mcp_client;
|
||||
pub mod moim;
|
||||
pub mod platform_extensions;
|
||||
pub mod platform_tools;
|
||||
pub mod prompt_manager;
|
||||
mod reply_parts;
|
||||
@@ -21,9 +18,6 @@ mod schedule_tool;
|
||||
pub mod subagent_execution_tool;
|
||||
pub(crate) mod subagent_handler;
|
||||
pub(crate) mod subagent_task_config;
|
||||
pub(crate) mod summon_extension;
|
||||
pub(crate) mod todo_extension;
|
||||
pub(crate) mod tom_extension;
|
||||
mod tool_execution;
|
||||
pub mod types;
|
||||
|
||||
|
||||
+1
-1
@@ -150,7 +150,7 @@ impl AppsManagerClient {
|
||||
|
||||
fn ensure_default_apps(&self) -> Result<(), String> {
|
||||
// TODO(Douwe): we have the same check in cache, consider unifying that
|
||||
const CLOCK_HTML: &str = include_str!("../goose_apps/clock.html");
|
||||
const CLOCK_HTML: &str = include_str!("../../goose_apps/clock.html");
|
||||
|
||||
// Check if clock app exists
|
||||
let clock_path = self.apps_dir.join("clock.html");
|
||||
-5
@@ -13,7 +13,6 @@ use tokio_util::sync::CancellationToken;
|
||||
|
||||
pub static EXTENSION_NAME: &str = "chatrecall";
|
||||
|
||||
/// Parameters for the chatrecall tool
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||
struct ChatRecallParams {
|
||||
/// Search keywords. Use multiple related terms/synonyms (e.g., 'database postgres sql'). Mutually exclusive with session_id.
|
||||
@@ -120,7 +119,6 @@ impl ChatRecallClient {
|
||||
total
|
||||
);
|
||||
|
||||
// Show first 3 messages
|
||||
let first_count = std::cmp::min(3, total);
|
||||
output.push_str("--- First Few Messages ---\n\n");
|
||||
for (idx, msg) in msgs.iter().take(first_count).enumerate() {
|
||||
@@ -134,7 +132,6 @@ impl ChatRecallClient {
|
||||
output.push('\n');
|
||||
}
|
||||
|
||||
// Show last 3 messages (if different from first)
|
||||
if total > first_count {
|
||||
output.push_str("--- Last Few Messages ---\n\n");
|
||||
let last_count = std::cmp::min(3, total);
|
||||
@@ -186,7 +183,6 @@ impl ChatRecallClient {
|
||||
.and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok())
|
||||
.map(|dt| dt.with_timezone(&chrono::Utc));
|
||||
|
||||
// Exclude current session from results to avoid self-referential loops
|
||||
let exclude_session_id = Some(current_session_id.to_string());
|
||||
|
||||
match self
|
||||
@@ -248,7 +244,6 @@ impl ChatRecallClient {
|
||||
}
|
||||
|
||||
fn get_tools() -> Vec<Tool> {
|
||||
// Generate JSON schema from the ChatRecallParams struct
|
||||
let schema = schema_for!(ChatRecallParams);
|
||||
let schema_value =
|
||||
serde_json::to_value(schema).expect("Failed to serialize ChatRecallParams schema");
|
||||
+6
-18
@@ -16,10 +16,8 @@ use serde_json::Value;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::error;
|
||||
|
||||
pub static EXTENSION_NAME: &str = "Extension Manager";
|
||||
// pub static DISPLAY_NAME: &str = "Extension Manager";
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ExtensionManagerToolError {
|
||||
@@ -32,9 +30,6 @@ pub enum ExtensionManagerToolError {
|
||||
#[error("Missing required parameter: {param_name}")]
|
||||
MissingParameter { param_name: String },
|
||||
|
||||
#[error("Invalid action: {action}. Must be 'enable' or 'disable'")]
|
||||
InvalidAction { action: String },
|
||||
|
||||
#[error("Extension operation failed: {message}")]
|
||||
OperationFailed { message: String },
|
||||
|
||||
@@ -336,7 +331,6 @@ impl ExtensionManagerClient {
|
||||
}),
|
||||
];
|
||||
|
||||
// Only add resource tools if extension manager supports resources
|
||||
if let Some(weak_ref) = &self.context.extension_manager {
|
||||
if let Some(extension_manager) = weak_ref.upgrade() {
|
||||
if extension_manager.supports_resources().await {
|
||||
@@ -454,18 +448,12 @@ impl McpClientTrait for ExtensionManagerClient {
|
||||
|
||||
match result {
|
||||
Ok(content) => Ok(CallToolResult::success(content)),
|
||||
Err(error) => {
|
||||
// Log the error for debugging
|
||||
error!("Extension manager tool '{}' failed: {}", name, error);
|
||||
|
||||
// Return proper error result with is_error flag set
|
||||
Ok(CallToolResult {
|
||||
content: vec![Content::text(error.to_string())],
|
||||
is_error: Some(true), // ✅ Properly mark as error
|
||||
structured_content: None,
|
||||
meta: None,
|
||||
})
|
||||
}
|
||||
Err(error) => Ok(CallToolResult {
|
||||
content: vec![Content::text(error.to_string())],
|
||||
is_error: Some(true),
|
||||
structured_content: None,
|
||||
meta: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
pub mod apps;
|
||||
pub mod chatrecall;
|
||||
pub mod code_execution;
|
||||
pub mod ext_manager;
|
||||
pub mod summon;
|
||||
pub mod todo;
|
||||
pub mod tom;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::agents::mcp_client::McpClientTrait;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
pub use ext_manager::MANAGE_EXTENSIONS_TOOL_NAME_COMPLETE;
|
||||
|
||||
// These are used by integration tests in crates/goose/tests/
|
||||
#[allow(unused_imports)]
|
||||
pub use ext_manager::MANAGE_EXTENSIONS_TOOL_NAME;
|
||||
#[allow(unused_imports)]
|
||||
pub use ext_manager::SEARCH_AVAILABLE_EXTENSIONS_TOOL_NAME;
|
||||
|
||||
pub static PLATFORM_EXTENSIONS: Lazy<HashMap<&'static str, PlatformExtensionDef>> = Lazy::new(
|
||||
|| {
|
||||
let mut map = HashMap::new();
|
||||
|
||||
map.insert(
|
||||
todo::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: todo::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::TodoClient::new(ctx).unwrap()),
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
apps::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: apps::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::AppsManagerClient::new(ctx).unwrap()),
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
chatrecall::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: chatrecall::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::ChatRecallClient::new(ctx).unwrap()),
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
"extensionmanager",
|
||||
PlatformExtensionDef {
|
||||
name: ext_manager::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(ext_manager::ExtensionManagerClient::new(ctx).unwrap()),
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
summon::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: summon::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::SummonClient::new(ctx).unwrap()),
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
code_execution::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: code_execution::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::CodeExecutionClient::new(ctx).unwrap())
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
map.insert(
|
||||
tom::EXTENSION_NAME,
|
||||
PlatformExtensionDef {
|
||||
name: tom::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::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>,
|
||||
}
|
||||
@@ -8,7 +8,7 @@ use serde_json::{json, Value};
|
||||
use tracing::debug;
|
||||
|
||||
use super::super::agents::Agent;
|
||||
use crate::agents::code_execution_extension::EXTENSION_NAME as CODE_EXECUTION_EXTENSION;
|
||||
use crate::agents::platform_extensions::code_execution;
|
||||
use crate::conversation::message::{Message, MessageContent, ToolRequest};
|
||||
use crate::conversation::Conversation;
|
||||
use crate::providers::base::{stream_from_single_message, MessageStream, Provider, ProviderUsage};
|
||||
@@ -146,7 +146,7 @@ impl Agent {
|
||||
|
||||
let code_execution_active = self
|
||||
.extension_manager
|
||||
.is_extension_enabled(CODE_EXECUTION_EXTENSION)
|
||||
.is_extension_enabled(code_execution::EXTENSION_NAME)
|
||||
.await;
|
||||
if code_execution_active {
|
||||
tools.retain(|tool| {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::agents::extension_manager_extension::MANAGE_EXTENSIONS_TOOL_NAME_COMPLETE;
|
||||
use crate::agents::platform_extensions::MANAGE_EXTENSIONS_TOOL_NAME_COMPLETE;
|
||||
use crate::config::permission::PermissionLevel;
|
||||
use crate::config::{GooseMode, PermissionManager};
|
||||
use crate::conversation::message::{Message, ToolRequest};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::agents::extension_manager_extension::MANAGE_EXTENSIONS_TOOL_NAME_COMPLETE;
|
||||
use crate::agents::platform_extensions::MANAGE_EXTENSIONS_TOOL_NAME_COMPLETE;
|
||||
use crate::config::permission::PermissionLevel;
|
||||
use crate::config::PermissionManager;
|
||||
use crate::conversation::message::{Message, MessageContent, ToolRequest};
|
||||
|
||||
@@ -510,7 +510,7 @@ mod tests {
|
||||
mod extension_manager_tests {
|
||||
use super::*;
|
||||
use goose::agents::extension::ExtensionConfig;
|
||||
use goose::agents::extension_manager_extension::{
|
||||
use goose::agents::platform_extensions::{
|
||||
MANAGE_EXTENSIONS_TOOL_NAME, SEARCH_AVAILABLE_EXTENSIONS_TOOL_NAME,
|
||||
};
|
||||
use goose::agents::AgentConfig;
|
||||
|
||||
Reference in New Issue
Block a user