chore(plugins): finish compat registry cleanup

This commit is contained in:
Vincent Koc
2026-04-26 03:15:07 -07:00
parent bc49fb1cdf
commit 6d60b035b4
4 changed files with 364 additions and 3 deletions

View File

@@ -6,6 +6,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Plugins/compat: add missing dated compatibility records for legacy extension-api, memory registration, provider hook/type aliases, runtime aliases, channel SDK helpers, and approval/test utility shims. Thanks @vincentkoc.
- Plugins/CLI: make plugin install and uninstall config writes conflict-aware, clear stale denylist entries on explicit reinstall/removal, and delete managed plugin files only after config/index commit succeeds. Thanks @codex.
- Plugins: fail `plugins update` when tracked plugin or hook updates error, keep bundled runtime-dependency repair behind restrictive allowlists, and reject package installs with unloadable extension entries. Thanks @codex.
- Gateway/chat: keep duplicate attachment-backed `chat.send` retries with the same idempotency key on the documented in-flight path so aborts still target the real active run. Fixes #70139. Thanks @Feelw00.

View File

@@ -84,11 +84,20 @@ Current compatibility records include:
- 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
- legacy SDK aliases such as `openclaw/extension-api`,
`openclaw/plugin-sdk/channel-runtime`, `openclaw/plugin-sdk/command-auth`
status builders, `openclaw/plugin-sdk/test-utils`, and the `ClawdbotConfig`
type alias
- bundled plugin allowlist and enablement behavior
- legacy provider/channel env-var manifest metadata
- legacy provider plugin hooks and type aliases while providers move to
explicit catalog, auth, thinking, replay, and transport hooks
- legacy runtime aliases such as `api.runtime.taskFlow`,
`api.runtime.subagent.getSession`, and `api.runtime.stt`
- legacy memory-plugin split registration while memory plugins move to
`registerMemoryCapability`
- legacy channel SDK helpers for native message schemas, mention gating,
inbound envelope formatting, and approval capability nesting
- activation hints that are being replaced by manifest contribution ownership
- `setup-api` runtime fallback while setup descriptors move to cold
`setup.requiresRuntime: false` metadata

View File

@@ -9,6 +9,89 @@ import {
const datePattern = /^\d{4}-\d{2}-\d{2}$/u;
const knownDeprecatedSurfaceMarkers = [
{
code: "legacy-extension-api-import",
file: "src/extensionAPI.ts",
marker: "openclaw/extension-api is deprecated",
},
{
code: "memory-split-registration",
file: "src/plugins/memory-state.ts",
marker: "registerMemoryPromptSection",
},
{
code: "provider-static-capabilities-bag",
file: "src/plugins/types.ts",
marker: "Legacy static provider capability bag",
},
{
code: "provider-discovery-type-aliases",
file: "src/plugins/types.ts",
marker: "ProviderPluginDiscovery = ProviderPluginCatalog",
},
{
code: "provider-thinking-policy-hooks",
file: "src/plugins/types.ts",
marker: "Prefer `resolveThinkingProfile`",
},
{
code: "provider-external-oauth-profiles-hook",
file: "src/plugins/types.ts",
marker: "resolveExternalOAuthProfiles",
},
{
code: "agent-tool-result-harness-alias",
file: "src/plugins/agent-tool-result-middleware-types.ts",
marker: "AgentToolResultMiddlewareHarness",
},
{
code: "runtime-taskflow-legacy-alias",
file: "src/plugins/runtime/types-core.ts",
marker: "taskFlow",
},
{
code: "runtime-subagent-get-session-alias",
file: "src/plugins/runtime/types.ts",
marker: "getSessionMessages",
},
{
code: "runtime-stt-alias",
file: "src/plugins/runtime/types-core.ts",
marker: "stt",
},
{
code: "runtime-inbound-envelope-alias",
file: "src/plugins/runtime/types-channel.ts",
marker: "formatInboundEnvelope",
},
{
code: "channel-native-message-schema-helpers",
file: "src/plugin-sdk/channel-actions.ts",
marker: "createMessageToolButtonsSchema",
},
{
code: "channel-mention-gating-legacy-helpers",
file: "src/plugin-sdk/channel-inbound.ts",
marker: "resolveMentionGatingWithBypass",
},
{
code: "provider-web-search-core-wrapper",
file: "src/plugin-sdk/provider-web-search.ts",
marker: "createPluginBackedWebSearchProvider",
},
{
code: "approval-capability-approvals-alias",
file: "src/plugin-sdk/approval-delivery-helpers.ts",
marker: "approvals?: Partial<ChannelApprovalCapabilitySurfaces>",
},
{
code: "plugin-sdk-test-utils-alias",
file: "src/plugin-sdk/test-utils.ts",
marker: "Deprecated compatibility alias",
},
] as const;
function parseDate(date: string): Date {
return new Date(`${date}T00:00:00Z`);
}
@@ -58,4 +141,11 @@ describe("plugin compatibility registry", () => {
}
}
});
it("tracks known plugin-facing deprecated surfaces", () => {
for (const surface of knownDeprecatedSurfaceMarkers) {
expect(isPluginCompatCode(surface.code), surface.code).toBe(true);
expect(fs.readFileSync(surface.file, "utf8"), surface.file).toContain(surface.marker);
}
});
});

View File

@@ -361,6 +361,267 @@ export const PLUGIN_COMPAT_RECORDS = [
diagnostics: ["plugin SDK compatibility warning"],
tests: ["src/plugins/contracts/plugin-sdk-index.test.ts"],
},
{
code: "legacy-extension-api-import",
status: "deprecated",
owner: "sdk",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement:
"injected `api.runtime.*` helpers or focused `openclaw/plugin-sdk/<subpath>` imports",
docsPath: "/plugins/sdk-migration",
surfaces: ["openclaw/extension-api"],
diagnostics: ["OPENCLAW_EXTENSION_API_DEPRECATED"],
tests: ["src/plugins/sdk-alias.test.ts", "src/index.test.ts"],
},
{
code: "memory-split-registration",
status: "deprecated",
owner: "sdk",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "`api.registerMemoryCapability({ promptBuilder, flushPlanResolver, runtime })`",
docsPath: "/plugins/sdk-migration",
surfaces: [
"api.registerMemoryPromptSection",
"api.registerMemoryFlushPlan",
"api.registerMemoryRuntime",
"src/plugins/memory-state split registration helpers",
],
diagnostics: ["plugin SDK compatibility warning"],
tests: ["src/plugins/memory-state.test.ts", "src/plugins/loader.test.ts"],
},
{
code: "provider-static-capabilities-bag",
status: "deprecated",
owner: "provider",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement:
"explicit provider hooks such as `buildReplayPolicy`, `normalizeToolSchemas`, and `wrapStreamFn`",
docsPath: "/plugins/sdk-provider-plugins",
surfaces: ["ProviderPlugin.capabilities", "ProviderCapabilities"],
diagnostics: ["provider validation warning"],
tests: [
"src/plugins/provider-runtime.test.ts",
"src/plugins/contracts/provider-family-plugin-tests.test.ts",
],
},
{
code: "provider-discovery-type-aliases",
status: "deprecated",
owner: "provider",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement:
"`ProviderCatalogOrder`, `ProviderCatalogContext`, `ProviderCatalogResult`, and `ProviderPluginCatalog`",
docsPath: "/plugins/sdk-migration",
surfaces: [
"ProviderDiscoveryOrder",
"ProviderDiscoveryContext",
"ProviderDiscoveryResult",
"ProviderPluginDiscovery",
],
diagnostics: ["plugin SDK compatibility warning"],
tests: ["src/plugins/contracts/plugin-sdk-index.test.ts"],
},
{
code: "provider-thinking-policy-hooks",
status: "deprecated",
owner: "provider",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "`resolveThinkingProfile`",
docsPath: "/plugins/sdk-provider-plugins",
surfaces: [
"ProviderPlugin.isBinaryThinking",
"ProviderPlugin.supportsXHighThinking",
"ProviderPlugin.resolveDefaultThinkingLevel",
],
diagnostics: ["provider runtime compatibility warning"],
tests: ["src/plugins/provider-runtime.test.ts"],
},
{
code: "provider-external-oauth-profiles-hook",
status: "deprecated",
owner: "provider",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "`contracts.externalAuthProviders` plus `resolveExternalAuthProfiles`",
docsPath: "/plugins/sdk-provider-plugins",
surfaces: ["ProviderPlugin.resolveExternalOAuthProfiles"],
diagnostics: ["provider external auth fallback warning"],
tests: ["src/plugins/provider-runtime.test.ts"],
},
{
code: "agent-tool-result-harness-alias",
status: "deprecated",
owner: "agent-runtime",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "`runtime` and `runtimes` agent tool-result middleware fields",
docsPath: "/plugins/sdk-agent-harness",
surfaces: [
"AgentToolResultMiddlewareHarness",
"AgentToolResultMiddlewareContext.harness",
"AgentToolResultMiddlewareOptions.harnesses",
"normalizeAgentToolResultMiddlewareHarnesses",
],
diagnostics: ["agent runtime compatibility warning"],
tests: [
"src/plugins/captured-registration.test.ts",
"src/agents/codex-app-server.extensions.test.ts",
],
},
{
code: "runtime-taskflow-legacy-alias",
status: "deprecated",
owner: "sdk",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "`api.runtime.tasks.flows`",
docsPath: "/plugins/sdk-runtime",
surfaces: ["api.runtime.taskFlow", "api.runtime.tasks.flow"],
diagnostics: ["plugin runtime compatibility warning"],
tests: ["src/plugins/runtime/index.test.ts", "src/plugins/runtime/runtime-tasks.test.ts"],
},
{
code: "runtime-subagent-get-session-alias",
status: "deprecated",
owner: "sdk",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "`api.runtime.subagent.getSessionMessages`",
docsPath: "/plugins/sdk-runtime",
surfaces: ["api.runtime.subagent.getSession"],
diagnostics: ["plugin runtime compatibility warning"],
tests: ["src/plugins/runtime/index.test.ts"],
},
{
code: "runtime-stt-alias",
status: "deprecated",
owner: "sdk",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "`api.runtime.mediaUnderstanding.transcribeAudioFile`",
docsPath: "/plugins/sdk-runtime",
surfaces: ["api.runtime.stt.transcribeAudioFile"],
diagnostics: ["plugin runtime compatibility warning"],
tests: ["src/plugins/runtime/index.test.ts"],
},
{
code: "runtime-inbound-envelope-alias",
status: "deprecated",
owner: "channel",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "`BodyForAgent` plus structured user-context blocks",
docsPath: "/plugins/sdk-runtime",
surfaces: ["api.runtime.channel.reply.formatInboundEnvelope"],
diagnostics: ["channel runtime compatibility warning"],
tests: ["src/plugins/runtime/index.test.ts"],
},
{
code: "channel-native-message-schema-helpers",
status: "deprecated",
owner: "channel",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "semantic `presentation` capabilities",
docsPath: "/plugins/sdk-migration",
surfaces: [
"openclaw/plugin-sdk/channel-actions createMessageToolButtonsSchema",
"openclaw/plugin-sdk/channel-actions createMessageToolCardSchema",
],
diagnostics: ["plugin SDK compatibility warning"],
tests: ["src/plugins/contracts/plugin-sdk-subpaths.test.ts"],
},
{
code: "channel-mention-gating-legacy-helpers",
status: "deprecated",
owner: "channel",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "`resolveInboundMentionDecision({ facts, policy })`",
docsPath: "/plugins/sdk-migration",
surfaces: [
"openclaw/plugin-sdk/channel-inbound resolveMentionGating",
"openclaw/plugin-sdk/channel-inbound resolveMentionGatingWithBypass",
"openclaw/plugin-sdk/channel-mention-gating resolveMentionGating",
"openclaw/plugin-sdk/channel-mention-gating resolveMentionGatingWithBypass",
],
diagnostics: ["plugin SDK compatibility warning"],
tests: ["src/plugins/contracts/plugin-sdk-subpaths.test.ts"],
},
{
code: "provider-web-search-core-wrapper",
status: "deprecated",
owner: "provider",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "provider-owned `createTool(...)` on the returned `WebSearchProviderPlugin`",
docsPath: "/plugins/sdk-provider-plugins",
surfaces: ["openclaw/plugin-sdk/provider-web-search createPluginBackedWebSearchProvider"],
diagnostics: ["plugin SDK compatibility warning"],
tests: ["src/plugins/contracts/plugin-sdk-subpaths.test.ts"],
},
{
code: "approval-capability-approvals-alias",
status: "deprecated",
owner: "channel",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement:
"top-level `delivery`, `nativeRuntime`, `render`, and `native` approval capability fields",
docsPath: "/plugins/sdk-channel-plugins",
surfaces: ["createChannelApprovalCapability({ approvals })"],
diagnostics: ["plugin SDK compatibility warning"],
tests: ["src/plugin-sdk/approval-delivery-helpers.test.ts"],
},
{
code: "plugin-sdk-test-utils-alias",
status: "deprecated",
owner: "sdk",
introduced: "2026-04-24",
deprecated: "2026-04-26",
warningStarts: "2026-04-26",
removeAfter: "2026-07-26",
replacement: "`openclaw/plugin-sdk/testing`",
docsPath: "/plugins/sdk-migration",
surfaces: ["openclaw/plugin-sdk/test-utils"],
diagnostics: ["plugin SDK compatibility warning"],
tests: ["src/plugins/contracts/plugin-sdk-subpaths.test.ts"],
},
] as const satisfies readonly PluginCompatRecord[];
export type PluginCompatCode = (typeof PLUGIN_COMPAT_RECORDS)[number]["code"];