-
Notifications
You must be signed in to change notification settings - Fork 5.9k
feat: created sub recipe tools #2982
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
cc207bb
cc870fb
ad67286
285149a
1a32ff7
f610962
1db66e8
65923b3
77ab90c
8d5d4dd
94308e0
8592fb0
6c26884
00cf73c
559217f
c88bc24
69db1a3
7e39000
6042707
9822f66
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,13 +10,14 @@ use futures_util::stream; | |
| use futures_util::stream::StreamExt; | ||
| use mcp_core::protocol::JsonRpcMessage; | ||
|
|
||
| use crate::agents::sub_recipe_manager::SubRecipeManager; | ||
| use crate::config::{Config, ExtensionConfigManager, PermissionManager}; | ||
| use crate::message::Message; | ||
| use crate::permission::permission_judge::check_tool_permissions; | ||
| use crate::permission::PermissionConfirmation; | ||
| use crate::providers::base::Provider; | ||
| use crate::providers::errors::ProviderError; | ||
| use crate::recipe::{Author, Recipe, Settings}; | ||
| use crate::recipe::{Author, Recipe, Settings, SubRecipe}; | ||
| use crate::tool_monitor::{ToolCall, ToolMonitor}; | ||
| use regex::Regex; | ||
| use serde_json::Value; | ||
|
|
@@ -50,6 +51,7 @@ use super::tool_execution::{ToolCallResult, CHAT_MODE_TOOL_SKIPPED_RESPONSE, DEC | |
| pub struct Agent { | ||
| pub(super) provider: Mutex<Option<Arc<dyn Provider>>>, | ||
| pub(super) extension_manager: Mutex<ExtensionManager>, | ||
| pub(super) sub_recipe_manager: Mutex<SubRecipeManager>, | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I created a sub_recipe_manager to manage sub recipe tools and trigger the sub recipe tool call. I could also use the extension manager to add these tool, but the extension manager is mainly for MCP. So I create a sub_recipe_manager, maybe later it could evolve to sub_agent_manager
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems great. They are distinct from extensions so I think that makes sense. It also leaves the door open to agents treating sub-recipes differently: instead of shelling out to a new goose, a future version may use the same agent or a new in-process instance |
||
| pub(super) frontend_tools: Mutex<HashMap<String, FrontendTool>>, | ||
| pub(super) frontend_instructions: Mutex<Option<String>>, | ||
| pub(super) prompt_manager: Mutex<PromptManager>, | ||
|
|
@@ -76,6 +78,7 @@ impl Agent { | |
| Self { | ||
| provider: Mutex::new(None), | ||
| extension_manager: Mutex::new(ExtensionManager::new()), | ||
| sub_recipe_manager: Mutex::new(SubRecipeManager::new()), | ||
| frontend_tools: Mutex::new(HashMap::new()), | ||
| frontend_instructions: Mutex::new(None), | ||
| prompt_manager: Mutex::new(PromptManager::new()), | ||
|
|
@@ -182,6 +185,11 @@ impl Agent { | |
| Ok(tools) | ||
| } | ||
|
|
||
| pub async fn add_sub_recipes(&self, sub_recipes: Vec<SubRecipe>) { | ||
| let mut sub_recipe_manager = self.sub_recipe_manager.lock().await; | ||
| sub_recipe_manager.add_sub_recipe_tools(sub_recipes); | ||
| } | ||
|
|
||
| /// Dispatch a single tool call to the appropriate client | ||
| #[instrument(skip(self, tool_call, request_id), fields(input, output))] | ||
| pub(super) async fn dispatch_tool_call( | ||
|
|
@@ -224,7 +232,15 @@ impl Agent { | |
| } | ||
|
|
||
| let extension_manager = self.extension_manager.lock().await; | ||
| let result: ToolCallResult = if tool_call.name == PLATFORM_READ_RESOURCE_TOOL_NAME { | ||
| let sub_recipe_manager = self.sub_recipe_manager.lock().await; | ||
|
|
||
| let result: ToolCallResult = if sub_recipe_manager.is_sub_recipe_tool(&tool_call.name) { | ||
| ToolCallResult::from( | ||
| sub_recipe_manager | ||
| .run_sub_recipe(&tool_call.name, tool_call.arguments.clone()) | ||
| .await, | ||
| ) | ||
| } else if tool_call.name == PLATFORM_READ_RESOURCE_TOOL_NAME { | ||
| // Check if the tool is read_resource and handle it separately | ||
| ToolCallResult::from( | ||
| extension_manager | ||
|
|
@@ -450,16 +466,25 @@ impl Agent { | |
|
|
||
| if extension_name.is_none() || extension_name.as_deref() == Some("platform") { | ||
| // Add platform tools | ||
| prefixed_tools.push(platform_tools::search_available_extensions_tool()); | ||
| prefixed_tools.push(platform_tools::manage_extensions_tool()); | ||
| prefixed_tools.extend([ | ||
| platform_tools::search_available_extensions_tool(), | ||
| platform_tools::manage_extensions_tool(), | ||
| ]); | ||
|
|
||
| // Add resource tools if supported | ||
| if extension_manager.supports_resources() { | ||
| prefixed_tools.push(platform_tools::read_resource_tool()); | ||
| prefixed_tools.push(platform_tools::list_resources_tool()); | ||
| prefixed_tools.extend([ | ||
| platform_tools::read_resource_tool(), | ||
| platform_tools::list_resources_tool(), | ||
| ]); | ||
| } | ||
| } | ||
|
|
||
| if extension_name.is_none() { | ||
| let sub_recipe_manager = self.sub_recipe_manager.lock().await; | ||
| prefixed_tools.extend(sub_recipe_manager.sub_recipe_tools.values().cloned()); | ||
| } | ||
|
|
||
| prefixed_tools | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| pub mod sub_recipe_tools; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved to goose package to be reusable