feat(cross-project): découverte et contact inter-projets — tools MCP idea_project_{list,read_context,list_agents,ask_agent,cancel_agent}, permission contactable par agent + default_contactable persistée dans les templates, routage orchestrator par projectId+agentId — #260 (tests ciblés verts, QA en attente)

This commit is contained in:
2026-09-07 16:31:14 +02:00
parent d7b24ad183
commit 98954986a7
18 changed files with 721 additions and 15 deletions

View File

@ -4295,6 +4295,8 @@ pub struct CreateTemplateRequestDto {
pub default_system_permissions: Option<SystemPermissionSet>,
/// Optional agent-level MCP tool policy override for created agents.
pub default_mcp_tool_policy: Option<McpToolPolicy>,
/// Whether agents created from this template are cross-project contactable.
pub default_contactable: bool,
}
impl<'de> Deserialize<'de> for CreateTemplateRequestDto {
@ -4327,6 +4329,10 @@ impl<'de> Deserialize<'de> for CreateTemplateRequestDto {
)
.map_err(serde::de::Error::custom)?
.flatten();
let default_contactable = take_optional_value::<bool>(object, "defaultContactable")
.map_err(serde::de::Error::custom)?
.flatten()
.unwrap_or(false);
Ok(Self {
name,
content,
@ -4334,6 +4340,7 @@ impl<'de> Deserialize<'de> for CreateTemplateRequestDto {
default_agent_name,
default_system_permissions,
default_mcp_tool_policy,
default_contactable,
})
}
}
@ -4351,6 +4358,7 @@ impl CreateTemplateRequestDto {
default_agent_name: self.default_agent_name,
default_system_permissions: self.default_system_permissions,
default_mcp_tool_policy: self.default_mcp_tool_policy,
default_contactable: self.default_contactable,
})
}
}
@ -4372,6 +4380,8 @@ pub struct UpdateTemplateRequestDto {
pub default_system_permissions: Option<Option<SystemPermissionSet>>,
/// New default MCP tool policy. Missing leaves it unchanged; null clears it.
pub default_mcp_tool_policy: Option<Option<McpToolPolicy>>,
/// New default contactable flag. Missing leaves it unchanged.
pub default_contactable: Option<bool>,
}
impl<'de> Deserialize<'de> for UpdateTemplateRequestDto {
@ -4408,6 +4418,9 @@ impl<'de> Deserialize<'de> for UpdateTemplateRequestDto {
],
)
.map_err(serde::de::Error::custom)?;
let default_contactable = take_optional_value::<bool>(object, "defaultContactable")
.map_err(serde::de::Error::custom)?
.flatten();
Ok(Self {
template_id,
content,
@ -4416,6 +4429,7 @@ impl<'de> Deserialize<'de> for UpdateTemplateRequestDto {
default_agent_name,
default_system_permissions,
default_mcp_tool_policy,
default_contactable,
})
}
}
@ -4438,6 +4452,7 @@ impl UpdateTemplateRequestDto {
default_agent_name: self.default_agent_name,
default_system_permissions: self.default_system_permissions,
default_mcp_tool_policy: self.default_mcp_tool_policy,
default_contactable: self.default_contactable,
})
}
}

View File

@ -3033,6 +3033,7 @@ impl BackendCore {
// Messagerie inter-agents (cadrage C3) : médiateur d'entrée (file + livraison
// PTV sérialisée) + registre de conversations + bus pour AgentReplied.
.with_input_mediator(Arc::clone(&input_mediator), Arc::clone(&mailbox))
.with_project_store(Arc::clone(&store_port))
.with_conversations(Arc::clone(&conversation_registry))
.with_events(Arc::clone(&events_port))
// Faits OS/runtime (exe $APPIMAGE/current_exe + endpoint loopback) pour
@ -4973,6 +4974,7 @@ mod mcp_serve_peer_tests {
synced_template_version: None,
skills: Vec::new(),
effort: None,
contactable: false,
});
id
}
@ -6310,6 +6312,7 @@ mod mcp_e2e_loopback_tests {
synced_template_version: None,
skills: Vec::new(),
effort: None,
contactable: false,
});
id
}