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:
2026-07-22 07:37:03 +02:00
parent 47aacc6da9
commit bb35641715
24 changed files with 4304 additions and 41 deletions

View File

@ -24,27 +24,30 @@ use application::{
EnsureLocalModelServer, FirstRunState, GetAppExitWorkGuardState, GetLiveStateLean, GetMemory,
GetProjectPermissions, GetProjectWorkState, GitBranches, GitCheckout, GitCommit, GitGraph,
GitInit, GitLog, GitStage, GitStatus, GitUnstage, HarvestMemoryFromTurn, HealthUseCase,
InspectConversation, LaunchAgent, LaunchAgentInput, LinkIssues, ListAgents, ListAgentsInput,
ListDevices, ListEmbedderProfiles, ListIssues, ListLayouts, ListMemories, ListModelServers,
ListProfiles, ListProjects, ListResumableAgents, ListSkills, ListSprints, ListTemplates,
LiveAgentRegistry, LiveSessions, LiveStateLeanProvider, LiveStateProvider,
LiveStateReadProvider, LoadLayout, McpRuntime, McpToolPermissionCatalogue, MoveTabToNewWindow,
MutateLayout, OnnxModelView, OpenProject, OpenTerminal, OpenTicketAssistant,
OrchestratorService, PairAttemptLimiter, PairDevice, PermissionProjectorRegistry,
ProposeContext, ReadAgentContext, ReadContext, ReadConversationPage, ReadIssue,
ReadIssueCarnet, ReadMcpToolPermissions, ReadMemory, ReadMemoryIndex, ReadProjectContext,
ReadSkill, ReadTemplate, RecallMemory, ReconcileLayouts, ReconcileLiveState,
ReconcileLiveStateInput, RecordTurn, RecordTurnProvider, ReferenceProfiles, RenameDevice,
RenameLayout, RenameSprint, ReorderSprints, ResizeTerminal, ResolveAgentPermissions,
ResolveMemoryLinks, RestoreOpenWindows, RetryBackgroundTask, RevokeAllDevices, RevokeDevice,
InspectConversation, InstallPluginFromArchive, InstallPluginFromDirectory,
JsonPluginManifestValidator, LaunchAgent, LaunchAgentInput, LinkIssues, ListAgents,
ListAgentsInput, ListDevices, ListEmbedderProfiles, ListIssues, ListLayouts, ListMemories,
ListModelServers, ListPluginRuntimeContributions, ListPlugins, ListProfiles, ListProjects,
ListResumableAgents, ListSkills, ListSprints, ListTemplates, LiveAgentRegistry, LiveSessions,
LiveStateLeanProvider, LiveStateProvider, LiveStateReadProvider, LoadLayout, McpRuntime,
McpToolPermissionCatalogue, MoveTabToNewWindow, MutateLayout, OnnxModelView, OpenProject,
OpenTerminal, OpenTicketAssistant, OrchestratorService, PairAttemptLimiter, PairDevice,
PermissionProjectorRegistry, ProposeContext, ReadAgentContext, ReadContext,
ReadConversationPage, ReadIssue, ReadIssueCarnet, ReadMcpToolPermissions, ReadMemory,
ReadMemoryIndex, ReadProjectContext, ReadSkill, ReadTemplate, RecallMemory, ReconcileLayouts,
ReconcileLiveState, ReconcileLiveStateInput, ReconcilePluginMcpServers, RecordTurn,
RecordTurnProvider, ReferenceProfiles, RenameDevice, RenameLayout, RenameSprint,
ReorderSprints, ResizeTerminal, ResolveAgentPermissions, ResolveMemoryLinks,
RestoreOpenWindows, RetryBackgroundTask, ReviewPluginPackage, RevokeAllDevices, RevokeDevice,
RotateConversationLog, SaveEmbedderProfile, SaveModelServer, SaveProfile, SessionLimitService,
SetActiveLayout, SnapshotOpenWindows, SnapshotRunningAgents, SpawnBackgroundCommand,
StopLiveAgent, StructuredRoutingMode, StructuredSessions, SuggestedThisSession,
SyncAgentWithTemplate, TerminalSessions, TouchDevice, UnassignSkillFromAgent,
UnassignTicketFromSprint, UnlinkIssues, UpdateAgentContext, UpdateAgentMcpToolPermissions,
UpdateAgentPermissions, UpdateIssue, UpdateIssueCarnet, UpdateLiveState, UpdateMemory,
UpdateProjectContext, UpdateProjectMcpToolPermissions, UpdateProjectPermissions, UpdateSkill,
UpdateTemplate, WakeSessionProvider, WriteMemory, WriteToTerminal, AGENT_MEMORY_RECALL_BUDGET,
SetActiveLayout, SetPluginEnabled, SnapshotOpenWindows, SnapshotRunningAgents,
SpawnBackgroundCommand, StopLiveAgent, StructuredRoutingMode, StructuredSessions,
SuggestedThisSession, SyncAgentWithTemplate, TerminalSessions, TouchDevice,
UnassignSkillFromAgent, UnassignTicketFromSprint, UninstallPlugin, UnlinkIssues,
UpdateAgentContext, UpdateAgentMcpToolPermissions, UpdateAgentPermissions, UpdateIssue,
UpdateIssueCarnet, UpdateLiveState, UpdateMemory, UpdateProjectContext,
UpdateProjectMcpToolPermissions, UpdateProjectPermissions, UpdateSkill, UpdateTemplate,
WakeSessionProvider, WriteMemory, WriteToTerminal, AGENT_MEMORY_RECALL_BUDGET,
};
use async_trait::async_trait;
use domain::ports::{
@ -53,9 +56,10 @@ use domain::ports::{
BackgroundTaskStore, Clock, DeviceSessionStore, Embedder, EmbedderEnvInspector,
EmbedderProfileStore, EmbedderPromptStore, EventBus, FileSystem, GitPort, IdGenerator,
IssueNumberAllocator, IssueStore, McpToolPermissionStore, MemoryRecall, MemoryStore,
PermissionStore, ProcessSpawner, ProfileStore, ProjectStore, PtyPort, ScheduledTask, Scheduler,
SkillStore, SprintStore, StructuredSessionEnvironmentPreparer, TemplateStore, ToolInvoker,
WakeError, WakeReason, WindowStateStore,
PermissionStore, PluginManifestValidator, PluginMcpSupervisor, PluginPackageStore,
PluginRegistryStore, ProcessSpawner, ProfileStore, ProjectStore, PtyPort, ScheduledTask,
Scheduler, SkillStore, SprintStore, StructuredSessionEnvironmentPreparer, TemplateStore,
ToolInvoker, WakeError, WakeReason, WindowStateStore,
};
use domain::profile::{
AgentProfile, ContextInjection, McpConfigStrategy, McpTransport, StructuredAdapter,
@ -73,10 +77,11 @@ use infrastructure::{
embedder_from_profile, AdaptiveMemoryRecall, BackgroundCompletionSink,
BackgroundTaskReadyToDeliver, ClaudePermissionProjector, ClaudeTranscriptInspector,
CliAgentRuntime, CodexPermissionProjector, CommandBackgroundRunner, EmbedderEnvProbe,
FsAssistantContextStore, FsBackgroundTaskStore, FsConversationLog, FsDeviceSessionStore,
FsEmbedderProfileStore, FsEmbedderPromptStore, FsHandoffStore, FsIssueNumberAllocator,
FsIssueStore, FsLiveStateStore, FsMcpToolPermissionStore, FsMemoryStore, FsModelServerRegistry,
FsOrchestratorWatcher, FsPermissionStore, FsProfileStore, FsProjectStore,
ExternalMcpPluginSupervisor, FsAssistantContextStore, FsBackgroundTaskStore, FsConversationLog,
FsDeviceSessionStore, FsEmbedderProfileStore, FsEmbedderPromptStore, FsHandoffStore,
FsIssueNumberAllocator, FsIssueStore, FsLiveStateStore, FsMcpToolPermissionStore,
FsMemoryStore, FsModelServerRegistry, FsOrchestratorWatcher, FsPermissionStore,
FsPluginPackageStore, FsPluginRegistryStore, FsProfileStore, FsProjectStore,
FsProviderSessionStore, FsSkillStore, FsSprintStore, FsTemplateStore, FsWindowStateStore,
Git2Repository, HeuristicHandoffSummarizer, HfModelArtifactDownloader,
HttpOpenAiCompatibleProbe, IdeaiContextStore, InMemoryConversationRegistry, InMemoryMailbox,
@ -1062,6 +1067,29 @@ pub struct BackendCore {
pub retry_background_task: Arc<RetryBackgroundTask>,
/// Store handle used by `list_background_tasks` to read the task read-model.
pub background_task_store: Arc<dyn BackgroundTaskStore>,
// --- Plugins (#43) ---
/// Review a local plugin package before install.
pub review_plugin_package: Arc<ReviewPluginPackage>,
/// Install a plugin archive.
pub install_plugin_from_archive: Arc<InstallPluginFromArchive>,
/// Install a plugin directory snapshot.
pub install_plugin_from_directory: Arc<InstallPluginFromDirectory>,
/// List installed plugins for admin UI.
pub list_plugins: Arc<ListPlugins>,
/// Enable or disable a plugin.
pub set_plugin_enabled: Arc<SetPluginEnabled>,
/// Uninstall a plugin.
pub uninstall_plugin: Arc<UninstallPlugin>,
/// List runtime contributions for UI bootstrap.
pub list_plugin_runtime_contributions: Arc<ListPluginRuntimeContributions>,
/// Reconcile external MCP plugin servers.
pub reconcile_plugin_mcp_servers: Arc<ReconcilePluginMcpServers>,
/// Package store exposed for the Tauri asset protocol adapter.
pub plugin_package_store: Arc<FsPluginPackageStore>,
/// Registry store exposed for the Tauri asset protocol adapter.
pub plugin_registry_store: Arc<dyn PluginRegistryStore>,
/// Manifest validator exposed for the Tauri asset protocol adapter.
pub plugin_manifest_validator: Arc<dyn PluginManifestValidator>,
// --- Templates & sync (L7) ---
/// Create a template in the global store.
pub create_template: Arc<CreateTemplate>,
@ -1233,6 +1261,17 @@ impl BackendCore {
let pair_attempt_limiter_port =
Arc::clone(&pair_attempt_limiter) as Arc<dyn PairAttemptLimiter>;
let events_port = Arc::clone(&event_bus) as Arc<dyn EventBus>;
let plugin_packages = Arc::new(FsPluginPackageStore::new(app_data_dir.clone()));
let plugin_registry = Arc::new(FsPluginRegistryStore::new(app_data_dir.clone()));
let plugin_validator =
Arc::new(JsonPluginManifestValidator::new(env!("CARGO_PKG_VERSION")));
let plugin_mcp_supervisor = Arc::new(ExternalMcpPluginSupervisor::new());
let plugin_package_store = Arc::clone(&plugin_packages) as Arc<dyn PluginPackageStore>;
let plugin_registry_store = Arc::clone(&plugin_registry) as Arc<dyn PluginRegistryStore>;
let plugin_manifest_validator =
Arc::clone(&plugin_validator) as Arc<dyn PluginManifestValidator>;
let plugin_mcp_supervisor_port =
Arc::clone(&plugin_mcp_supervisor) as Arc<dyn PluginMcpSupervisor>;
// --- Use cases (ports injected as Arc<dyn Port>) ---
let health = Arc::new(HealthUseCase::new(
@ -2089,6 +2128,53 @@ impl BackendCore {
Arc::clone(&background_runner) as Arc<dyn BackgroundCommandArchive>,
Arc::clone(&spawn_background_command),
));
let review_plugin_package = Arc::new(ReviewPluginPackage::new(
Arc::clone(&plugin_package_store),
Arc::clone(&plugin_manifest_validator),
));
let list_plugins = Arc::new(ListPlugins::new(
Arc::clone(&plugin_package_store),
Arc::clone(&plugin_registry_store),
Arc::clone(&plugin_manifest_validator),
));
let install_plugin_from_archive = Arc::new(InstallPluginFromArchive::new(
Arc::clone(&plugin_package_store),
Arc::clone(&plugin_registry_store),
Arc::clone(&plugin_manifest_validator),
Arc::clone(&events_port),
Arc::clone(&plugin_mcp_supervisor_port),
));
let install_plugin_from_directory = Arc::new(InstallPluginFromDirectory::new(
Arc::clone(&plugin_package_store),
Arc::clone(&plugin_registry_store),
Arc::clone(&plugin_manifest_validator),
Arc::clone(&events_port),
Arc::clone(&plugin_mcp_supervisor_port),
));
let set_plugin_enabled = Arc::new(SetPluginEnabled::new(
Arc::clone(&plugin_package_store),
Arc::clone(&plugin_registry_store),
Arc::clone(&plugin_manifest_validator),
Arc::clone(&events_port),
Arc::clone(&plugin_mcp_supervisor_port),
));
let uninstall_plugin = Arc::new(UninstallPlugin::new(
Arc::clone(&plugin_package_store),
Arc::clone(&plugin_registry_store),
Arc::clone(&events_port),
Arc::clone(&plugin_mcp_supervisor_port),
));
let list_plugin_runtime_contributions = Arc::new(ListPluginRuntimeContributions::new(
Arc::clone(&plugin_package_store),
Arc::clone(&plugin_registry_store),
Arc::clone(&plugin_manifest_validator),
));
let reconcile_plugin_mcp_servers = Arc::new(ReconcilePluginMcpServers::new(
Arc::clone(&plugin_package_store),
Arc::clone(&plugin_registry_store),
Arc::clone(&plugin_manifest_validator),
Arc::clone(&plugin_mcp_supervisor_port),
));
let background_wake = Arc::new(AgentWakeService::new(
Arc::clone(&mediated_inbox) as Arc<dyn AgentInbox>,
Arc::clone(&input_mediator),
@ -2613,6 +2699,17 @@ impl BackendCore {
cancel_background_task,
retry_background_task,
background_task_store: Arc::clone(&background_tasks_port),
review_plugin_package,
install_plugin_from_archive,
install_plugin_from_directory,
list_plugins,
set_plugin_enabled,
uninstall_plugin,
list_plugin_runtime_contributions,
reconcile_plugin_mcp_servers,
plugin_package_store: Arc::clone(&plugin_packages),
plugin_registry_store: Arc::clone(&plugin_registry_store),
plugin_manifest_validator: Arc::clone(&plugin_manifest_validator),
ticket_tool_binder,
template_tool_binder,
}