feat(sdk): pluginRoot officiel exposé dans activate(ctx) — #285 (src/runtime: champ pluginRoot = racine du package installé; docs activation-context/commands-and-feedback/services/manifest réécrits du constat d'absence vers le contrat d'usage officiel — runCommand reste project-scoped, pluginRoot utilisable dans command/args, substitution manifest ${pluginRoot}/${appDataDir} inchangée pour mcpServers; exemple hello-plugin: script packagé scripts/hello-task.mjs consommé via ctx.pluginRoot, packaging étendu; QA verte: npm run check — build, typecheck:examples, package:hello-plugin, artefact zip vérifié)
This commit is contained in:
@ -6,7 +6,10 @@ The plugin entrypoint exports `activate(ctx)`.
|
||||
import type { ActivateContext, IdeAPluginModule } from "@idea/plugin-sdk";
|
||||
|
||||
export function activate(ctx: ActivateContext): void {
|
||||
ctx.logger.info("activated", { pluginId: ctx.pluginId });
|
||||
ctx.logger.info("activated", {
|
||||
pluginId: ctx.pluginId,
|
||||
pluginRoot: ctx.pluginRoot
|
||||
});
|
||||
}
|
||||
|
||||
export default { activate } satisfies IdeAPluginModule;
|
||||
@ -28,6 +31,7 @@ focused project at invocation/render time.
|
||||
## Context Fields
|
||||
|
||||
- `pluginId`: host-provided plugin identity.
|
||||
- `pluginRoot`: absolute host-local path to the active installed plugin package.
|
||||
- `logger`: `debug`, `info`, `warn`, `error`.
|
||||
- `subscriptions`: push disposables returned by command/layout/watch
|
||||
registrations.
|
||||
@ -41,11 +45,11 @@ focused project at invocation/render time.
|
||||
The context never exposes internal IdeA gateways or Tauri commands. Use
|
||||
`ctx.services` and the registration APIs instead.
|
||||
|
||||
`ActivateContext` does not expose the plugin installation directory, package
|
||||
root, archive root or a file URL that plugins can convert into a local path.
|
||||
Plugin runtime code must treat packaged files as unavailable to
|
||||
`ctx.services.tasks.runCommand()` unless a dedicated public SDK API documents
|
||||
otherwise. Workspace services resolve project-owned paths only.
|
||||
`pluginRoot` identifies the committed package currently loaded by IdeA. It is
|
||||
not the original source directory or archive path and may change after reinstall.
|
||||
Treat it as read-only, do not persist it, and resolve packaged scripts/assets
|
||||
under it only while the plugin is active. Workspace services remain confined to
|
||||
project-owned paths.
|
||||
|
||||
## Disposal
|
||||
|
||||
|
||||
@ -43,9 +43,10 @@ Check preconditions before calling `runCommand()`:
|
||||
- `ownerAgentId` is a real agent id when the work is owned by an agent workflow.
|
||||
Do not use all-zero placeholders in production.
|
||||
- `cwd` is relative to the project root.
|
||||
- `command`, `args` and `cwd` do not resolve package-relative plugin resources.
|
||||
Do not use `runCommand()` to launch scripts shipped inside the plugin package;
|
||||
there is no public runtime `pluginRoot` path in `activate(ctx)`.
|
||||
- `command` and `args` do not resolve package-relative plugin resources
|
||||
implicitly. Build an explicit absolute script path from `ctx.pluginRoot` when
|
||||
launching read-only files shipped in the installed package.
|
||||
- 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.
|
||||
|
||||
If any required precondition fails, return a skipped result:
|
||||
|
||||
@ -255,9 +255,10 @@ declared MCP server. In `command`, `args`, `env` and `cwd`, the host expands:
|
||||
- `${pluginRoot}` to the installed plugin package root.
|
||||
- `${appDataDir}` to the host-owned application data directory.
|
||||
|
||||
This substitution is limited to manifest-declared MCP server startup. It is not
|
||||
available from `activate(ctx)`, `ctx.services.workspace` or
|
||||
`ctx.services.tasks.runCommand()`.
|
||||
This string substitution is limited to manifest-declared MCP server startup.
|
||||
Runtime handlers receive the same installed package location separately as
|
||||
`ctx.pluginRoot`; `ctx.services.tasks.runCommand()` does not perform placeholder
|
||||
substitution, and workspace APIs remain project-confined.
|
||||
|
||||
## Validation
|
||||
|
||||
|
||||
@ -37,12 +37,24 @@ Key APIs:
|
||||
Use `runCommand()` only after preconditions are satisfied. `ownerAgentId` must be
|
||||
a real agent id when work belongs to an agent workflow.
|
||||
|
||||
`runCommand()` is project/workspace scoped. Its `cwd` option is a relative path
|
||||
under the project root, and `command`/`args` are not resolved against the
|
||||
calling plugin's package. The SDK does not currently provide a public
|
||||
`pluginRoot` or package-path resolver for runtime command handlers. Packaged
|
||||
scripts cannot be launched through `runCommand()` by referring to their
|
||||
package-relative path.
|
||||
`runCommand()` keeps its `cwd` project/workspace scoped: `cwd` must be a relative
|
||||
path under the project root. The host does not implicitly resolve `command` or
|
||||
`args` against the plugin package. Use the absolute `ctx.pluginRoot` supplied at
|
||||
activation time to construct an explicit path to a packaged script, and pass
|
||||
that path as `command` or as an argument to its interpreter. Treat package files
|
||||
as read-only.
|
||||
|
||||
```ts
|
||||
const script = `${ctx.pluginRoot.replace(/[\\/]+$/, "")}/scripts/check.mjs`;
|
||||
await ctx.services.tasks.runCommand({
|
||||
projectId,
|
||||
ownerAgentId,
|
||||
label: "Run packaged check",
|
||||
command: "node",
|
||||
args: [script],
|
||||
cwd: "."
|
||||
});
|
||||
```
|
||||
|
||||
## Tooling
|
||||
|
||||
|
||||
Reference in New Issue
Block a user