feat(frontend): système de plugins — runtime, menus, layouts custom (#43)

Lots F1-F4 : runtime de chargement/registre plugin, extension des menus
existants, panneau de gestion des plugins, types de layout custom
(sélecteur, fallback, cellule dédiée) branchés sur le port plugin.
Suite npm typecheck/test verte (947/947).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 07:37:11 +02:00
parent bb35641715
commit ac726d075e
41 changed files with 3245 additions and 24 deletions

View File

@ -39,6 +39,12 @@ import type {
PairedDevice,
PairingCode,
PermissionSet,
PluginAdmin,
PluginInstallResult,
PluginReview,
PluginRuntimeContributionCatalog,
PluginSourceKind,
PluginUninstallResult,
ProjectMcpToolPermissions,
PageDirection,
Project,
@ -77,6 +83,12 @@ export interface SystemGateway {
* sites go through this port; the Tauri plugin is only imported in the adapter.
*/
pickFolder(): Promise<string | null>;
/**
* Opens a native file picker for a single local archive (plugin install from
* archive, carnet §1.4/§9) and returns the chosen path, or `null` if the user
* cancelled. Same sanctioned-picker rule as {@link pickFolder}.
*/
pickArchiveFile(): Promise<string | null>;
/**
* Subscribes to the app-exit work-in-progress guard (ticket #83): fired when
* closing the main window is intercepted because it would interrupt active
@ -1175,6 +1187,28 @@ export interface UiPreferencesGateway {
* The full set of gateways the app depends on, injected via the DI provider.
* The composition (real vs mock) is chosen in `app/`.
*/
/** Input to `reviewPackage` — a candidate package not yet committed to the store. */
export interface ReviewPluginPackageInput {
sourceKind: PluginSourceKind;
path: string;
}
/**
* Plugin system gateway (ticket #43, F1) — admin CRUD + the bootstrap catalog
* the runtime loader consumes. Mirrors the Tauri commands in carnet §5
* (`plugin_*`); no DTO shape is re-derived here beyond what the carnet froze.
*/
export interface PluginGateway {
listPlugins(): Promise<PluginAdmin[]>;
reviewPackage(input: ReviewPluginPackageInput): Promise<PluginReview>;
installFromArchive(path: string): Promise<PluginInstallResult>;
installFromDirectory(path: string): Promise<PluginInstallResult>;
setEnabled(pluginId: string, enabled: boolean): Promise<PluginAdmin>;
uninstall(pluginId: string): Promise<PluginUninstallResult>;
listRuntimeContributions(): Promise<PluginRuntimeContributionCatalog>;
openPluginsFolder(pluginId?: string): Promise<void>;
}
export interface Gateways {
system: SystemGateway;
agent: AgentGateway;
@ -1199,4 +1233,5 @@ export interface Gateways {
window: WindowGateway;
focusedProject: FocusedProjectGateway;
uiPreferences: UiPreferencesGateway;
plugin: PluginGateway;
}