fix(permissions): tools MCP inter-projets exposés (idea_project_*) + contactable agent/template persisté — update_agent_contactable (application/web-server/app-tauri), defaultContactable TemplateEditor save/reopen, groupes MCP 'IdeA inter-projets' avec fallback, permissions agent Contactable — #267 (QA verte)

This commit is contained in:
2026-09-07 18:13:27 +02:00
parent 9266d121cd
commit f6101a8249
30 changed files with 632 additions and 89 deletions

View File

@ -1,3 +1,5 @@
import type { McpToolCatalogue } from "@/domain";
/**
* Presentational grouping of the MCP tool catalogue (ticket #82).
*
@ -15,6 +17,17 @@ export interface McpToolGroupDef {
/** Domain groups, in display order (carnet #82 — Conception UX/F). */
export const MCP_TOOL_GROUPS: McpToolGroupDef[] = [
{
id: "crossProject",
label: "IdeA inter-projets",
tools: [
"idea_project_list",
"idea_project_read_context",
"idea_project_list_agents",
"idea_project_ask_agent",
"idea_project_cancel_agent",
],
},
{
id: "readProject",
label: "Lecture projet",
@ -78,6 +91,11 @@ export const MCP_TOOL_GROUPS: McpToolGroupDef[] = [
/** Short, human French label per exact MCP tool name. */
export const MCP_TOOL_LABELS: Record<string, string> = {
idea_project_list: "Lister les projets IdeA",
idea_project_read_context: "Lire le contexte d'un autre projet",
idea_project_list_agents: "Lister les agents d'un autre projet",
idea_project_ask_agent: "Demander à un agent d'un autre projet",
idea_project_cancel_agent: "Annuler une demande inter-projet",
idea_list_agents: "Lister les agents",
idea_context_read: "Lire le contexte d'un agent",
idea_memory_read: "Lire la mémoire projet",
@ -115,3 +133,27 @@ export function mcpToolLabel(tool: string): string {
export function mcpToolGroupId(tool: string): string | undefined {
return MCP_TOOL_GROUPS.find((group) => group.tools.includes(tool))?.id;
}
/**
* Builds the exhaustive presentation groups from the backend catalogue.
* Local groups only choose placement/labels; every catalogued tool remains
* configurable, with unmapped names collected under the visible fallback.
*/
export function mcpToolGroupsForCatalogue(
catalogue: McpToolCatalogue,
): McpToolGroupDef[] {
const catalogued = Array.from(
new Set([...catalogue.readOnlyTools, ...catalogue.writeActionTools]),
);
const cataloguedSet = new Set(catalogued);
const mapped = new Set<string>();
const groups = MCP_TOOL_GROUPS.flatMap((group) => {
const tools = group.tools.filter((tool) => cataloguedSet.has(tool));
tools.forEach((tool) => mapped.add(tool));
return tools.length > 0 ? [{ ...group, tools }] : [];
});
const otherTools = catalogued.filter((tool) => !mapped.has(tool));
return otherTools.length > 0
? [...groups, { id: "other", label: "Autres", tools: otherTools }]
: groups;
}