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

@ -45,6 +45,8 @@ pub struct CreateTemplateInput {
pub default_system_permissions: Option<SystemPermissionSet>,
/// Optional agent-level MCP tool permission override applied at creation time.
pub default_mcp_tool_policy: Option<McpToolPolicy>,
/// Whether agents created from this template are cross-project contactable.
pub default_contactable: bool,
}
/// Output of [`CreateTemplate::execute`].
@ -90,6 +92,7 @@ impl CreateTemplate {
input.default_agent_name,
input.default_system_permissions,
input.default_mcp_tool_policy,
input.default_contactable,
)
})
.map_err(|e| AppError::Invalid(e.to_string()))?;
@ -122,6 +125,8 @@ pub struct UpdateTemplateInput {
/// New default MCP tool policy. Outer `None` leaves the current value; inner
/// `None` preserves project inheritance for future agents.
pub default_mcp_tool_policy: Option<Option<McpToolPolicy>>,
/// New default contactable flag. `None` leaves the current value.
pub default_contactable: Option<bool>,
}
/// Output of [`UpdateTemplate::execute`].
@ -175,6 +180,9 @@ impl UpdateTemplate {
input
.default_mcp_tool_policy
.unwrap_or_else(|| updated.default_mcp_tool_policy.clone()),
input
.default_contactable
.unwrap_or(updated.default_contactable),
)
.map_err(|e| AppError::Invalid(e.to_string()))?;
self.templates.save(&updated).await?;
@ -397,7 +405,8 @@ impl CreateAgentFromTemplate {
origin,
input.synchronized,
)
.map_err(|e| AppError::Invalid(e.to_string()))?;
.map_err(|e| AppError::Invalid(e.to_string()))?
.with_contactable(template.default_contactable);
let mut entries = manifest.entries;
entries.push(ManifestEntry::from_agent(&agent));