refactor(plugins): track activation compat hints

This commit is contained in:
Vincent Koc
2026-04-23 20:59:07 -07:00
parent 76a4c167f7
commit b1d0c14d38
8 changed files with 374 additions and 106 deletions

View File

@@ -119,22 +119,31 @@ signals also appear in `openclaw status --all` and `openclaw plugins doctor`.
## Architecture overview
OpenClaw's plugin system has four layers:
OpenClaw's plugin system is split into four planes:
1. **Manifest + discovery**
OpenClaw finds candidate plugins from configured paths, workspace roots,
global plugin roots, and bundled plugins. Discovery reads native
`openclaw.plugin.json` manifests plus supported bundle manifests first.
2. **Enablement + validation**
Core decides whether a discovered plugin is enabled, disabled, blocked, or
selected for an exclusive slot such as memory.
3. **Runtime loading**
Native OpenClaw plugins are loaded in-process via jiti and register
capabilities into a central registry. Compatible bundles are normalized into
registry records without importing runtime code.
4. **Surface consumption**
The rest of OpenClaw reads the registry to expose tools, channels, provider
setup, hooks, HTTP routes, CLI commands, and services.
1. **Source plane**
OpenClaw decides where a plugin comes from and how it can be installed. This
includes bundled catalogs, official external catalogs, ClawHub/npm specs,
local source paths, minimum host version, expected npm integrity, and install
policy checks.
2. **Control plane**
OpenClaw reads package and manifest metadata before runtime code executes.
This includes discovery, config schemas, provider/channel ownership,
setup/onboarding hints, contracts, auth choices, and enablement policy.
3. **Load plane**
OpenClaw builds deterministic plans for concrete needs such as a provider,
channel, command, hook stage, or contract. Legacy `activation.*` fields are
compatibility hints in this plane, not the preferred public contract.
4. **Runtime plane**
OpenClaw imports plugin code only for actual execution. Native plugins
register capabilities into scoped or compatibility registries; compatible
bundles can still normalize into registry records without importing runtime
code.
The important compatibility rule: documented external plugins and existing
bundled plugins must keep working while contracts migrate. Breaking changes need
a replacement contract, compatibility adapter, diagnostics, tests, docs, and an
approved deprecation window before removal.
For plugin CLI specifically, root command discovery is split in two phases:

View File

@@ -239,11 +239,15 @@ runtime still owns actual CLI registration through a lightweight
| `commandName` | Yes | `string` | Subcommand mounted beneath `openclaw qa`, for example `matrix`. |
| `description` | No | `string` | Fallback help text used when the shared host needs a stub command. |
This block is metadata only. It does not register runtime behavior, and it does
not replace `register(...)`, `setupEntry`, or other runtime/plugin entrypoints.
Current consumers use it as a narrowing hint before broader plugin loading, so
missing activation metadata usually only costs performance; it should not
change correctness while legacy manifest ownership fallbacks still exist.
This block is legacy hint metadata. It does not register runtime behavior, and
it does not replace `register(...)`, `setupEntry`, or other runtime/plugin
entrypoints. Existing plugins may keep these fields, but new manifests should
prefer explicit ownership fields such as `providers`, `channels`, `contracts`,
`commandAliases`, and `setup`.
Current consumers still parse `activation` through the compatibility layer so
existing bundled and external plugins keep working. New code should treat these
fields as fallback hints for load planning, not as the primary plugin contract.
```json
{
@@ -257,23 +261,24 @@ change correctness while legacy manifest ownership fallbacks still exist.
}
```
| Field | Required | Type | What it means |
| ---------------- | -------- | ---------------------------------------------------- | ----------------------------------------------------------------- |
| `onProviders` | No | `string[]` | Provider ids that should activate this plugin when requested. |
| `onCommands` | No | `string[]` | Command ids that should activate this plugin. |
| `onChannels` | No | `string[]` | Channel ids that should activate this plugin. |
| `onRoutes` | No | `string[]` | Route kinds that should activate this plugin. |
| `onCapabilities` | No | `Array<"provider" \| "channel" \| "tool" \| "hook">` | Broad capability hints used by control-plane activation planning. |
| Field | Required | Type | What it means |
| ---------------- | -------- | ---------------------------------------------------- | ----------------------------------------------------------------------------- |
| `onProviders` | No | `string[]` | Legacy provider load hint. Prefer top-level `providers`. |
| `onCommands` | No | `string[]` | Legacy command load hint. Prefer command aliases or CLI descriptors. |
| `onChannels` | No | `string[]` | Legacy channel load hint. Prefer top-level `channels`. |
| `onRoutes` | No | `string[]` | Legacy route load hint. Keep only when no narrower route metadata exists yet. |
| `onCapabilities` | No | `Array<"provider" \| "channel" \| "tool" \| "hook">` | Legacy broad capability hint. Do not add new uses. |
Current live consumers:
- command-triggered CLI planning falls back to legacy
`commandAliases[].cliCommand` or `commandAliases[].name`
- channel-triggered setup/channel planning falls back to legacy `channels[]`
ownership when explicit channel activation metadata is missing
- provider-triggered setup/runtime planning falls back to legacy
`providers[]` and top-level `cliBackends[]` ownership when explicit provider
activation metadata is missing
- command-triggered CLI planning prefers `commandAliases[].cliCommand` or
`commandAliases[].name` before legacy `activation.onCommands`
- channel-triggered setup/channel planning prefers `channels[]` before legacy
`activation.onChannels`
- provider-triggered setup/runtime planning prefers `providers[]` and
`setup.providers[]` before legacy `activation.onProviders`
- broad capability planning prefers explicit ownership metadata before legacy
`activation.onCapabilities`
## setup reference

View File

@@ -25,12 +25,14 @@ anything they needed from a single entry point:
host-side helpers like the embedded agent runner.
Both surfaces are now **deprecated**. They still work at runtime, but new
plugins must not use them, and existing plugins should migrate before the next
major release removes them.
plugins must not use them, and existing plugins should migrate before an
approved breaking release removes them.
<Warning>
The backwards-compatibility layer will be removed in a future major release.
Plugins that still import from these surfaces will break when that happens.
The backwards-compatibility layer remains supported during the migration
window. Any removal must go through a documented deprecation path first:
replacement contract, compatibility adapter, diagnostics, tests, docs, and an
explicitly approved breaking release.
</Warning>
## Why this changed
@@ -374,13 +376,15 @@ check the source at `src/plugin-sdk/` or ask in Discord.
## Removal timeline
| When | What happens |
| ---------------------- | ----------------------------------------------------------------------- |
| **Now** | Deprecated surfaces emit runtime warnings |
| **Next major release** | Deprecated surfaces will be removed; plugins still using them will fail |
| When | What happens |
| ---------------------------------- | ---------------------------------------------------------------------------- |
| **Now** | Deprecated surfaces emit runtime warnings and keep working through adapters. |
| **Migration window** | Replacement contracts, diagnostics, tests, and docs stay available together. |
| **Approved breaking release only** | Deprecated surfaces may be removed after the migration window. |
All core plugins have already been migrated. External plugins should migrate
before the next major release.
All core plugins have already been migrated. External plugins should migrate,
but documented external plugins should not break without the compatibility path
above.
## Suppressing the warnings temporarily