Les contributions runtime des plugins (menus, slash commands, layouts, surfaces) ne sont exposées que dans les projets liés au plugin. - Définition du lien: ProjectPluginSettingsStore par racine projet (domaine) — une contribution runtime-active n'entre dans le catalogue que si elle est explicitement activée pour le projet courant; hors projet focalisé, catalogue vide - Application: ListPluginRuntimeContributions.execute prend un project_id optionnel, charge projet + settings et filtre le registre par activation projet; tests fake store/settings (catalogue vide sans projet, activation, layout, slash commands) - Backend/app-tauri: plugin_list_runtime_contributions et slash commands list/execute acceptent projectId optionnel (DTO camelCase, défaut serde), BackendCore recâblé avec store_port et project_plugin_settings_store; test DTO de scope optionnel - Frontend: PluginGateway.listRuntimeContributions(projectId) (ports, tauri, http/unsupported, mock alignés); PluginRuntimeProvider re-scope le catalogue au changement de focus projet (vidage du registre précédent, disposition des bundles, requêtes obsolètes ignorées par projectId/révision); PluginLayoutCellView ignore les références de layout devenues hors périmètre via onChooseAnotherLayout et ne rend rien pendant le rechargement (aucune fuite inter-projets) - Tests: plugin_install_load (infrastructure), dto slash commands, plugin.test, PluginRuntimeProvider.test, PluginLayoutCellView.test QA verte sur feature/321-plugin-contributions-linked-projects. Aucun push.
107 lines
3.6 KiB
TypeScript
107 lines
3.6 KiB
TypeScript
/**
|
|
* Tauri adapter for {@link PluginGateway} (ticket #43, F1).
|
|
*
|
|
* Commands use snake_case (Tauri convention); payload keys are camelCase,
|
|
* consistent with the other adapters in this directory. Command names and
|
|
* envelope match the carnet §5 exactly — no contract improvised here.
|
|
*
|
|
* NOTE: The Tauri commands wired here are defined in the backend `app-tauri`
|
|
* crate (lots B1-B4, in progress in parallel on this branch). The mock gateway
|
|
* covers tests and offline dev today.
|
|
*/
|
|
|
|
import { invoke } from "@tauri-apps/api/core";
|
|
|
|
import type {
|
|
PluginAdmin,
|
|
PluginInstallResult,
|
|
PluginReview,
|
|
PluginRuntimeContributionCatalog,
|
|
ProjectPluginSettings,
|
|
ProjectPluginSettingsView,
|
|
PluginUninstallResult,
|
|
} from "@/domain";
|
|
import type {
|
|
MutateAgentPluginSkillInput,
|
|
MutateAgentPluginToolInput,
|
|
PluginGateway,
|
|
ReviewPluginPackageInput,
|
|
SetProjectPluginEnabledInput,
|
|
} from "@/ports";
|
|
|
|
type TauriPluginReviewDto = Omit<PluginReview, "issues" | "installable"> & {
|
|
issues?: PluginReview["issues"];
|
|
installable?: boolean;
|
|
};
|
|
|
|
function normalizeReview(review: TauriPluginReviewDto): PluginReview {
|
|
return {
|
|
...review,
|
|
issues: review.issues ?? [],
|
|
installable: review.installable ?? true,
|
|
};
|
|
}
|
|
|
|
export class TauriPluginGateway implements PluginGateway {
|
|
listPlugins(): Promise<PluginAdmin[]> {
|
|
return invoke<PluginAdmin[]>("plugin_list_plugins");
|
|
}
|
|
|
|
async reviewPackage(input: ReviewPluginPackageInput): Promise<PluginReview> {
|
|
const review = await invoke<TauriPluginReviewDto>("plugin_review_package", {
|
|
input: { sourceKind: input.sourceKind, path: input.path },
|
|
});
|
|
return normalizeReview(review);
|
|
}
|
|
|
|
installFromArchive(path: string): Promise<PluginInstallResult> {
|
|
return invoke<PluginInstallResult>("plugin_install_from_archive", { path });
|
|
}
|
|
|
|
installFromDirectory(path: string): Promise<PluginInstallResult> {
|
|
return invoke<PluginInstallResult>("plugin_install_from_directory", { path });
|
|
}
|
|
|
|
setEnabled(pluginId: string, enabled: boolean): Promise<PluginAdmin> {
|
|
return invoke<PluginAdmin>("plugin_set_enabled", { pluginId, enabled });
|
|
}
|
|
|
|
uninstall(pluginId: string): Promise<PluginUninstallResult> {
|
|
return invoke<PluginUninstallResult>("plugin_uninstall", { pluginId });
|
|
}
|
|
|
|
listRuntimeContributions(projectId?: string): Promise<PluginRuntimeContributionCatalog> {
|
|
return invoke<PluginRuntimeContributionCatalog>("plugin_list_runtime_contributions", {
|
|
projectId: projectId ?? null,
|
|
});
|
|
}
|
|
|
|
listProjectSettings(projectId: string): Promise<ProjectPluginSettingsView> {
|
|
return invoke<ProjectPluginSettingsView>("plugin_list_project_settings", { projectId });
|
|
}
|
|
|
|
setProjectEnabled(input: SetProjectPluginEnabledInput): Promise<ProjectPluginSettings> {
|
|
return invoke<ProjectPluginSettings>("plugin_set_project_enabled", { input });
|
|
}
|
|
|
|
assignAgentSkill(input: MutateAgentPluginSkillInput): Promise<ProjectPluginSettings> {
|
|
return invoke<ProjectPluginSettings>("plugin_assign_agent_skill", { input });
|
|
}
|
|
|
|
unassignAgentSkill(input: MutateAgentPluginSkillInput): Promise<ProjectPluginSettings> {
|
|
return invoke<ProjectPluginSettings>("plugin_unassign_agent_skill", { input });
|
|
}
|
|
|
|
assignAgentTool(input: MutateAgentPluginToolInput): Promise<ProjectPluginSettings> {
|
|
return invoke<ProjectPluginSettings>("plugin_assign_agent_tool", { input });
|
|
}
|
|
|
|
unassignAgentTool(input: MutateAgentPluginToolInput): Promise<ProjectPluginSettings> {
|
|
return invoke<ProjectPluginSettings>("plugin_unassign_agent_tool", { input });
|
|
}
|
|
|
|
async openPluginsFolder(pluginId?: string): Promise<void> {
|
|
await invoke("plugin_open_plugins_folder", { pluginId: pluginId ?? null });
|
|
}
|
|
}
|