feat(backend): système de plugins — domaine, application, infrastructure (#43)
Lots B1-B4 : modèle de domaine des plugins (manifeste, capacités menus/layouts/MCP), port et registre applicatif, chargement/validation en infrastructure, exposition DTO et commandes Tauri. Tests cargo verts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@ -44,6 +44,7 @@ fn leaf_for(tree: &LayoutTree, id: domain::NodeId) -> Option<LeafCell> {
|
||||
match n {
|
||||
LayoutNode::Leaf(l) if l.id == id => Some(l.clone()),
|
||||
LayoutNode::Leaf(_) => None,
|
||||
LayoutNode::CustomPluginLayout(_) => None,
|
||||
LayoutNode::Split(s) => s.children.iter().find_map(|c| walk(&c.node, id)),
|
||||
LayoutNode::Grid(g) => g.cells.iter().find_map(|c| walk(&c.node, id)),
|
||||
}
|
||||
@ -235,6 +236,7 @@ fn session_for(tree: &LayoutTree, id: domain::NodeId) -> Option<domain::SessionI
|
||||
match n {
|
||||
LayoutNode::Leaf(l) if l.id == id => Some(l.session),
|
||||
LayoutNode::Leaf(_) => None,
|
||||
LayoutNode::CustomPluginLayout(_) => None,
|
||||
LayoutNode::Split(s) => s.children.iter().find_map(|c| walk(&c.node, id)),
|
||||
LayoutNode::Grid(g) => g.cells.iter().find_map(|c| walk(&c.node, id)),
|
||||
}
|
||||
|
||||
@ -4,10 +4,10 @@
|
||||
mod helpers;
|
||||
|
||||
use domain::{
|
||||
Agent, AgentManifest, AgentOrigin, AgentProfile, AgentTemplate, ContextInjection, Direction,
|
||||
LayoutNode, LayoutTree, LeafCell, ManifestEntry, MarkdownDoc, Project, ProjectPath, RemoteRef,
|
||||
SessionStrategy, Skill, SkillId, SkillRef, SkillScope, SplitContainer, SshAuth,
|
||||
TemplateVersion, WeightedChild,
|
||||
Agent, AgentManifest, AgentOrigin, AgentProfile, AgentTemplate, ContextInjection,
|
||||
CustomPluginLayoutCell, Direction, LayoutNode, LayoutTree, LeafCell, ManifestEntry,
|
||||
MarkdownDoc, PluginId, PluginLayoutType, Project, ProjectPath, RemoteRef, SessionStrategy,
|
||||
Skill, SkillId, SkillRef, SkillScope, SplitContainer, SshAuth, TemplateVersion, WeightedChild,
|
||||
};
|
||||
use helpers::{node, session};
|
||||
use uuid::Uuid;
|
||||
@ -472,3 +472,29 @@ fn leaf_with_agent_roundtrip_and_omits_null() {
|
||||
"agent field should be omitted when None; json was {json2}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_plugin_layout_roundtrips_with_opaque_state() {
|
||||
let tree = LayoutTree::new(LayoutNode::CustomPluginLayout(CustomPluginLayoutCell {
|
||||
id: node(43),
|
||||
plugin_id: PluginId::new("dev.acme.gitgraph").unwrap(),
|
||||
layout_type: PluginLayoutType::new("dev.acme.gitgraph.layout").unwrap(),
|
||||
state: serde_json::json!({"branch":"main","zoom":2}),
|
||||
}));
|
||||
|
||||
assert_eq!(roundtrip(&tree), tree);
|
||||
let json = serde_json::to_string(&tree).unwrap();
|
||||
assert!(
|
||||
json.contains("\"type\":\"customPluginLayout\""),
|
||||
"json was {json}"
|
||||
);
|
||||
assert!(
|
||||
json.contains("\"pluginId\":\"dev.acme.gitgraph\""),
|
||||
"json was {json}"
|
||||
);
|
||||
assert!(
|
||||
json.contains("\"layoutType\":\"dev.acme.gitgraph.layout\""),
|
||||
"json was {json}"
|
||||
);
|
||||
assert!(json.contains("\"state\""), "json was {json}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user