From 32d33b330f95f4340e27278f16eff1f523d2f004 Mon Sep 17 00:00:00 2001 From: Blomios Date: Sat, 19 Sep 2026 00:33:57 +0200 Subject: [PATCH] =?UTF-8?q?docs(sdk):=20feedbacks=20menu=20host=20g=C3=A9n?= =?UTF-8?q?=C3=A9riques=20=E2=80=94=20#329=20;=20README=20+=20docs=20comma?= =?UTF-8?q?nds-and-feedback/menus/services=20:=20failed/skipped=20sans=20m?= =?UTF-8?q?essage=20Git=20cod=C3=A9=20en=20dur=20ni=20payload=20brut,=20op?= =?UTF-8?q?ened/alreadyOpen=20succ=C3=A8s=20silencieux,=20logs=20host=20pl?= =?UTF-8?q?uginId/commandId/status/reason/message,=20vue=20de=20diagnostic?= =?UTF-8?q?=20reste=20accessible=20quand=20Git/ADB/Gradle=20ou=20autre=20o?= =?UTF-8?q?util=20optionnel=20manque,=20workspace.execTool=20rappel=C3=A9?= =?UTF-8?q?=20;=20QA=20verte=20:=20npm=20run=20check,=20git=20diff=20--che?= =?UTF-8?q?ck?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++++ docs/commands-and-feedback.md | 34 ++++++++++++++++++++++++++++------ docs/menus.md | 14 ++++++++++++-- docs/services.md | 7 +++++++ 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index bda7292..2481810 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,12 @@ For short project-scoped external tools, use [Manifest](docs/manifest.md). The primitive is generic and does not expose a native Git/SCM API. +Menu commands that open or focus a plugin view return `status: "opened"` +(including `alreadyOpen: true`) and remain UI-silent on success. Keep diagnostic +views accessible when optional tools are missing, and use the structured +`skipped`/`failed` feedback contract for genuinely impossible actions; see +[Commands And Feedback](docs/commands-and-feedback.md) and [Menus](docs/menus.md). + ## Install ```sh diff --git a/docs/commands-and-feedback.md b/docs/commands-and-feedback.md index 41819ed..abaddf8 100644 --- a/docs/commands-and-feedback.md +++ b/docs/commands-and-feedback.md @@ -1,7 +1,7 @@ # Commands And Feedback -This document is the normative SDK contract for plugin commands that may launch -background work. +This document is the normative SDK contract for plugin commands, including +commands that open a view or launch background work. ## Contract @@ -26,14 +26,16 @@ manifest contribution -> command id -> registered command handler -> optional ta - Feedback objects must be stable enough for agents and programmatic callers to parse, and their messages must be readable by humans. - The human menu-click UI presents minimal host-owned feedback for `skipped` - and `failed` results. It intentionally does not expose the raw result payload. + and `failed` results. It intentionally does not expose the raw result payload + or assume which tool (Git, ADB, Gradle, and so on) the plugin uses. For successful actions and richer status, open or focus a plugin layout/window from the handler with `ctx.services.windows.open({ layoutType, state })`. ## Preconditions -Check preconditions before calling `runCommand()`: +Check preconditions before calling `runCommand()`. These are task-launch +preconditions, not prerequisites for opening an explanatory view: - `ctx.services` exists. Plugins need the `ui` or `tooling` capability for the service facade. @@ -50,6 +52,12 @@ Check preconditions before calling `runCommand()`: - Do not use `ctx.pluginRoot` as `cwd`; `cwd` remains relative to the project root. - `command` and `args` are separate values. Do not shell-join user input. +A command whose purpose is to open or focus a diagnostic/configuration view +should call `services.windows.open(...)` before probing optional executables. +Missing Git, ADB, Gradle, or another tool must not block that view when the view +can explain the degraded state and the next step. Probe tools from the view (or +from its data loader) and render the degraded state there. + If any required precondition fails, return a skipped result: ```ts @@ -67,21 +75,30 @@ with equivalent fields: ```ts type CommandFeedback = + | { status: "opened"; message?: string; alreadyOpen: boolean } | { status: "skipped"; reason: string; message: string } + | { status: "failed"; reason?: string; message?: string } | { status: "launched"; taskId: string; state: string; message: string }; ``` Use the same `status` vocabulary consistently: +- `opened`: the requested view was opened or focused. `alreadyOpen: true` is a + successful focus operation, not a failure or skip. - `skipped`: no background task was created. - `launched`: a task was created; inspect the task state for later progress. -- `failed`: the handler itself failed before it could return normally. +- `failed`: the handler caught a failure and returned structured failure + feedback. An uncaught/rejected handler is also treated as a failure by the + host. Visible surfaces are intentionally distinct: - Command return value: immediate feedback for programmatic callers and agents. The human menu host maps `skipped` and `failed` results to concise feedback; - plugin-specific fields and messages are not displayed verbatim. + plugin-specific fields and messages are not displayed verbatim. `opened` + results, including `alreadyOpen: true`, succeed without an alert. The host + logs structured diagnostics with `pluginId`, `commandId`, `status`, `reason` + and `message`; raw objects, stack traces and internal ids are not user-facing. - Plugin layout/window: the normative visible feedback surface for menu actions that need to show status, results or next steps to a human. The layout must be declared in `idea-plugin.json` and registered during activation. @@ -146,6 +163,11 @@ const plugin: IdeAPluginModule = { export default plugin; ``` +The `opened` branch above must remain successful even when an optional tool +diagnosed by `HealthView` is absent. If `windows.open(...)` itself rejects, log +the technical cause and either let the promise reject or return `failed`; the +host will show generic, plugin-neutral feedback rather than the raw message. + Background task feedback: ```ts diff --git a/docs/menus.md b/docs/menus.md index 12bac33..0b72e45 100644 --- a/docs/menus.md +++ b/docs/menus.md @@ -33,7 +33,10 @@ Then register the command id: ```ts export function activate(ctx: ActivateContext): void { const disposable = ctx.commands?.registerCommand("hello-plugin.open", async () => { - await ctx.services?.windows.open({ layoutType: "hello-plugin.dashboard" }); + const win = await ctx.services?.windows.open({ layoutType: "hello-plugin.dashboard" }); + return win + ? { status: "opened", alreadyOpen: win.alreadyOpen } + : { status: "skipped", reason: "ui-service-unavailable", message: "UI service unavailable." }; }); if (disposable) ctx.subscriptions.push(disposable); } @@ -47,9 +50,16 @@ export function activate(ctx: ActivateContext): void { - A missing command handler is surfaced by the host as a retryable reload error; menu clicks must never fail silently. - A registered handler's rejected promise is not swallowed: the host logs the - plugin id, command id and reason, then presents a retryable error. In + plugin id, command id, status, reason and message, then presents a generic + retryable error without raw payloads. In particular, return/await `services.windows.open(...)` so native-window failures follow this path. +- An open/focus handler returns `status: "opened"` whether `alreadyOpen` is + `false` (new window) or `true` (existing window focused). Neither success + produces an alert. +- Keep diagnostic views reachable when optional executables such as Git, ADB or + Gradle are missing. Let the view explain that degraded state instead of + skipping the menu action before opening it. - A handler owns precondition checks and feedback. See [Commands And Feedback](commands-and-feedback.md). - Menu item `when` expressions are evaluated by the host; unsupported or false diff --git a/docs/services.md b/docs/services.md index 2872bc3..a26b083 100644 --- a/docs/services.md +++ b/docs/services.md @@ -125,6 +125,13 @@ locations. Use it for configuration the user expects to review/version. one of the calling plugin's declared layout contributions. See [Windows](windows.md). +Resolving this promise means the window was opened or focused. Its +`alreadyOpen` flag reports which happened; both outcomes are successful and a +menu handler should return `status: "opened"`. Do not gate a diagnostic window +on optional tool availability when that window can present the unavailable +state. A rejection means the window operation itself was impossible and may be +logged or returned as `status: "failed"`; do not expose its raw error to users. + ## Scheduled tasks Project scheduled tasks are exposed through native Tauri/HTTP commands and the