merge(sdk): fix #329 — feedbacks menu host génériques et doc SDK alignée (QA verte: npm run check, git diff --check) — docs only, aucun push
This commit is contained in:
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user