feat(templates): nom d'agent par défaut + permissions système et MCP outils sur AgentTemplate — #242

AgentTemplate étendu (defaultAgentName, systemPermissions, mcpToolPermissions),
CreateTemplate/UpdateTemplate/CreateAgentFromTemplate projetés vers l'agent créé,
DTO/MCP tools et persistance store complétés. Correctif modèle par défaut:
UpdateTemplate ne persistait pas defaultProfileId (profil stale à la création
d'agent). Backfill best-effort des templates existants depuis les agents du
projet au open_project, overrides explicites uniquement.
This commit is contained in:
2026-08-23 10:59:55 +02:00
parent ed5c5f73d6
commit d6c80be56d
11 changed files with 809 additions and 47 deletions

View File

@ -5,6 +5,8 @@ use serde::{Deserialize, Serialize};
use crate::error::DomainError;
use crate::ids::{ProfileId, TemplateId};
use crate::markdown::MarkdownDoc;
use crate::mcp_tool_permissions::McpToolPolicy;
use crate::system_permissions::SystemPermissionSet;
/// Monotonically increasing template version.
///
@ -55,6 +57,23 @@ pub struct AgentTemplate {
pub version: TemplateVersion,
/// Default runtime profile for agents created from this template.
pub default_profile_id: ProfileId,
/// Default agent name for agents created from this template. `None` falls
/// back to the template display name.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub default_agent_name: Option<String>,
/// Agent-level system permission override to apply at creation time.
/// `None` preserves project inheritance.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub default_system_permissions: Option<SystemPermissionSet>,
/// Agent-level MCP tool policy override to apply at creation time.
/// `None` preserves project inheritance.
#[serde(
default,
rename = "defaultMcpToolPermissions",
alias = "defaultMcpToolPolicy",
skip_serializing_if = "Option::is_none"
)]
pub default_mcp_tool_policy: Option<McpToolPolicy>,
}
impl AgentTemplate {
@ -76,6 +95,9 @@ impl AgentTemplate {
content_md,
version: TemplateVersion::INITIAL,
default_profile_id,
default_agent_name: None,
default_system_permissions: None,
default_mcp_tool_policy: None,
})
}
@ -89,4 +111,32 @@ impl AgentTemplate {
..self.clone()
}
}
/// Returns a copy with template metadata changed. The template version is
/// left unchanged because these defaults affect future agent creation only.
///
/// # Errors
/// Returns [`DomainError::EmptyField`] if `name` or a provided default agent
/// name is empty.
pub fn with_metadata(
&self,
name: String,
default_profile_id: ProfileId,
default_agent_name: Option<String>,
default_system_permissions: Option<SystemPermissionSet>,
default_mcp_tool_policy: Option<McpToolPolicy>,
) -> Result<Self, DomainError> {
crate::validation::non_empty(&name, "template.name")?;
if let Some(default_agent_name) = &default_agent_name {
crate::validation::non_empty(default_agent_name, "template.defaultAgentName")?;
}
Ok(Self {
name,
default_profile_id,
default_agent_name,
default_system_permissions,
default_mcp_tool_policy,
..self.clone()
})
}
}