feat(plugins): seam slash-commands contribuées par plugin via callback — #165 (QA verte)

Permet à un plugin de contribuer des commandes slash adossées à une callback,
transitant par le registry/contrat unifié (#162) :

- sdk/IdeaSDK: manifeste contributes.slashCommands (déclaratif) — pointer bumpé.
- domain: source Plugin étendue + effet PluginCallback (la commande ne
  s'exécute pas directement : elle renvoie une référence à la callback du plugin).
- application: registration des commandes plugin dans le registry + exécution
  renvoyant l'effet PluginCallback ; métadonnées UI suffisantes pour l'autocomplete.
- backend + app-tauri: DTO + commandes Tauri listant/invoquant les commandes plugin.
- frontend (contrat): types adapters/domain/ports/mock pour pluginCallback et
  l'invocation avec arguments.

L'exécution effective de la callback côté runtime UI est livrée par #166.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-06 15:46:52 +02:00
parent ff7696b724
commit fbaca9d5cc
17 changed files with 514 additions and 34 deletions

View File

@ -38,6 +38,8 @@ pub struct PluginContributionSummaryDto {
pub top_level_menus: usize,
/// Menu items count.
pub menu_items: usize,
/// Slash commands count.
pub slash_commands: usize,
/// Layouts count.
pub layouts: usize,
/// MCP servers count.
@ -49,6 +51,7 @@ impl From<application::PluginContributionSummary> for PluginContributionSummaryD
Self {
top_level_menus: value.top_level_menus,
menu_items: value.menu_items,
slash_commands: value.slash_commands,
layouts: value.layouts,
mcp_servers: value.mcp_servers,
}
@ -803,6 +806,9 @@ pub struct ExecuteSlashCommandRequestDto {
/// conversation-local commands.
#[serde(default)]
pub session_id: Option<String>,
/// Opaque arguments forwarded to plugin callbacks.
#[serde(default)]
pub arguments: Vec<serde_json::Value>,
}
/// Slash-command execution response DTO.
@ -848,6 +854,21 @@ pub enum SlashCommandEffectDto {
#[serde(rename = "sessionId")]
session_id: String,
},
/// Dispatch to a plugin-owned SDK command callback.
PluginCallback {
/// Plugin id owning the callback.
#[serde(rename = "pluginId")]
plugin_id: String,
/// SDK command callback id registered by the plugin.
#[serde(rename = "commandId")]
command_id: String,
/// Current structured chat session, when available.
#[serde(default, rename = "sessionId", skip_serializing_if = "Option::is_none")]
session_id: Option<String>,
/// Opaque arguments supplied by the caller.
#[serde(default)]
arguments: Vec<serde_json::Value>,
},
}
impl From<SlashCommandEffect> for SlashCommandEffectDto {
@ -861,6 +882,17 @@ impl From<SlashCommandEffect> for SlashCommandEffectDto {
SlashCommandEffect::ProfileSwitch { session_id } => Self::ProfileSwitch {
session_id: session_id.to_string(),
},
SlashCommandEffect::PluginCallback {
plugin_id,
command_id,
session_id,
arguments,
} => Self::PluginCallback {
plugin_id,
command_id,
session_id: session_id.map(|id| id.to_string()),
arguments,
},
}
}
}