mirror of
https://github.com/openai/codex.git
synced 2026-05-19 10:43:38 +00:00
feat(core): add reload_plugins tool
This commit is contained in:
@@ -15,6 +15,8 @@ pub(crate) mod multi_agents_spec;
|
||||
pub(crate) mod multi_agents_v2;
|
||||
mod plan;
|
||||
pub(crate) mod plan_spec;
|
||||
mod reload_plugins;
|
||||
pub(crate) mod reload_plugins_spec;
|
||||
mod request_permissions;
|
||||
mod request_plugin_install;
|
||||
pub(crate) mod request_plugin_install_spec;
|
||||
@@ -59,6 +61,7 @@ pub use mcp_resource::ListMcpResourceTemplatesHandler;
|
||||
pub use mcp_resource::ListMcpResourcesHandler;
|
||||
pub use mcp_resource::ReadMcpResourceHandler;
|
||||
pub use plan::PlanHandler;
|
||||
pub use reload_plugins::ReloadPluginsHandler;
|
||||
pub use request_permissions::RequestPermissionsHandler;
|
||||
pub use request_plugin_install::RequestPluginInstallHandler;
|
||||
pub use request_user_input::RequestUserInputHandler;
|
||||
|
||||
70
codex-rs/core/src/tools/handlers/reload_plugins.rs
Normal file
70
codex-rs/core/src/tools/handlers/reload_plugins.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::tools::context::FunctionToolOutput;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
use crate::tools::context::ToolOutput;
|
||||
use crate::tools::context::ToolPayload;
|
||||
use crate::tools::context::boxed_tool_output;
|
||||
use crate::tools::handlers::reload_plugins_spec::RELOAD_PLUGINS_TOOL_NAME;
|
||||
use crate::tools::handlers::reload_plugins_spec::create_reload_plugins_tool;
|
||||
use crate::tools::registry::CoreToolRuntime;
|
||||
use crate::tools::registry::ToolExecutor;
|
||||
use codex_tools::ToolName;
|
||||
use codex_tools::ToolSpec;
|
||||
|
||||
pub struct ReloadPluginsHandler;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl ToolExecutor<ToolInvocation> for ReloadPluginsHandler {
|
||||
fn tool_name(&self) -> ToolName {
|
||||
ToolName::plain(RELOAD_PLUGINS_TOOL_NAME)
|
||||
}
|
||||
|
||||
fn spec(&self) -> Option<ToolSpec> {
|
||||
Some(create_reload_plugins_tool())
|
||||
}
|
||||
|
||||
async fn handle(
|
||||
&self,
|
||||
invocation: ToolInvocation,
|
||||
) -> Result<Box<dyn ToolOutput>, FunctionCallError> {
|
||||
let ToolInvocation {
|
||||
payload,
|
||||
session,
|
||||
turn,
|
||||
..
|
||||
} = invocation;
|
||||
|
||||
match payload {
|
||||
ToolPayload::Function { arguments } if arguments.trim() == "{}" => {}
|
||||
ToolPayload::Function { arguments } if arguments.trim().is_empty() => {}
|
||||
ToolPayload::Function { .. } => {
|
||||
return Err(FunctionCallError::RespondToModel(
|
||||
"reload_plugins does not accept arguments".to_string(),
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
return Err(FunctionCallError::Fatal(format!(
|
||||
"{RELOAD_PLUGINS_TOOL_NAME} handler received unsupported payload"
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
session.reload_user_config_layer().await;
|
||||
let config = session.get_config().await;
|
||||
session
|
||||
.refresh_mcp_servers_now(
|
||||
turn.as_ref(),
|
||||
config.mcp_servers.get().clone(),
|
||||
config.mcp_oauth_credentials_store_mode,
|
||||
Some(session.mcp_elicitation_reviewer()),
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(boxed_tool_output(FunctionToolOutput::from_text(
|
||||
"{\"reloaded\":true}".to_string(),
|
||||
Some(true),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl CoreToolRuntime for ReloadPluginsHandler {}
|
||||
33
codex-rs/core/src/tools/handlers/reload_plugins_spec.rs
Normal file
33
codex-rs/core/src/tools/handlers/reload_plugins_spec.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
use codex_tools::JsonSchema;
|
||||
use codex_tools::ResponsesApiTool;
|
||||
use codex_tools::ToolSpec;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub const RELOAD_PLUGINS_TOOL_NAME: &str = "reload_plugins";
|
||||
|
||||
pub fn create_reload_plugins_tool() -> ToolSpec {
|
||||
ToolSpec::Function(ResponsesApiTool {
|
||||
name: RELOAD_PLUGINS_TOOL_NAME.to_string(),
|
||||
description: "Reload plugin configuration, clear plugin and skill caches, and rebuild MCP tools from the refreshed plugin state.".to_string(),
|
||||
strict: false,
|
||||
defer_loading: None,
|
||||
parameters: JsonSchema::object(BTreeMap::new(), Some(Vec::new()), Some(false.into())),
|
||||
output_schema: None,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn reload_plugins_tool_has_no_arguments() {
|
||||
let ToolSpec::Function(tool) = create_reload_plugins_tool() else {
|
||||
panic!("reload_plugins should be a function tool");
|
||||
};
|
||||
|
||||
assert_eq!(tool.name, RELOAD_PLUGINS_TOOL_NAME);
|
||||
assert_eq!(tool.parameters.required, Some(Vec::new()));
|
||||
assert_eq!(tool.parameters.properties, Some(BTreeMap::new()));
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ use crate::tools::handlers::ListMcpResourcesHandler;
|
||||
use crate::tools::handlers::McpHandler;
|
||||
use crate::tools::handlers::PlanHandler;
|
||||
use crate::tools::handlers::ReadMcpResourceHandler;
|
||||
use crate::tools::handlers::ReloadPluginsHandler;
|
||||
use crate::tools::handlers::RequestPermissionsHandler;
|
||||
use crate::tools::handlers::RequestPluginInstallHandler;
|
||||
use crate::tools::handlers::RequestUserInputHandler;
|
||||
@@ -45,6 +46,7 @@ use crate::tools::handlers::multi_agents_v2::ListAgentsHandler as ListAgentsHand
|
||||
use crate::tools::handlers::multi_agents_v2::SendMessageHandler as SendMessageHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::SpawnAgentHandler as SpawnAgentHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::WaitAgentHandler as WaitAgentHandlerV2;
|
||||
use crate::tools::handlers::reload_plugins_spec::RELOAD_PLUGINS_TOOL_NAME;
|
||||
use crate::tools::handlers::view_image_spec::ViewImageToolOptions;
|
||||
use crate::tools::hosted_spec::WebSearchToolOptions;
|
||||
use crate::tools::hosted_spec::create_image_generation_tool;
|
||||
@@ -435,6 +437,14 @@ fn collect_tool_executors(
|
||||
executors.push(Arc::new(TestSyncHandler));
|
||||
}
|
||||
|
||||
if config
|
||||
.experimental_supported_tools
|
||||
.iter()
|
||||
.any(|tool| tool == RELOAD_PLUGINS_TOOL_NAME)
|
||||
{
|
||||
executors.push(Arc::new(ReloadPluginsHandler));
|
||||
}
|
||||
|
||||
if config.environment_mode.has_environment() {
|
||||
let include_environment_id =
|
||||
matches!(config.environment_mode, ToolEnvironmentMode::Multiple);
|
||||
|
||||
@@ -14,6 +14,7 @@ use crate::tools::handlers::multi_agents_spec::create_spawn_agent_tool_v2;
|
||||
use crate::tools::handlers::multi_agents_spec::create_wait_agent_tool_v1;
|
||||
use crate::tools::handlers::multi_agents_spec::create_wait_agent_tool_v2;
|
||||
use crate::tools::handlers::plan_spec::create_update_plan_tool;
|
||||
use crate::tools::handlers::reload_plugins_spec::RELOAD_PLUGINS_TOOL_NAME;
|
||||
use crate::tools::handlers::request_user_input_spec::REQUEST_USER_INPUT_TOOL_NAME;
|
||||
use crate::tools::handlers::request_user_input_spec::create_request_user_input_tool;
|
||||
use crate::tools::handlers::request_user_input_spec::request_user_input_tool_description;
|
||||
@@ -1392,6 +1393,36 @@ fn test_test_model_info_includes_sync_tool() {
|
||||
assert!(tools.iter().any(|tool| tool.name() == "test_sync_tool"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_model_info_includes_reload_plugins_tool() {
|
||||
let mut model_info = model_info();
|
||||
model_info.experimental_supported_tools = vec![RELOAD_PLUGINS_TOOL_NAME.to_string()];
|
||||
let features = Features::with_defaults();
|
||||
let available_models = Vec::new();
|
||||
let tools_config = ToolsConfig::new(&ToolsConfigParams {
|
||||
model_info: &model_info,
|
||||
available_models: &available_models,
|
||||
features: &features,
|
||||
image_generation_tool_auth_allowed: true,
|
||||
web_search_mode: Some(WebSearchMode::Cached),
|
||||
session_source: SessionSource::Cli,
|
||||
permission_profile: &PermissionProfile::Disabled,
|
||||
windows_sandbox_level: WindowsSandboxLevel::Disabled,
|
||||
});
|
||||
let (tools, _) = build_specs(
|
||||
&tools_config,
|
||||
/*mcp_tools*/ None,
|
||||
/*deferred_mcp_tools*/ None,
|
||||
&[],
|
||||
);
|
||||
|
||||
assert!(
|
||||
tools
|
||||
.iter()
|
||||
.any(|tool| tool.name() == RELOAD_PLUGINS_TOOL_NAME)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_specs_mcp_tools_converted() {
|
||||
let model_info = model_info();
|
||||
|
||||
Reference in New Issue
Block a user