feat(plugins): paramètres projet plugins + attribution skills/tools aux agents — #282 (manifeste accepte contributes.skills IdeA-native multi-harness; store .ideai/project-plugins.json v1: enable plugin par projet + assignments skills/tools par agent; refs + use cases settings/assign/unassign; resolver skills pour idea_skill_read et injection catalogue lancement agent; permissions MCP dynamiques projetées par harness Claude Code/Codex/OpenCode; tombstones uninstall, hot reload recalcule catalogue et marque assignments cassés; frontend: Settings projet Plugins, détail capabilities, attribution agent, catalogue permissions; bump pointeur IdeaSDK 6eb8db3; QA verte: cargo test -p application, project_plugin_settings 3/3, dto_plugins 2/2, structured_launch_d3 26/26, catalogue mcp 7/7, frontend 5 tests ProjectPluginSettings/plugin, npm build frontend)
This commit is contained in:
@ -3,19 +3,24 @@
|
||||
use std::future::Future;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use application::{ReviewPluginPackageInput, SetPluginEnabledInput, UninstallPluginInput};
|
||||
use application::{
|
||||
plugin_skill_ref, plugin_tool_ref, AppError, AssignmentMutation, ReviewPluginPackageInput,
|
||||
SetPluginEnabledInput, UninstallPluginInput,
|
||||
};
|
||||
use backend::dto::{
|
||||
ErrorDto, PluginAdminDto, PluginConfigDocumentDto, PluginConfigDocumentReadDto,
|
||||
PluginConfigDocumentUpdateDto, PluginConfigDocumentWriteResultDto, PluginEventBatchDto,
|
||||
PluginEventPollDto, PluginEventSubscribeDto, PluginEventSubscriptionDto,
|
||||
parse_agent_id, parse_project_id, ErrorDto, MutateAgentPluginSkillRequestDto,
|
||||
MutateAgentPluginToolRequestDto, PluginAdminDto, PluginConfigDocumentDto,
|
||||
PluginConfigDocumentReadDto, PluginConfigDocumentUpdateDto, PluginConfigDocumentWriteResultDto,
|
||||
PluginEventBatchDto, PluginEventPollDto, PluginEventSubscribeDto, PluginEventSubscriptionDto,
|
||||
PluginEventUnsubscribeDto, PluginInstallResultDto, PluginProjectStructureDto,
|
||||
PluginProjectStructureQueryDto, PluginReloadResultDto, PluginReviewDto, PluginRunCommandDto,
|
||||
PluginRuntimeContributionCatalogDto, PluginStorageGetDto, PluginStorageSetDto, PluginTaskDto,
|
||||
PluginTaskStatusDto, PluginToolchainDiagnosticDto, PluginToolchainDiagnosticRequestDto,
|
||||
PluginUninstallResultDto, PluginWorkspaceBinaryFileDto, PluginWorkspaceDirectoryListingDto,
|
||||
PluginWorkspacePathDto, PluginWorkspaceStatDto, PluginWorkspaceTextFileDto,
|
||||
PluginWorkspaceWriteBinaryDto, PluginWorkspaceWriteTextDto, ReloadPluginDto,
|
||||
ReviewPluginPackageDto,
|
||||
PluginWorkspaceWriteBinaryDto, PluginWorkspaceWriteTextDto, ProjectPluginSettingsDto,
|
||||
ProjectPluginSettingsViewDto, ReloadPluginDto, ReviewPluginPackageDto,
|
||||
SetProjectPluginEnabledRequestDto,
|
||||
};
|
||||
use domain::ports::{PluginManifestValidator, PluginPackageStore, PluginRegistryStore};
|
||||
use domain::{PluginId, RelativePath};
|
||||
@ -27,6 +32,14 @@ use crate::state::AppState;
|
||||
const PLUGIN_ASSET_CORS_ORIGIN: &str = "*";
|
||||
const PLUGIN_ASSET_CORS_METHODS: &str = "GET";
|
||||
|
||||
async fn resolve_project(state: &AppState, project_id: &str) -> Result<domain::Project, ErrorDto> {
|
||||
state
|
||||
.project_store
|
||||
.load_project(parse_project_id(project_id)?)
|
||||
.await
|
||||
.map_err(|error| ErrorDto::from(AppError::from(error)))
|
||||
}
|
||||
|
||||
/// Lists installed plugins for the admin surface.
|
||||
#[tauri::command]
|
||||
pub async fn plugin_list_plugins(
|
||||
@ -40,6 +53,107 @@ pub async fn plugin_list_plugins(
|
||||
.map_err(ErrorDto::from)
|
||||
}
|
||||
|
||||
/// Lists project plugin activation, assignments, and installed manifests.
|
||||
#[tauri::command]
|
||||
pub async fn plugin_list_project_settings(
|
||||
project_id: String,
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<ProjectPluginSettingsViewDto, ErrorDto> {
|
||||
let project = resolve_project(&state, &project_id).await?;
|
||||
state
|
||||
.list_project_plugin_settings
|
||||
.execute(project)
|
||||
.await
|
||||
.map(ProjectPluginSettingsViewDto::from)
|
||||
.map_err(ErrorDto::from)
|
||||
}
|
||||
|
||||
/// Enables or disables an installed plugin for one project.
|
||||
#[tauri::command]
|
||||
pub async fn plugin_set_project_enabled(
|
||||
input: SetProjectPluginEnabledRequestDto,
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<ProjectPluginSettingsDto, ErrorDto> {
|
||||
let project = resolve_project(&state, &input.project_id).await?;
|
||||
let plugin_id =
|
||||
PluginId::new(input.plugin_id).map_err(|error| ErrorDto::invalid(error.to_string()))?;
|
||||
state
|
||||
.set_project_plugin_enabled
|
||||
.execute(project, plugin_id, input.enabled)
|
||||
.await
|
||||
.map(ProjectPluginSettingsDto::from)
|
||||
.map_err(ErrorDto::from)
|
||||
}
|
||||
|
||||
async fn mutate_project_skill(
|
||||
input: MutateAgentPluginSkillRequestDto,
|
||||
mutation: AssignmentMutation,
|
||||
state: &AppState,
|
||||
) -> Result<ProjectPluginSettingsDto, ErrorDto> {
|
||||
let project = resolve_project(state, &input.project_id).await?;
|
||||
let agent_id = parse_agent_id(&input.agent_id)?;
|
||||
let reference = plugin_skill_ref(input.plugin_id, input.skill_id).map_err(ErrorDto::from)?;
|
||||
state
|
||||
.mutate_agent_plugin_skill
|
||||
.execute(project, agent_id, reference, mutation)
|
||||
.await
|
||||
.map(ProjectPluginSettingsDto::from)
|
||||
.map_err(ErrorDto::from)
|
||||
}
|
||||
|
||||
/// Assigns a contributed plugin skill to a project agent.
|
||||
#[tauri::command]
|
||||
pub async fn plugin_assign_agent_skill(
|
||||
input: MutateAgentPluginSkillRequestDto,
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<ProjectPluginSettingsDto, ErrorDto> {
|
||||
mutate_project_skill(input, AssignmentMutation::Assign, &state).await
|
||||
}
|
||||
|
||||
/// Unassigns a contributed plugin skill from a project agent.
|
||||
#[tauri::command]
|
||||
pub async fn plugin_unassign_agent_skill(
|
||||
input: MutateAgentPluginSkillRequestDto,
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<ProjectPluginSettingsDto, ErrorDto> {
|
||||
mutate_project_skill(input, AssignmentMutation::Unassign, &state).await
|
||||
}
|
||||
|
||||
async fn mutate_project_tool(
|
||||
input: MutateAgentPluginToolRequestDto,
|
||||
mutation: AssignmentMutation,
|
||||
state: &AppState,
|
||||
) -> Result<ProjectPluginSettingsDto, ErrorDto> {
|
||||
let project = resolve_project(state, &input.project_id).await?;
|
||||
let agent_id = parse_agent_id(&input.agent_id)?;
|
||||
let reference = plugin_tool_ref(input.plugin_id, input.server_id, input.tool_name)
|
||||
.map_err(ErrorDto::from)?;
|
||||
state
|
||||
.mutate_agent_plugin_tool
|
||||
.execute(project, agent_id, reference, mutation)
|
||||
.await
|
||||
.map(ProjectPluginSettingsDto::from)
|
||||
.map_err(ErrorDto::from)
|
||||
}
|
||||
|
||||
/// Assigns a namespaced plugin MCP tool to a project agent.
|
||||
#[tauri::command]
|
||||
pub async fn plugin_assign_agent_tool(
|
||||
input: MutateAgentPluginToolRequestDto,
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<ProjectPluginSettingsDto, ErrorDto> {
|
||||
mutate_project_tool(input, AssignmentMutation::Assign, &state).await
|
||||
}
|
||||
|
||||
/// Unassigns a namespaced plugin MCP tool from a project agent.
|
||||
#[tauri::command]
|
||||
pub async fn plugin_unassign_agent_tool(
|
||||
input: MutateAgentPluginToolRequestDto,
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<ProjectPluginSettingsDto, ErrorDto> {
|
||||
mutate_project_tool(input, AssignmentMutation::Unassign, &state).await
|
||||
}
|
||||
|
||||
/// Reviews a local plugin package without committing it.
|
||||
#[tauri::command]
|
||||
pub async fn plugin_review_package(
|
||||
|
||||
Reference in New Issue
Block a user