docs(sdk): feedbacks menu host génériques — #329 ; README + docs commands-and-feedback/menus/services : failed/skipped sans message Git codé en dur ni payload brut, opened/alreadyOpen succès silencieux, logs host pluginId/commandId/status/reason/message, vue de diagnostic reste accessible quand Git/ADB/Gradle ou autre outil optionnel manque, workspace.execTool rappelé ; QA verte : npm run check, git diff --check
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
|
[Manifest](docs/manifest.md). The primitive is generic and does not expose a
|
||||||
native Git/SCM API.
|
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
|
## Install
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Commands And Feedback
|
# Commands And Feedback
|
||||||
|
|
||||||
This document is the normative SDK contract for plugin commands that may launch
|
This document is the normative SDK contract for plugin commands, including
|
||||||
background work.
|
commands that open a view or launch background work.
|
||||||
|
|
||||||
## Contract
|
## 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
|
- Feedback objects must be stable enough for agents and programmatic callers to
|
||||||
parse, and their messages must be readable by humans.
|
parse, and their messages must be readable by humans.
|
||||||
- The human menu-click UI presents minimal host-owned feedback for `skipped`
|
- 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
|
For successful actions and richer status, open or focus a plugin layout/window
|
||||||
from the handler with
|
from the handler with
|
||||||
`ctx.services.windows.open({ layoutType, state })`.
|
`ctx.services.windows.open({ layoutType, state })`.
|
||||||
|
|
||||||
## Preconditions
|
## 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
|
- `ctx.services` exists. Plugins need the `ui` or `tooling` capability for the
|
||||||
service facade.
|
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.
|
- 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.
|
- `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:
|
If any required precondition fails, return a skipped result:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
@ -67,21 +75,30 @@ with equivalent fields:
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
type CommandFeedback =
|
type CommandFeedback =
|
||||||
|
| { status: "opened"; message?: string; alreadyOpen: boolean }
|
||||||
| { status: "skipped"; reason: string; message: string }
|
| { status: "skipped"; reason: string; message: string }
|
||||||
|
| { status: "failed"; reason?: string; message?: string }
|
||||||
| { status: "launched"; taskId: string; state: string; message: string };
|
| { status: "launched"; taskId: string; state: string; message: string };
|
||||||
```
|
```
|
||||||
|
|
||||||
Use the same `status` vocabulary consistently:
|
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.
|
- `skipped`: no background task was created.
|
||||||
- `launched`: a task was created; inspect the task state for later progress.
|
- `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:
|
Visible surfaces are intentionally distinct:
|
||||||
|
|
||||||
- Command return value: immediate feedback for programmatic callers and agents.
|
- Command return value: immediate feedback for programmatic callers and agents.
|
||||||
The human menu host maps `skipped` and `failed` results to concise feedback;
|
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
|
- 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
|
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.
|
declared in `idea-plugin.json` and registered during activation.
|
||||||
@ -146,6 +163,11 @@ const plugin: IdeAPluginModule = {
|
|||||||
export default plugin;
|
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:
|
Background task feedback:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
|
|||||||
@ -33,7 +33,10 @@ Then register the command id:
|
|||||||
```ts
|
```ts
|
||||||
export function activate(ctx: ActivateContext): void {
|
export function activate(ctx: ActivateContext): void {
|
||||||
const disposable = ctx.commands?.registerCommand("hello-plugin.open", async () => {
|
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);
|
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;
|
- A missing command handler is surfaced by the host as a retryable reload error;
|
||||||
menu clicks must never fail silently.
|
menu clicks must never fail silently.
|
||||||
- A registered handler's rejected promise is not swallowed: the host logs the
|
- 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
|
particular, return/await `services.windows.open(...)` so native-window
|
||||||
failures follow this path.
|
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
|
- A handler owns precondition checks and feedback. See
|
||||||
[Commands And Feedback](commands-and-feedback.md).
|
[Commands And Feedback](commands-and-feedback.md).
|
||||||
- Menu item `when` expressions are evaluated by the host; unsupported or false
|
- 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
|
one of the calling plugin's declared layout contributions. See
|
||||||
[Windows](windows.md).
|
[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
|
## Scheduled tasks
|
||||||
|
|
||||||
Project scheduled tasks are exposed through native Tauri/HTTP commands and the
|
Project scheduled tasks are exposed through native Tauri/HTTP commands and the
|
||||||
|
|||||||
Reference in New Issue
Block a user