From 1239104b0f3985e95ddd338b150fd1f66a3c84d4 Mon Sep 17 00:00:00 2001 From: Blomios Date: Tue, 8 Sep 2026 13:40:52 +0200 Subject: [PATCH] =?UTF-8?q?docs(sdk):=20feedback=20visible=20via=20windows?= =?UTF-8?q?.open=20+=20s=C3=A9paration=20Codex=20skills=20document=C3=A9es?= =?UTF-8?q?=20=E2=80=94=20commands-and-feedback=20(surface=20normative=20+?= =?UTF-8?q?=20exemple),=20layouts-react=20(type=E2=86=94contributes.layout?= =?UTF-8?q?s,=20capacit=C3=A9=20ui),=20manifest=20(exemple=20complet=20men?= =?UTF-8?q?u+layout+ui),=20windows=20(contrat=20ui,=20retour=20structur?= =?UTF-8?q?=C3=A9),=20packaging-distribution=20(idea=5Fplugin=5Finstall=5F?= =?UTF-8?q?from=5Fdirectory,=20s=C3=A9mantique=20plugin=5Freloaded/ESM),?= =?UTF-8?q?=20nouveau=20codex-skills-and-idea-plugins,=20README=20(lien)?= =?UTF-8?q?=20=E2=80=94=20#280=20QA=20verte?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + docs/codex-skills-and-idea-plugins.md | 41 ++++++++++++++++++++ docs/commands-and-feedback.md | 42 +++++++++++++++++++- docs/layouts-react.md | 20 ++++++++++ docs/manifest.md | 55 +++++++++++++++++++++++++++ docs/packaging-distribution.md | 37 +++++++++++++++--- docs/windows.md | 15 +++++++- 7 files changed, 202 insertions(+), 9 deletions(-) create mode 100644 docs/codex-skills-and-idea-plugins.md diff --git a/README.md b/README.md index a67d239..1b7adfe 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ exports `activate(ctx)`. - [Windows](docs/windows.md): opening plugin layouts in detached OS windows. - [Services](docs/services.md): workspace, tasks, tooling, events, config, terminal and windows facades. - [Packaging And Distribution](docs/packaging-distribution.md): build output, archive layout, hot reload and dependency rules. +- [Codex Skills And IdeA Plugins](docs/codex-skills-and-idea-plugins.md): separate runtime install from Codex skill discovery. The installable example lives in [`examples/hello-plugin`](examples/hello-plugin). It demonstrates a menu command, storage, background-task feedback, a React layout diff --git a/docs/codex-skills-and-idea-plugins.md b/docs/codex-skills-and-idea-plugins.md new file mode 100644 index 0000000..59c1693 --- /dev/null +++ b/docs/codex-skills-and-idea-plugins.md @@ -0,0 +1,41 @@ +# Codex Skills And IdeA Plugins + +IdeA runtime plugins and Codex plugins are separate installation and discovery +systems. + +An IdeA runtime plugin is described by `idea-plugin.json`. Installing it through +IdeA makes its IdeA runtime contributions available: menus, menu items, slash +commands, layouts, MCP servers and runtime services declared by the IdeA plugin +manifest. + +A Codex plugin is described by `.codex-plugin/plugin.json`. Its `skills` entry +points Codex at skill directories such as `skills/*/SKILL.md`. This metadata is +for Codex plugin installation and skill discovery, not for IdeA runtime plugin +loading. + +## Normative Behavior + +- Installing or reloading an IdeA plugin does not automatically install a bundled + Codex plugin. +- Installing or reloading an IdeA plugin does not automatically make bundled + Codex skills available to agents in the current project. +- Installing or reloading an IdeA plugin does not automatically make bundled + Codex skills available to agents in other projects. +- No `idea-plugin.json` manifest field currently declares Codex skills for IdeA + agent assignment. +- Bundling `.codex-plugin/plugin.json` and `skills/*/SKILL.md` inside an IdeA + plugin package is allowed as distribution content, but it is inert for IdeA + runtime plugin loading unless a separate bridge explicitly consumes it. + +## Required Mechanism + +If a plugin needs Codex skills to be available to agents, install the Codex +plugin through the Codex plugin mechanism for the intended scope, then assign or +enable those skills for the relevant agents according to Codex/IdeA agent +configuration. + +Do not rely on IdeA plugin installation as a cross-project skill propagation +mechanism. Cross-project skill availability needs an explicit product contract +covering scope, provenance, permissions, uninstall behavior, hot reload, +collisions and security. Until that bridge exists, document and perform Codex +skill installation separately from IdeA runtime plugin installation. diff --git a/docs/commands-and-feedback.md b/docs/commands-and-feedback.md index e30b327..6b349d0 100644 --- a/docs/commands-and-feedback.md +++ b/docs/commands-and-feedback.md @@ -26,8 +26,9 @@ 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 current human menu-click UI does not guarantee display of a command - handler return value. Use logs, Work/task state or plugin-owned UI/files when - a human needs visible feedback today. + handler return value. When a human must see feedback from a menu action, open + or focus a plugin layout/window from the handler with + `ctx.services.windows.open({ layoutType, state })`. ## Preconditions @@ -76,6 +77,9 @@ Visible surfaces are intentionally distinct: - Command return value: immediate feedback for programmatic callers, agents and future host surfaces. It is not a guaranteed visible UI surface for current human menu clicks. +- 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. - Plugin logs: diagnostics for developers and operators. - Work/background-task surfaces: only for tasks actually launched through `runCommand()`. @@ -105,6 +109,40 @@ state when invoked instead of assuming a watch was installed at activation. ## Example +Visible menu feedback: + +```tsx +import type { IdeAPluginModule, PluginLayoutProps } from "@idea/plugin-sdk"; + +function HealthView(_props: PluginLayoutProps<{ source?: string }>) { + return
Unity tools are ready.
; +} + +const plugin: IdeAPluginModule = { + activate(ctx) { + ctx.layouts?.register({ + type: "unity-plugin.health", + component: HealthView + }); + + ctx.commands?.registerCommand("unity-plugin.health", async () => { + const win = await ctx.services?.windows.open({ + layoutType: "unity-plugin.health", + state: { source: "menu" } + }); + + return win + ? { status: "opened", message: "Opened Unity Health.", alreadyOpen: win.alreadyOpen } + : { status: "skipped", reason: "ui-service-unavailable", message: "UI service unavailable." }; + }); + } +}; + +export default plugin; +``` + +Background task feedback: + ```ts const project = await ctx.services?.workspace.getCurrentProject(); if (!project) { diff --git a/docs/layouts-react.md b/docs/layouts-react.md index e823ee8..275a318 100644 --- a/docs/layouts-react.md +++ b/docs/layouts-react.md @@ -32,6 +32,26 @@ ctx.layouts?.register({ }); ``` +The `type` must exactly match one entry in `contributes.layouts`. The host +rejects registrations for undeclared layout types. A plugin that opens this +layout for human feedback must also declare the `ui` capability so the UI +runtime and window services are part of the public contract. + +```json +{ + "capabilities": ["ui", "tooling"], + "contributes": { + "layouts": [ + { + "type": "hello-plugin.dashboard", + "label": "Dashboard", + "component": "Dashboard" + } + ] + } +} +``` + ## Props - `projectId`: project hosting the layout. diff --git a/docs/manifest.md b/docs/manifest.md index 83a8fe7..ebaf2de 100644 --- a/docs/manifest.md +++ b/docs/manifest.md @@ -147,6 +147,61 @@ development loop. contribution can be mounted inside an IdeA layout cell or opened in a detached OS window. Do not add a separate manifest contribution type for windows. +For a command that opens a visible plugin window, declare both the menu command +and the layout type: + +```json +{ + "ideaPluginManifestVersion": 1, + "id": "com.example.unity-plugin", + "displayName": "Unity Developer Tools", + "publisher": "Example", + "version": "0.1.0", + "description": "Unity integration for IdeA.", + "main": "dist/index.js", + "engines": { + "idea": ">=0.1.0" + }, + "trustLevel": "full", + "capabilities": ["ui", "tooling"], + "activationScope": "app", + "contributes": { + "menus": [ + { + "id": "unity-plugin.menu", + "label": "Unity Developer Tools", + "topLevel": true, + "order": 100 + } + ], + "menuItems": [ + { + "id": "unity-plugin.health.item", + "targetMenuId": "unity-plugin.menu", + "label": "Health", + "command": "unity-plugin.health", + "order": 10, + "when": "projectOpen" + } + ], + "layouts": [ + { + "type": "unity-plugin.health", + "label": "Unity Health", + "component": "UnityHealth", + "order": 10 + } + ] + } +} +``` + +`capabilities: ["ui"]` is required when a plugin relies on layouts or windows as +human-facing UI. Add `"tooling"` when the same plugin uses workspace, task, +tooling or terminal services. The `contributes.layouts[].type` value is the +public id used by both `ctx.layouts.register({ type, component })` and +`ctx.services.windows.open({ layoutType })`. + Contribution ids are part of the runtime contract: - commands can only register ids declared by `contributes.menuItems[*].command`; diff --git a/docs/packaging-distribution.md b/docs/packaging-distribution.md index cdc3d8d..71c21eb 100644 --- a/docs/packaging-distribution.md +++ b/docs/packaging-distribution.md @@ -102,8 +102,23 @@ After editing plugin source files, rebuild the plugin output first: npm run build ``` -Then ask an IdeA agent that has the plugin administration tool available to run -`idea_plugin_reload` with the installed plugin id: +An IdeA agent can install a development plugin directory only when that agent has +the plugin administration MCP tool explicitly allowed. The public tool is +`idea_plugin_install_from_directory`: + +```json +{ + "path": "relative/path/to/hello-plugin", + "expectedPluginId": "com.example.hello-plugin" +} +``` + +The path must resolve under the requester's project root. This installs the +directory as the recorded development source for later reloads. + +After source edits, rebuild the plugin output and ask an IdeA agent that has the +plugin administration tool available to run `idea_plugin_reload` with the +installed plugin id: ```json { @@ -122,7 +137,17 @@ reload. Archive installs are fixed package snapshots. They are appropriate for distribution, but the reload command is only defined for plugins installed from a directory source. -Current limitation: backend registry state and plugin MCP/tool contributions are -reloaded without restarting IdeA. Frontend React contributions that are already -loaded in the current UI session may keep their existing module instance until -the relevant plugin surface is recreated or the app session is restarted. +On reload, `plugin_reloaded` tells the UI to rebuild the plugin runtime registry. +When the package content hash changes, plugin ESM URLs change and React layout +components are loaded from the new package. Existing plugin layout instances may +remount and lose local React state; host-persisted layout state written through +`setState` remains the durable state channel. + +JavaScript module instances cannot be forcibly removed from the browser ESM +cache. Register handlers, layouts, watches and subscriptions through the SDK +registries and push disposable side effects into `ctx.subscriptions`; global +module side effects can otherwise survive a reload. If the package hash did not +change, the reload is idempotent and may reuse the same module instance. + +IdeA runtime plugin installation is separate from Codex plugin/skill discovery. +See [Codex Skills And IdeA Plugins](codex-skills-and-idea-plugins.md). diff --git a/docs/windows.md b/docs/windows.md index 8bd3b62..7ff1ae4 100644 --- a/docs/windows.md +++ b/docs/windows.md @@ -10,9 +10,18 @@ await ctx.services?.windows.open({ }); ``` +`windows.open` is the public API for commands that need to make feedback visible +to a human. A command handler may still return structured data, but menu clicks +do not currently guarantee that return value is displayed. + ## Contract - `layoutType` must match a layout type declared by the calling plugin. +- The plugin must declare `capabilities: ["ui"]` when it relies on plugin + layouts/windows as a human-facing surface. Add `"tooling"` only when the + plugin also uses tooling/workspace/task services. +- There is no `contributes.windows` manifest key. Windows always host an + existing `contributes.layouts` layout. - The host validates the plugin is runtime-active and the layout exists before opening or focusing the window. - Reopening the same plugin/layout pair focuses the existing window. @@ -38,9 +47,13 @@ The returned `label` is a host-owned window identity. Treat it as opaque. ```ts ctx.commands?.registerCommand("hello-plugin.open-dashboard", async () => { - return ctx.services?.windows.open({ + const win = await ctx.services?.windows.open({ layoutType: "hello-plugin.dashboard", state: { source: "menu" } }); + + return win + ? { status: "opened", message: "Opened dashboard.", alreadyOpen: win.alreadyOpen } + : { status: "skipped", reason: "ui-service-unavailable", message: "UI service unavailable." }; }); ```