feat(plugins): hot reload des plugins sans relancer IdeA — use case ReloadPlugin (invalidation registry/catalogue, resultat hashes+changed), tools MCP d'administration plugin agent-facing (mcp/plugins.rs + PluginToolProvider), evenement domaine plugin_reloaded relaye sur le wire (dto/events), exposition openai_tools rafraichie, wiring app-tauri — #271/#269 (QA verte #273: application 32, mcp_server 38, openai_tools 10, plugin_install_load 5, plugin 10, wire 1 — 96 tests ciblés; app-tauri compile sans desktop runtime)
This commit is contained in:
@ -35,6 +35,7 @@ use super::jsonrpc::{
|
||||
JSONRPC_VERSION,
|
||||
};
|
||||
use super::managed_temp::ManagedTempToolProvider;
|
||||
use super::plugins::PluginToolProvider;
|
||||
use super::policy::ToolPolicyRegistry;
|
||||
use super::templates::TemplateToolProvider;
|
||||
use super::tickets::TicketToolProvider;
|
||||
@ -84,6 +85,8 @@ pub struct McpServer {
|
||||
/// Optional public managed-temp provider. The MCP surface says `managed_temp`;
|
||||
/// the provider maps those calls to application managed-temp use cases.
|
||||
managed_temp_tools: Option<Arc<dyn ManagedTempToolProvider>>,
|
||||
/// Optional public plugin administration provider.
|
||||
plugin_tools: Option<Arc<dyn PluginToolProvider>>,
|
||||
/// Optional per-requester MCP tool policy registry for constrained sessions.
|
||||
tool_policies: Option<Arc<ToolPolicyRegistry>>,
|
||||
/// Optional durable MCP tool permission store. When wired, absence of project or
|
||||
@ -106,6 +109,7 @@ impl McpServer {
|
||||
ticket_tools: None,
|
||||
template_tools: None,
|
||||
managed_temp_tools: None,
|
||||
plugin_tools: None,
|
||||
tool_policies: None,
|
||||
mcp_tool_permissions: None,
|
||||
}
|
||||
@ -156,6 +160,13 @@ impl McpServer {
|
||||
self
|
||||
}
|
||||
|
||||
/// Attaches the public plugin administration provider.
|
||||
#[must_use]
|
||||
pub fn with_plugin_tools(mut self, plugin_tools: Arc<dyn PluginToolProvider>) -> Self {
|
||||
self.plugin_tools = Some(plugin_tools);
|
||||
self
|
||||
}
|
||||
|
||||
/// Attaches the requester-scoped MCP tool policy registry.
|
||||
#[must_use]
|
||||
pub fn with_tool_policies(mut self, tool_policies: Arc<ToolPolicyRegistry>) -> Self {
|
||||
@ -192,6 +203,7 @@ impl McpServer {
|
||||
ticket_tools: self.ticket_tools.clone(),
|
||||
template_tools: self.template_tools.clone(),
|
||||
managed_temp_tools: self.managed_temp_tools.clone(),
|
||||
plugin_tools: self.plugin_tools.clone(),
|
||||
tool_policies: self.tool_policies.clone(),
|
||||
mcp_tool_permissions: self.mcp_tool_permissions.clone(),
|
||||
}
|
||||
@ -624,6 +636,32 @@ impl McpServer {
|
||||
};
|
||||
}
|
||||
|
||||
if tools::is_plugin_tool(&name) {
|
||||
let result = match &self.plugin_tools {
|
||||
Some(provider) => {
|
||||
provider
|
||||
.handle_plugin_tool(&self.project, &self.requester, &name, arguments)
|
||||
.await
|
||||
}
|
||||
None => Err(super::plugins::PluginToolError::new(
|
||||
"UNAVAILABLE",
|
||||
"plugin tools are not configured",
|
||||
)),
|
||||
};
|
||||
self.publish_processed(&name, result.is_ok());
|
||||
return match result {
|
||||
Ok(value) => {
|
||||
let text = serde_json::to_string(&value).unwrap_or_else(|_| "null".to_owned());
|
||||
Ok(tool_result_text(&text, false))
|
||||
}
|
||||
Err(err) => {
|
||||
let text =
|
||||
serde_json::to_string(&err.to_value()).unwrap_or_else(|_| err.to_string());
|
||||
Ok(tool_result_text(&text, true))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// The handshake-provided requester is still passed to the mapper for tools that
|
||||
// need peer identity.
|
||||
let command = match tools::map_tool_call(&name, &arguments, &self.requester) {
|
||||
|
||||
Reference in New Issue
Block a user