chore(plugins): complete compat registry inventory

This commit is contained in:
Vincent Koc
2026-04-26 02:33:42 -07:00
parent 975fd5bc8d
commit a9d243327c
6 changed files with 167 additions and 4 deletions

View File

@@ -65,6 +65,7 @@ Docs: https://docs.openclaw.ai
- CLI/configure: keep web-search configure prompts on cold plugin registry metadata until the user chooses managed search setup. Thanks @vincentkoc.
- Plugins/chat commands: refresh the persisted plugin registry after `/plugins enable` and `/plugins disable`, matching the CLI mutation path. Thanks @vincentkoc.
- Plugins/compat: mark `OPENCLAW_DISABLE_PERSISTED_PLUGIN_REGISTRY` as a deprecated break-glass switch and point operators at registry repair instead. Thanks @vincentkoc.
- Plugins/compat: expand the central compatibility registry with dated owners, replacements, and removal targets for legacy SDK, manifest, setup, registry-migration, and agent-runtime surfaces. Thanks @vincentkoc.
- Plugins/registry: ignore stale persisted registry reads when plugin policy no longer matches current config, and stamp generated registry files with a do-not-edit warning. Thanks @vincentkoc.
- Diagnostics/OTEL: surface provider request identifiers as bounded hashes on model-call diagnostics and span events, without exporting raw request IDs or metric labels. Thanks @Lidang-Jiang and @vincentkoc.
- Plugins/diagnostics: add metadata-only `model_call_started` and `model_call_ended` hooks for provider/model call telemetry without exposing prompts, responses, headers, request bodies, or raw provider request IDs. Thanks @vincentkoc.

View File

@@ -71,7 +71,9 @@ The migration sequence is:
7. Remove only with explicit breaking-release approval.
Deprecated records must include a warning start date, replacement, docs link,
and target removal date when known.
and target removal date. Do not add a deprecated compatibility path with an
open-ended removal window unless maintainers explicitly decide it is permanent
compatibility and mark it `active` instead.
## Current compatibility areas
@@ -79,15 +81,27 @@ Current compatibility records include:
- legacy broad SDK imports such as `openclaw/plugin-sdk/compat`
- legacy hook-only plugin shapes and `before_agent_start`
- legacy `activate(api)` plugin entrypoints while plugins migrate to
`register(api)`
- legacy SDK aliases such as `openclaw/plugin-sdk/channel-runtime`,
`openclaw/plugin-sdk/command-auth` status builders, and the
`ClawdbotConfig` type alias
- bundled plugin allowlist and enablement behavior
- legacy provider/channel env-var manifest metadata
- activation hints that are being replaced by manifest contribution ownership
- `setup-api` runtime fallback while setup descriptors move to cold
`setup.requiresRuntime: false` metadata
- provider `discovery` hooks while provider catalog hooks move to
`catalog.run(...)`
- channel `showConfigured` / `showInSetup` metadata while channel packages move
to `openclaw.channel.exposure`
- legacy runtime-policy config keys while doctor migrates operators to
`agentRuntime`
- generated bundled channel config metadata fallback while registry-first
`channelConfigs` metadata lands
- the persisted plugin registry disable env while repair flows migrate operators
to `openclaw plugins registry --refresh` and `openclaw doctor --fix`
- persisted plugin registry disable and install-migration env flags while
repair flows migrate operators to `openclaw plugins registry --refresh` and
`openclaw doctor --fix`
New plugin code should prefer the replacement listed in the registry and in the
specific migration guide. Existing plugins can keep using a compatibility path

View File

@@ -1,3 +1,4 @@
import fs from "node:fs";
import { describe, expect, it } from "vitest";
import {
getPluginCompatRecord,
@@ -23,6 +24,7 @@ describe("plugin compatibility registry", () => {
for (const record of listDeprecatedPluginCompatRecords()) {
expect(record.deprecated, record.code).toMatch(datePattern);
expect(record.warningStarts, record.code).toMatch(datePattern);
expect(record.removeAfter, record.code).toMatch(datePattern);
expect(record.replacement, record.code).toBeTruthy();
expect(record.docsPath, record.code).toMatch(/^\//u);
}
@@ -35,6 +37,9 @@ describe("plugin compatibility registry", () => {
expect(record.surfaces.length, record.code).toBeGreaterThan(0);
expect(record.diagnostics.length, record.code).toBeGreaterThan(0);
expect(record.tests.length, record.code).toBeGreaterThan(0);
for (const testPath of record.tests) {
expect(fs.existsSync(testPath), `${record.code}: ${testPath}`).toBe(true);
}
}
});
});

View File

@@ -8,6 +8,7 @@ export const PLUGIN_COMPAT_RECORDS = [
introduced: "2026-04-24",
deprecated: "2026-04-24",
warningStarts: "2026-04-24",
removeAfter: "2026-07-01",
replacement: "`before_model_resolve` and `before_prompt_build` hooks",
docsPath: "/plugins/sdk-migration",
surfaces: ["plugin hooks", "plugins inspect", "status diagnostics"],
@@ -34,6 +35,7 @@ export const PLUGIN_COMPAT_RECORDS = [
introduced: "2026-04-24",
deprecated: "2026-04-24",
warningStarts: "2026-04-24",
removeAfter: "2026-07-01",
replacement: "focused `openclaw/plugin-sdk/<subpath>` imports",
docsPath: "/plugins/sdk-migration",
surfaces: ["openclaw/plugin-sdk", "openclaw/plugin-sdk/compat"],
@@ -83,6 +85,7 @@ export const PLUGIN_COMPAT_RECORDS = [
introduced: "2026-04-24",
deprecated: "2026-04-24",
warningStarts: "2026-04-24",
removeAfter: "2026-07-01",
replacement: "`setup.providers[].envVars` and `providerAuthChoices`",
docsPath: "/plugins/manifest",
surfaces: ["openclaw.plugin.json providerAuthEnvVars", "provider setup"],
@@ -96,6 +99,7 @@ export const PLUGIN_COMPAT_RECORDS = [
introduced: "2026-04-24",
deprecated: "2026-04-24",
warningStarts: "2026-04-24",
removeAfter: "2026-07-01",
replacement: "`channelConfigs.<id>.schema` and setup descriptors",
docsPath: "/plugins/manifest",
surfaces: ["openclaw.plugin.json channelEnvVars", "channel setup"],
@@ -105,6 +109,18 @@ export const PLUGIN_COMPAT_RECORDS = [
"src/channels/plugins/setup-group-access.test.ts",
],
},
{
code: "activation-agent-harness-hint",
status: "active",
owner: "plugin-execution",
introduced: "2026-04-24",
replacement:
"top-level `cliBackends[]` for CLI aliases and future `agentRuntime` ownership metadata",
docsPath: "/plugins/manifest",
surfaces: ["activation.onAgentHarnesses", "activation planner"],
diagnostics: ["activation plan compat reason"],
tests: ["src/plugins/activation-planner.test.ts"],
},
{
code: "activation-provider-hint",
status: "active",
@@ -167,11 +183,12 @@ export const PLUGIN_COMPAT_RECORDS = [
introduced: "2026-04-24",
deprecated: "2026-04-25",
warningStarts: "2026-04-25",
removeAfter: "2026-08-01",
replacement: "`agentRuntime` config naming",
docsPath: "/plugins/sdk-agent-harness",
surfaces: ["agents.defaults.embeddedHarness", "model/provider runtime selection"],
diagnostics: ["agent runtime config compatibility"],
tests: ["src/agents/config.test.ts", "src/agents/runtime-selection.test.ts"],
tests: ["src/commands/doctor/shared/legacy-config-migrate.test.ts"],
},
{
code: "agent-harness-sdk-alias",
@@ -180,6 +197,7 @@ export const PLUGIN_COMPAT_RECORDS = [
introduced: "2026-04-24",
deprecated: "2026-04-25",
warningStarts: "2026-04-25",
removeAfter: "2026-08-01",
replacement: "`openclaw/plugin-sdk/agent-runtime`",
docsPath: "/plugins/sdk-agent-harness",
surfaces: ["openclaw/plugin-sdk/agent-harness", "openclaw/plugin-sdk/agent-harness-runtime"],
@@ -193,6 +211,7 @@ export const PLUGIN_COMPAT_RECORDS = [
introduced: "2026-04-24",
deprecated: "2026-04-25",
warningStarts: "2026-04-25",
removeAfter: "2026-08-01",
replacement: "`agentRuntime` ids and policy metadata",
docsPath: "/plugins/sdk-agent-harness",
surfaces: ["manifest/catalog execution policy", "runtime selection"],
@@ -217,12 +236,131 @@ export const PLUGIN_COMPAT_RECORDS = [
introduced: "2026-04-25",
deprecated: "2026-04-25",
warningStarts: "2026-04-25",
removeAfter: "2026-07-15",
replacement: "`openclaw plugins registry --refresh` and `openclaw doctor --fix`",
docsPath: "/cli/plugins#registry",
surfaces: ["OPENCLAW_DISABLE_PERSISTED_PLUGIN_REGISTRY", "plugin registry reads"],
diagnostics: ["persisted-registry-disabled"],
tests: ["src/plugins/plugin-registry.test.ts"],
},
{
code: "plugin-registry-install-migration-env",
status: "deprecated",
owner: "config",
introduced: "2026-04-25",
deprecated: "2026-04-25",
warningStarts: "2026-04-25",
removeAfter: "2026-07-15",
replacement: "`openclaw plugins registry --refresh` and `openclaw doctor --fix`",
docsPath: "/cli/plugins#registry",
surfaces: [
"OPENCLAW_DISABLE_PLUGIN_REGISTRY_MIGRATION",
"OPENCLAW_FORCE_PLUGIN_REGISTRY_MIGRATION",
"package postinstall plugin registry migration",
],
diagnostics: ["postinstall migration skip", "postinstall migration force deprecation warning"],
tests: ["src/commands/doctor/shared/plugin-registry-migration.test.ts"],
},
{
code: "plugin-activate-entrypoint-alias",
status: "deprecated",
owner: "sdk",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-08-01",
replacement: "`register(api)` plugin entrypoint",
docsPath: "/plugins/sdk-entrypoints",
surfaces: ["plugin module `activate(api)`", "plugin loader registration"],
diagnostics: ["loader compatibility path"],
tests: ["src/plugins/loader.test.ts"],
},
{
code: "setup-runtime-fallback",
status: "active",
owner: "setup",
introduced: "2026-04-24",
replacement: "`setup.requiresRuntime: false` with complete setup descriptors",
docsPath: "/plugins/manifest#setup-reference",
surfaces: ["setup-api runtime fallback", "setup.requiresRuntime omitted"],
diagnostics: ["setup registry runtime diagnostic"],
tests: ["src/plugins/setup-registry.test.ts", "src/plugins/setup-registry.runtime.test.ts"],
},
{
code: "provider-discovery-hook-alias",
status: "deprecated",
owner: "provider",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-08-01",
replacement: "`catalog.run(...)` provider catalog hook",
docsPath: "/plugins/sdk-migration",
surfaces: ["provider plugin `discovery` hook", "provider catalog resolution"],
diagnostics: ["provider validation warning when catalog and discovery both register"],
tests: ["src/plugins/provider-discovery.test.ts", "src/plugins/provider-validation.test.ts"],
},
{
code: "channel-exposure-legacy-aliases",
status: "deprecated",
owner: "channel",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-08-01",
replacement: "`openclaw.channel.exposure` metadata",
docsPath: "/plugins/sdk-setup",
surfaces: ["openclaw.channel.showConfigured", "openclaw.channel.showInSetup"],
diagnostics: ["channel exposure compatibility path"],
tests: ["src/commands/channel-setup/discovery.test.ts"],
},
{
code: "channel-runtime-sdk-alias",
status: "deprecated",
owner: "sdk",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-08-01",
replacement:
"focused channel SDK subpaths, especially `openclaw/plugin-sdk/channel-runtime-context`",
docsPath: "/plugins/sdk-migration",
surfaces: ["openclaw/plugin-sdk/channel-runtime"],
diagnostics: ["plugin SDK compatibility warning"],
tests: ["src/plugins/contracts/plugin-sdk-subpaths.test.ts"],
},
{
code: "command-auth-status-builders",
status: "deprecated",
owner: "sdk",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-08-01",
replacement: "`openclaw/plugin-sdk/command-status`",
docsPath: "/plugins/sdk-migration",
surfaces: [
"openclaw/plugin-sdk/command-auth buildCommandsMessage",
"openclaw/plugin-sdk/command-auth buildCommandsMessagePaginated",
"openclaw/plugin-sdk/command-auth buildHelpMessage",
],
diagnostics: ["plugin SDK compatibility warning"],
tests: ["src/plugin-sdk/command-auth.test.ts"],
},
{
code: "clawdbot-config-type-alias",
status: "deprecated",
owner: "sdk",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-08-01",
replacement: "`OpenClawConfig`",
docsPath: "/plugins/sdk-migration",
surfaces: ["openclaw/plugin-sdk `ClawdbotConfig` type export"],
diagnostics: ["plugin SDK compatibility warning"],
tests: ["src/plugins/contracts/plugin-sdk-index.test.ts"],
},
] as const satisfies readonly PluginCompatRecord[];
export type PluginCompatCode = (typeof PLUGIN_COMPAT_RECORDS)[number]["code"];

View File

@@ -127,6 +127,7 @@ function createRichPluginFixture(params: { packageVersion?: string } = {}) {
"demo-chat": ["DEMO_CHAT_TOKEN"],
},
activation: {
onAgentHarnesses: ["codex"],
onProviders: ["demo"],
onChannels: ["demo-chat"],
},
@@ -205,6 +206,7 @@ describe("installed plugin index", () => {
},
},
compat: [
"activation-agent-harness-hint",
"activation-channel-hint",
"activation-provider-hint",
"channel-env-vars",

View File

@@ -223,6 +223,9 @@ function collectCompatCodes(record: PluginManifestRecord): readonly PluginCompat
if (record.activation?.onProviders?.length) {
codes.push("activation-provider-hint");
}
if (record.activation?.onAgentHarnesses?.length) {
codes.push("activation-agent-harness-hint");
}
if (record.activation?.onChannels?.length) {
codes.push("activation-channel-hint");
}