From 0bd8d0bba08b386ca975510235e00df2139b3e70 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Fri, 24 Apr 2026 18:09:49 -0700 Subject: [PATCH] fix(plugins): remove Pi tool result compat --- CHANGELOG.md | 2 +- .../.generated/plugin-sdk-api-baseline.sha256 | 4 +- docs/plugins/manifest.md | 14 +- docs/plugins/sdk-agent-harness.md | 5 +- docs/plugins/sdk-migration.md | 36 ++- docs/plugins/sdk-overview.md | 35 +-- .../pi-embedded-runner.extensions.test.ts | 254 +----------------- src/agents/pi-embedded-runner/extensions.ts | 2 - src/gateway/server-plugins.test.ts | 1 - src/gateway/test-helpers.plugin-registry.ts | 1 - src/plugins/api-builder.ts | 5 - src/plugins/captured-registration.ts | 7 - src/plugins/embedded-extension-factory.ts | 8 - src/plugins/hooks.test-helpers.ts | 1 - src/plugins/loader.ts | 3 - src/plugins/registry-empty.ts | 1 - src/plugins/registry-types.ts | 10 - src/plugins/registry.ts | 68 ----- src/plugins/status.test-helpers.ts | 1 - src/plugins/types.ts | 17 +- src/test-utils/channel-plugins.ts | 1 - test/helpers/plugins/plugin-api.ts | 1 - 22 files changed, 50 insertions(+), 427 deletions(-) delete mode 100644 src/plugins/embedded-extension-factory.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index ae547a06fda..8164fcb3e38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Docs: https://docs.openclaw.ai ### Breaking -- Plugin SDK/tool-result transforms: deprecate the Pi-only `api.registerEmbeddedExtensionFactory(...)` path for tool-result rewriting in favor of bundled `api.registerAgentToolResultMiddleware(...)`, with `contracts.agentToolResultMiddleware` declaring the targeted harnesses. The legacy Pi hook remains wired as a bundled compatibility seam, but new bundled transforms should use the harness-neutral middleware contract so transforms run consistently across Pi and Codex app-server dynamic tools. Thanks @vincentkoc. +- Plugin SDK/tool-result transforms: remove the Pi-only `api.registerEmbeddedExtensionFactory(...)` compatibility path. Bundled tool-result rewrites must use `api.registerAgentToolResultMiddleware(...)` with `contracts.agentToolResultMiddleware` declaring the targeted harnesses, so transforms run consistently across Pi and Codex app-server dynamic tools. Thanks @vincentkoc. ### Changes diff --git a/docs/.generated/plugin-sdk-api-baseline.sha256 b/docs/.generated/plugin-sdk-api-baseline.sha256 index c258f2848f7..d9316d62c2d 100644 --- a/docs/.generated/plugin-sdk-api-baseline.sha256 +++ b/docs/.generated/plugin-sdk-api-baseline.sha256 @@ -1,2 +1,2 @@ -f74435d49aa0af2509264d8581e12ffc624b1d6542d250d608ee5c3b41a234f3 plugin-sdk-api-baseline.json -df33bbe47bb092ed11814576b5386253140f7aa6f8479a5334aff9b988125afc plugin-sdk-api-baseline.jsonl +1b8ce6687d91267f78f589ee29d4cca0809fde73ea47c82ddbd14ecf54f1803a plugin-sdk-api-baseline.json +55c48203fe5d6409f690f4d27abde41502feec1bfb63d9096cd9958fcf45c2c2 plugin-sdk-api-baseline.jsonl diff --git a/docs/plugins/manifest.md b/docs/plugins/manifest.md index 036d37f24ad..4759be5cc77 100644 --- a/docs/plugins/manifest.md +++ b/docs/plugins/manifest.md @@ -431,7 +431,7 @@ Each list is optional: | Field | Type | What it means | | -------------------------------- | ---------- | --------------------------------------------------------------------- | -| `embeddedExtensionFactories` | `string[]` | Deprecated embedded extension factory ids. | +| `embeddedExtensionFactories` | `string[]` | Codex app-server extension factory ids, currently `codex-app-server`. | | `agentToolResultMiddleware` | `string[]` | Runtime ids a bundled plugin may register tool-result middleware for. | | `externalAuthProviders` | `string[]` | Provider ids whose external auth profile hook this plugin owns. | | `speechProviders` | `string[]` | Speech provider ids this plugin owns. | @@ -445,12 +445,12 @@ Each list is optional: | `webSearchProviders` | `string[]` | Web-search provider ids this plugin owns. | | `tools` | `string[]` | Agent tool names this plugin owns for bundled contract checks. | -`contracts.embeddedExtensionFactories` is retained for bundled compatibility -code that still needs direct Pi embedded-runner events. New bundled -tool-result transforms should declare `contracts.agentToolResultMiddleware` -and register with `api.registerAgentToolResultMiddleware(...)` instead. -External plugins cannot register tool-result middleware because the seam can -rewrite high-trust tool output before the model sees it. +`contracts.embeddedExtensionFactories` is retained for bundled Codex +app-server-only extension factories. Bundled tool-result transforms should +declare `contracts.agentToolResultMiddleware` and register with +`api.registerAgentToolResultMiddleware(...)` instead. External plugins cannot +register tool-result middleware because the seam can rewrite high-trust tool +output before the model sees it. Provider plugins that implement `resolveExternalAuthProfiles` should declare `contracts.externalAuthProviders`. Plugins without the declaration still run diff --git a/docs/plugins/sdk-agent-harness.md b/docs/plugins/sdk-agent-harness.md index b1b5f9cdbff..9f3d8f106d9 100644 --- a/docs/plugins/sdk-agent-harness.md +++ b/docs/plugins/sdk-agent-harness.md @@ -155,9 +155,8 @@ tool output back into the model. Legacy bundled plugins can still use `api.registerCodexAppServerExtensionFactory(...)` for Codex app-server-only middleware, but new result transforms should use the runtime-neutral API. -The Pi-only `api.registerEmbeddedExtensionFactory(...)` hook is deprecated for -tool-result transforms; keep it only for bundled compatibility code that still -needs direct Pi embedded-runner events. +The Pi-only `api.registerEmbeddedExtensionFactory(...)` hook has been removed; +Pi tool-result transforms must use runtime-neutral middleware. ### Native Codex harness mode diff --git a/docs/plugins/sdk-migration.md b/docs/plugins/sdk-migration.md index 262c1ad1d4f..2e824ddbf32 100644 --- a/docs/plugins/sdk-migration.md +++ b/docs/plugins/sdk-migration.md @@ -5,7 +5,7 @@ sidebarTitle: "Migrate to SDK" read_when: - You see the OPENCLAW_PLUGIN_SDK_COMPAT_DEPRECATED warning - You see the OPENCLAW_EXTENSION_API_DEPRECATED warning - - You use api.registerEmbeddedExtensionFactory + - You used api.registerEmbeddedExtensionFactory before OpenClaw 2026.4.24 - You are updating a plugin to the modern plugin architecture - You maintain an external OpenClaw plugin --- @@ -24,12 +24,14 @@ anything they needed from a single entry point: new plugin architecture was being built. - **`openclaw/extension-api`** — a bridge that gave plugins direct access to host-side helpers like the embedded agent runner. -- **`api.registerEmbeddedExtensionFactory(...)`** — a Pi-only bundled extension - hook that could observe embedded-runner events such as `tool_result`. +- **`api.registerEmbeddedExtensionFactory(...)`** — a removed Pi-only bundled + extension hook that could observe embedded-runner events such as + `tool_result`. -These 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. +The broad import 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. The Pi-only embedded extension factory +registration API has been removed; use tool-result middleware instead. OpenClaw does not remove or reinterpret documented plugin behavior in the same change that introduces a replacement. Breaking contract changes must first go @@ -40,6 +42,7 @@ registration behavior. The backwards-compatibility layer will be removed in a future major release. Plugins that still import from these surfaces will break when that happens. + Pi-only embedded extension factory registrations already no longer load. ## Why this changed @@ -91,19 +94,12 @@ releases. - Bundled plugins should replace Pi-only + Bundled plugins must replace Pi-only `api.registerEmbeddedExtensionFactory(...)` tool-result handlers with runtime-neutral middleware. ```typescript - // Before: Pi-only compatibility hook - api.registerEmbeddedExtensionFactory((pi) => { - pi.on("tool_result", async (event) => { - return compactToolResult(event); - }); - }); - - // After: Pi and Codex runtime dynamic tools + // Pi and Codex runtime dynamic tools api.registerAgentToolResultMiddleware(async (event) => { return compactToolResult(event); }, { @@ -121,10 +117,8 @@ releases. } ``` - Keep `contracts.embeddedExtensionFactories` only for bundled compatibility - code that still needs direct Pi embedded-runner events. External plugins - cannot register tool-result middleware because it can rewrite high-trust - tool output before the model sees it. + External plugins cannot register tool-result middleware because it can + rewrite high-trust tool output before the model sees it. @@ -624,8 +618,8 @@ canonical replacement. Covered in "How to migrate → Migrate Pi tool-result extensions to - middleware" above. Included here for completeness: the Pi-only - `api.registerEmbeddedExtensionFactory(...)` path is deprecated in favor of + middleware" above. Included here for completeness: the removed Pi-only + `api.registerEmbeddedExtensionFactory(...)` path is replaced by `api.registerAgentToolResultMiddleware(...)` with an explicit runtime list in `contracts.agentToolResultMiddleware`. diff --git a/docs/plugins/sdk-overview.md b/docs/plugins/sdk-overview.md index f1671fe0911..b96e58c2ca2 100644 --- a/docs/plugins/sdk-overview.md +++ b/docs/plugins/sdk-overview.md @@ -96,19 +96,18 @@ methods: ### Infrastructure -| Method | What it registers | -| ----------------------------------------------- | --------------------------------------- | -| `api.registerHook(events, handler, opts?)` | Event hook | -| `api.registerHttpRoute(params)` | Gateway HTTP endpoint | -| `api.registerGatewayMethod(name, handler)` | Gateway RPC method | -| `api.registerGatewayDiscoveryService(service)` | Local Gateway discovery advertiser | -| `api.registerCli(registrar, opts?)` | CLI subcommand | -| `api.registerService(service)` | Background service | -| `api.registerInteractiveHandler(registration)` | Interactive handler | -| `api.registerAgentToolResultMiddleware(...)` | Runtime tool-result middleware | -| `api.registerEmbeddedExtensionFactory(factory)` | Deprecated PI extension factory | -| `api.registerMemoryPromptSupplement(builder)` | Additive memory-adjacent prompt section | -| `api.registerMemoryCorpusSupplement(adapter)` | Additive memory search/read corpus | +| Method | What it registers | +| ---------------------------------------------- | --------------------------------------- | +| `api.registerHook(events, handler, opts?)` | Event hook | +| `api.registerHttpRoute(params)` | Gateway HTTP endpoint | +| `api.registerGatewayMethod(name, handler)` | Gateway RPC method | +| `api.registerGatewayDiscoveryService(service)` | Local Gateway discovery advertiser | +| `api.registerCli(registrar, opts?)` | CLI subcommand | +| `api.registerService(service)` | Background service | +| `api.registerInteractiveHandler(registration)` | Interactive handler | +| `api.registerAgentToolResultMiddleware(...)` | Runtime tool-result middleware | +| `api.registerMemoryPromptSupplement(builder)` | Additive memory-adjacent prompt section | +| `api.registerMemoryCorpusSupplement(adapter)` | Additive memory search/read corpus | Reserved core admin namespaces (`config.*`, `exec.approvals.*`, `wizard.*`, @@ -126,14 +125,8 @@ methods: Bundled plugins must declare `contracts.agentToolResultMiddleware` for each targeted runtime, for example `["pi", "codex"]`. External plugins cannot register this middleware; keep normal OpenClaw plugin hooks for work -that does not need pre-model tool-result timing. - - - - `api.registerEmbeddedExtensionFactory(...)` is deprecated. It remains a - compatibility seam for bundled plugins that still need direct Pi - embedded-runner events. New tool-result transforms should use - `api.registerAgentToolResultMiddleware(...)` instead. +that does not need pre-model tool-result timing. The old Pi-only embedded +extension factory registration path has been removed. ### Gateway discovery registration diff --git a/src/agents/pi-embedded-runner.extensions.test.ts b/src/agents/pi-embedded-runner.extensions.test.ts index c0fcd9df93b..dc949aed8cc 100644 --- a/src/agents/pi-embedded-runner.extensions.test.ts +++ b/src/agents/pi-embedded-runner.extensions.test.ts @@ -1,24 +1,13 @@ import { SessionManager } from "@mariozechner/pi-coding-agent"; import { afterEach, describe, expect, it } from "vitest"; -import { listEmbeddedExtensionFactories } from "../plugins/embedded-extension-factory.js"; -import { loadOpenClawPlugins } from "../plugins/loader.js"; import { createEmptyPluginRegistry } from "../plugins/registry.js"; import { setActivePluginRegistry } from "../plugins/runtime.js"; import { buildEmbeddedExtensionFactories } from "./pi-embedded-runner/extensions.js"; -import { - cleanupTempPluginTestEnvironment, - createTempPluginDir, - resetActivePluginRegistryForTest, - writeTempPlugin, -} from "./test-helpers/temp-plugin-extension-fixtures.js"; +import { cleanupTempPluginTestEnvironment } from "./test-helpers/temp-plugin-extension-fixtures.js"; const originalBundledPluginsDir = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR; const tempDirs: string[] = []; -function createTempDir(): string { - return createTempPluginDir(tempDirs, "openclaw-embedded-ext-"); -} - afterEach(() => { cleanupTempPluginTestEnvironment(tempDirs, originalBundledPluginsDir); }); @@ -80,245 +69,4 @@ describe("buildEmbeddedExtensionFactories", () => { expect(seenToolCallIds[1]).toMatch(/^pi-/); expect(seenToolCallIds[0]).not.toBe(seenToolCallIds[1]); }); - - it("includes plugin-registered embedded extension factories and restores them from cache", async () => { - const tmp = createTempDir(); - process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = tmp; - - writeTempPlugin({ - dir: tmp, - id: "embedded-ext", - filename: "index.mjs", - manifest: { - contracts: { - embeddedExtensionFactories: ["pi"], - }, - }, - body: `export default { id: "embedded-ext", register(api) { - api.registerEmbeddedExtensionFactory((pi) => { - pi.on("session_start", () => undefined); - }); -} };`, - }); - - const options = { - config: { - plugins: { - entries: { - "embedded-ext": { - enabled: true, - }, - }, - }, - }, - }; - - loadOpenClawPlugins(options); - - const firstFactories = buildEmbeddedExtensionFactories({ - cfg: undefined, - sessionManager: SessionManager.inMemory(), - provider: "openai", - modelId: "gpt-5.4", - model: undefined, - }); - expect(firstFactories).toHaveLength(2); - expect(listEmbeddedExtensionFactories()).toHaveLength(1); - - resetActivePluginRegistryForTest(); - expect(listEmbeddedExtensionFactories()).toHaveLength(0); - - loadOpenClawPlugins(options); - - const cachedFactories = buildEmbeddedExtensionFactories({ - cfg: undefined, - sessionManager: SessionManager.inMemory(), - provider: "openai", - modelId: "gpt-5.4", - model: undefined, - }); - expect(cachedFactories).toHaveLength(2); - - const handlers = new Map(); - await cachedFactories[1]?.({ - on(event: string, handler: Function) { - handlers.set(event, handler); - }, - } as never); - expect(handlers.has("session_start")).toBe(true); - }); - - it("rejects embedded extension factories from non-bundled plugins even when they declare the Pi manifest contract", () => { - const tmp = createTempDir(); - process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins"; - - const pluginFile = writeTempPlugin({ - dir: tmp, - id: "embedded-ext", - manifest: { - contracts: { - embeddedExtensionFactories: ["pi"], - }, - }, - body: `export default { id: "embedded-ext", register(api) { - api.registerEmbeddedExtensionFactory((pi) => { - pi.on("session_start", () => undefined); - }); -} };`, - }); - - const registry = loadOpenClawPlugins({ - workspaceDir: tmp, - config: { - plugins: { - load: { paths: [pluginFile] }, - allow: ["embedded-ext"], - }, - }, - }); - - expect(registry.diagnostics).toContainEqual( - expect.objectContaining({ - level: "error", - pluginId: "embedded-ext", - message: "only bundled plugins can register Pi embedded extension factories", - }), - ); - expect(listEmbeddedExtensionFactories()).toHaveLength(0); - expect( - buildEmbeddedExtensionFactories({ - cfg: undefined, - sessionManager: SessionManager.inMemory(), - provider: "openai", - modelId: "gpt-5.4", - model: undefined, - }), - ).toHaveLength(1); - }); - - it("rejects bundled plugins that omit the Pi embedded extension manifest contract", () => { - const tmp = createTempDir(); - process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = tmp; - - writeTempPlugin({ - dir: tmp, - id: "embedded-ext", - filename: "index.mjs", - body: `export default { id: "embedded-ext", register(api) { - api.registerEmbeddedExtensionFactory((pi) => { - pi.on("session_start", () => undefined); - }); -} };`, - }); - - const registry = loadOpenClawPlugins({ - config: { - plugins: { - entries: { - "embedded-ext": { - enabled: true, - }, - }, - }, - }, - }); - - expect(registry.diagnostics).toContainEqual( - expect.objectContaining({ - level: "error", - pluginId: "embedded-ext", - message: - 'plugin must declare contracts.embeddedExtensionFactories: ["pi"] to register Pi embedded extension factories', - }), - ); - expect(listEmbeddedExtensionFactories()).toHaveLength(0); - }); - - it("rejects non-function embedded extension factories from bundled plugins", () => { - const tmp = createTempDir(); - process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = tmp; - - writeTempPlugin({ - dir: tmp, - id: "embedded-ext", - filename: "index.mjs", - manifest: { - contracts: { - embeddedExtensionFactories: ["pi"], - }, - }, - body: `export default { id: "embedded-ext", register(api) { - api.registerEmbeddedExtensionFactory("not-a-function"); -} };`, - }); - - const registry = loadOpenClawPlugins({ - config: { - plugins: { - entries: { - "embedded-ext": { - enabled: true, - }, - }, - }, - }, - }); - - expect(registry.diagnostics).toContainEqual( - expect.objectContaining({ - level: "error", - pluginId: "embedded-ext", - message: "embedded extension factory must be a function", - }), - ); - expect(listEmbeddedExtensionFactories()).toHaveLength(0); - }); - - it("contains embedded extension factory failures so one bad plugin cannot crash setup", async () => { - const tmp = createTempDir(); - process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = tmp; - - writeTempPlugin({ - dir: tmp, - id: "embedded-ext", - filename: "index.mjs", - manifest: { - contracts: { - embeddedExtensionFactories: ["pi"], - }, - }, - body: `export default { id: "embedded-ext", register(api) { - api.registerEmbeddedExtensionFactory(() => { - throw new Error("boom"); - }); -} };`, - }); - - loadOpenClawPlugins({ - config: { - plugins: { - entries: { - "embedded-ext": { - enabled: true, - }, - }, - }, - }, - }); - - const factories = buildEmbeddedExtensionFactories({ - cfg: undefined, - sessionManager: SessionManager.inMemory(), - provider: "openai", - modelId: "gpt-5.4", - model: undefined, - }); - expect(factories).toHaveLength(2); - - await expect( - factories[1]?.({ - on() {}, - } as never), - ).resolves.toBeUndefined(); - }); }); diff --git a/src/agents/pi-embedded-runner/extensions.ts b/src/agents/pi-embedded-runner/extensions.ts index 067f101cf5f..483786d4414 100644 --- a/src/agents/pi-embedded-runner/extensions.ts +++ b/src/agents/pi-embedded-runner/extensions.ts @@ -3,7 +3,6 @@ import type { AgentToolResult } from "@mariozechner/pi-agent-core"; import type { ExtensionFactory, SessionManager } from "@mariozechner/pi-coding-agent"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; import { listAgentToolResultMiddlewares } from "../../plugins/agent-tool-result-middleware.js"; -import { listEmbeddedExtensionFactories } from "../../plugins/embedded-extension-factory.js"; import type { ProviderRuntimeModel } from "../../plugins/provider-runtime-model.types.js"; import { resolveContextWindowInfo } from "../context-window-guard.js"; import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js"; @@ -176,7 +175,6 @@ export function buildEmbeddedExtensionFactories(params: { factories.push(pruningFactory); } factories.push(buildAgentToolResultMiddlewareFactory()); - factories.push(...listEmbeddedExtensionFactories()); return factories; } diff --git a/src/gateway/server-plugins.test.ts b/src/gateway/server-plugins.test.ts index 7a32eabccc1..5fdcb06d898 100644 --- a/src/gateway/server-plugins.test.ts +++ b/src/gateway/server-plugins.test.ts @@ -88,7 +88,6 @@ const createRegistry = (diagnostics: PluginDiagnostic[]): PluginRegistry => ({ webFetchProviders: [], webSearchProviders: [], memoryEmbeddingProviders: [], - embeddedExtensionFactories: [], codexAppServerExtensionFactories: [], agentToolResultMiddlewares: [], textTransforms: [], diff --git a/src/gateway/test-helpers.plugin-registry.ts b/src/gateway/test-helpers.plugin-registry.ts index 70462336d16..8aa03fd6f2d 100644 --- a/src/gateway/test-helpers.plugin-registry.ts +++ b/src/gateway/test-helpers.plugin-registry.ts @@ -22,7 +22,6 @@ function createStubPluginRegistry(): PluginRegistry { musicGenerationProviders: [], webFetchProviders: [], webSearchProviders: [], - embeddedExtensionFactories: [], codexAppServerExtensionFactories: [], agentToolResultMiddlewares: [], memoryEmbeddingProviders: [], diff --git a/src/plugins/api-builder.ts b/src/plugins/api-builder.ts index 1bba2e148c8..84d6d827ad5 100644 --- a/src/plugins/api-builder.ts +++ b/src/plugins/api-builder.ts @@ -49,7 +49,6 @@ export type BuildPluginApiParams = { | "registerContextEngine" | "registerCompactionProvider" | "registerAgentHarness" - | "registerEmbeddedExtensionFactory" | "registerCodexAppServerExtensionFactory" | "registerAgentToolResultMiddleware" | "registerDetachedTaskRuntime" @@ -105,8 +104,6 @@ const noopRegisterCommand: OpenClawPluginApi["registerCommand"] = () => {}; const noopRegisterContextEngine: OpenClawPluginApi["registerContextEngine"] = () => {}; const noopRegisterCompactionProvider: OpenClawPluginApi["registerCompactionProvider"] = () => {}; const noopRegisterAgentHarness: OpenClawPluginApi["registerAgentHarness"] = () => {}; -const noopRegisterEmbeddedExtensionFactory: OpenClawPluginApi["registerEmbeddedExtensionFactory"] = - () => {}; const noopRegisterCodexAppServerExtensionFactory: OpenClawPluginApi["registerCodexAppServerExtensionFactory"] = () => {}; const noopRegisterAgentToolResultMiddleware: OpenClawPluginApi["registerAgentToolResultMiddleware"] = @@ -180,8 +177,6 @@ export function buildPluginApi(params: BuildPluginApiParams): OpenClawPluginApi registerCompactionProvider: handlers.registerCompactionProvider ?? noopRegisterCompactionProvider, registerAgentHarness: handlers.registerAgentHarness ?? noopRegisterAgentHarness, - registerEmbeddedExtensionFactory: - handlers.registerEmbeddedExtensionFactory ?? noopRegisterEmbeddedExtensionFactory, registerCodexAppServerExtensionFactory: handlers.registerCodexAppServerExtensionFactory ?? noopRegisterCodexAppServerExtensionFactory, registerAgentToolResultMiddleware: diff --git a/src/plugins/captured-registration.ts b/src/plugins/captured-registration.ts index 02605d426cc..7bbba7dbbca 100644 --- a/src/plugins/captured-registration.ts +++ b/src/plugins/captured-registration.ts @@ -1,4 +1,3 @@ -import type { ExtensionFactory } from "@mariozechner/pi-coding-agent"; import type { OpenClawConfig } from "../config/types.openclaw.js"; import type { AgentToolResultMiddleware, @@ -43,7 +42,6 @@ export type CapturedPluginRegistration = { cliRegistrars: CapturedPluginCliRegistration[]; cliBackends: CliBackendPlugin[]; textTransforms: PluginTextTransformRegistration[]; - embeddedExtensionFactories: ExtensionFactory[]; codexAppServerExtensionFactories: CodexAppServerExtensionFactory[]; agentToolResultMiddlewares: PluginAgentToolResultMiddlewareRegistration[]; speechProviders: SpeechProviderPlugin[]; @@ -68,7 +66,6 @@ export function createCapturedPluginRegistration(params?: { const cliRegistrars: CapturedPluginCliRegistration[] = []; const cliBackends: CliBackendPlugin[] = []; const textTransforms: PluginTextTransformRegistration[] = []; - const embeddedExtensionFactories: ExtensionFactory[] = []; const codexAppServerExtensionFactories: CodexAppServerExtensionFactory[] = []; const agentToolResultMiddlewares: PluginAgentToolResultMiddlewareRegistration[] = []; const speechProviders: SpeechProviderPlugin[] = []; @@ -95,7 +92,6 @@ export function createCapturedPluginRegistration(params?: { cliRegistrars, cliBackends, textTransforms, - embeddedExtensionFactories, codexAppServerExtensionFactories, agentToolResultMiddlewares, speechProviders, @@ -148,9 +144,6 @@ export function createCapturedPluginRegistration(params?: { registerAgentHarness(harness: AgentHarness) { agentHarnesses.push(harness); }, - registerEmbeddedExtensionFactory(factory: ExtensionFactory) { - embeddedExtensionFactories.push(factory); - }, registerCodexAppServerExtensionFactory(factory: CodexAppServerExtensionFactory) { codexAppServerExtensionFactories.push(factory); }, diff --git a/src/plugins/embedded-extension-factory.ts b/src/plugins/embedded-extension-factory.ts deleted file mode 100644 index 6348b70e52a..00000000000 --- a/src/plugins/embedded-extension-factory.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { ExtensionFactory } from "@mariozechner/pi-coding-agent"; -import { getActivePluginRegistry } from "./runtime.js"; - -export const PI_EMBEDDED_EXTENSION_RUNTIME_ID = "pi"; - -export function listEmbeddedExtensionFactories(): ExtensionFactory[] { - return getActivePluginRegistry()?.embeddedExtensionFactories?.map((entry) => entry.factory) ?? []; -} diff --git a/src/plugins/hooks.test-helpers.ts b/src/plugins/hooks.test-helpers.ts index 91e817f88d8..12ea7b8bcb3 100644 --- a/src/plugins/hooks.test-helpers.ts +++ b/src/plugins/hooks.test-helpers.ts @@ -42,7 +42,6 @@ export function createMockPluginRegistry( musicGenerationProviders: [], webFetchProviders: [], webSearchProviders: [], - embeddedExtensionFactories: [], codexAppServerExtensionFactories: [], agentToolResultMiddlewares: [], memoryEmbeddingProviders: [], diff --git a/src/plugins/loader.ts b/src/plugins/loader.ts index 7196b44d860..0d34e3e92c4 100644 --- a/src/plugins/loader.ts +++ b/src/plugins/loader.ts @@ -292,7 +292,6 @@ type PluginRegistrySnapshot = { musicGenerationProviders: PluginRegistry["musicGenerationProviders"]; webFetchProviders: PluginRegistry["webFetchProviders"]; webSearchProviders: PluginRegistry["webSearchProviders"]; - embeddedExtensionFactories: PluginRegistry["embeddedExtensionFactories"]; codexAppServerExtensionFactories: PluginRegistry["codexAppServerExtensionFactories"]; agentToolResultMiddlewares: PluginRegistry["agentToolResultMiddlewares"]; memoryEmbeddingProviders: PluginRegistry["memoryEmbeddingProviders"]; @@ -331,7 +330,6 @@ function snapshotPluginRegistry(registry: PluginRegistry): PluginRegistrySnapsho musicGenerationProviders: [...registry.musicGenerationProviders], webFetchProviders: [...registry.webFetchProviders], webSearchProviders: [...registry.webSearchProviders], - embeddedExtensionFactories: [...registry.embeddedExtensionFactories], codexAppServerExtensionFactories: [...registry.codexAppServerExtensionFactories], agentToolResultMiddlewares: [...registry.agentToolResultMiddlewares], memoryEmbeddingProviders: [...registry.memoryEmbeddingProviders], @@ -369,7 +367,6 @@ function restorePluginRegistry(registry: PluginRegistry, snapshot: PluginRegistr registry.musicGenerationProviders = snapshot.arrays.musicGenerationProviders; registry.webFetchProviders = snapshot.arrays.webFetchProviders; registry.webSearchProviders = snapshot.arrays.webSearchProviders; - registry.embeddedExtensionFactories = snapshot.arrays.embeddedExtensionFactories; registry.codexAppServerExtensionFactories = snapshot.arrays.codexAppServerExtensionFactories; registry.agentToolResultMiddlewares = snapshot.arrays.agentToolResultMiddlewares; registry.memoryEmbeddingProviders = snapshot.arrays.memoryEmbeddingProviders; diff --git a/src/plugins/registry-empty.ts b/src/plugins/registry-empty.ts index 96145873390..96d77148d28 100644 --- a/src/plugins/registry-empty.ts +++ b/src/plugins/registry-empty.ts @@ -20,7 +20,6 @@ export function createEmptyPluginRegistry(): PluginRegistry { musicGenerationProviders: [], webFetchProviders: [], webSearchProviders: [], - embeddedExtensionFactories: [], codexAppServerExtensionFactories: [], agentToolResultMiddlewares: [], memoryEmbeddingProviders: [], diff --git a/src/plugins/registry-types.ts b/src/plugins/registry-types.ts index 1c313a048a8..223ed429070 100644 --- a/src/plugins/registry-types.ts +++ b/src/plugins/registry-types.ts @@ -1,4 +1,3 @@ -import type { ExtensionFactory } from "@mariozechner/pi-coding-agent"; import type { AgentHarness } from "../agents/harness/types.js"; import type { ChannelPlugin } from "../channels/plugins/types.plugin.js"; import type { OperatorScope } from "../gateway/operator-scopes.js"; @@ -152,14 +151,6 @@ export type PluginWebSearchProviderRegistration = PluginOwnedProviderRegistration; export type PluginMemoryEmbeddingProviderRegistration = PluginOwnedProviderRegistration; -export type PluginEmbeddedExtensionFactoryRegistration = { - pluginId: string; - pluginName?: string; - rawFactory: ExtensionFactory; - factory: ExtensionFactory; - source: string; - rootDir?: string; -}; export type PluginCodexAppServerExtensionFactoryRegistration = { pluginId: string; pluginName?: string; @@ -323,7 +314,6 @@ export type PluginRegistry = { musicGenerationProviders: PluginMusicGenerationProviderRegistration[]; webFetchProviders: PluginWebFetchProviderRegistration[]; webSearchProviders: PluginWebSearchProviderRegistration[]; - embeddedExtensionFactories: PluginEmbeddedExtensionFactoryRegistration[]; codexAppServerExtensionFactories: PluginCodexAppServerExtensionFactoryRegistration[]; agentToolResultMiddlewares: PluginAgentToolResultMiddlewareRegistration[]; memoryEmbeddingProviders: PluginMemoryEmbeddingProviderRegistration[]; diff --git a/src/plugins/registry.ts b/src/plugins/registry.ts index 75bfad6a3f6..54e0ad6519d 100644 --- a/src/plugins/registry.ts +++ b/src/plugins/registry.ts @@ -1,5 +1,4 @@ import path from "node:path"; -import type { ExtensionFactory } from "@mariozechner/pi-coding-agent"; import { getRegisteredAgentHarness, registerAgentHarness as registerGlobalAgentHarness, @@ -43,7 +42,6 @@ import { getRegisteredCompactionProvider, registerCompactionProvider, } from "./compaction-provider.js"; -import { PI_EMBEDDED_EXTENSION_RUNTIME_ID } from "./embedded-extension-factory.js"; import { normalizePluginHttpPath } from "./http-path.js"; import { findOverlappingPluginHttpRoute } from "./http-route-overlap.js"; import { @@ -229,69 +227,6 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) { registry.diagnostics.push(diag); }; - const registerPiEmbeddedExtensionFactory = ( - record: PluginRecord, - factory: Parameters[0], - ) => { - if (record.origin !== "bundled") { - pushDiagnostic({ - level: "error", - pluginId: record.id, - source: record.source, - message: "only bundled plugins can register Pi embedded extension factories", - }); - return; - } - if ( - !(record.contracts?.embeddedExtensionFactories ?? []).includes( - PI_EMBEDDED_EXTENSION_RUNTIME_ID, - ) - ) { - pushDiagnostic({ - level: "error", - pluginId: record.id, - source: record.source, - message: - 'plugin must declare contracts.embeddedExtensionFactories: ["pi"] to register Pi embedded extension factories', - }); - return; - } - if (typeof (factory as unknown) !== "function") { - pushDiagnostic({ - level: "error", - pluginId: record.id, - source: record.source, - message: "embedded extension factory must be a function", - }); - return; - } - if ( - registry.embeddedExtensionFactories.some( - (entry) => entry.pluginId === record.id && entry.rawFactory === factory, - ) - ) { - return; - } - const safeFactory: ExtensionFactory = async (pi) => { - try { - await factory(pi); - } catch (error) { - const detail = error instanceof Error ? error.message : String(error); - registryParams.logger.warn( - `[plugins] embedded extension factory failed for ${record.id}: ${detail}`, - ); - } - }; - registry.embeddedExtensionFactories.push({ - pluginId: record.id, - pluginName: record.name, - rawFactory: factory, - factory: safeFactory, - source: record.source, - rootDir: record.rootDir, - }); - }; - const registerCodexAppServerExtensionFactory = ( record: PluginRecord, factory: Parameters[0], @@ -1585,9 +1520,6 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) { } registerCompactionProvider(provider, { ownerPluginId: record.id }); }, - registerEmbeddedExtensionFactory: (factory) => { - registerPiEmbeddedExtensionFactory(record, factory); - }, registerCodexAppServerExtensionFactory: (factory) => { registerCodexAppServerExtensionFactory(record, factory); }, diff --git a/src/plugins/status.test-helpers.ts b/src/plugins/status.test-helpers.ts index a00068d5cbd..d51746e7d77 100644 --- a/src/plugins/status.test-helpers.ts +++ b/src/plugins/status.test-helpers.ts @@ -129,7 +129,6 @@ export function createPluginLoadResult( musicGenerationProviders: [], webFetchProviders: [], webSearchProviders: [], - embeddedExtensionFactories: [], codexAppServerExtensionFactories: [], agentToolResultMiddlewares: [], memoryEmbeddingProviders: [], diff --git a/src/plugins/types.ts b/src/plugins/types.ts index 67c6de1ec1e..d802bdc4204 100644 --- a/src/plugins/types.ts +++ b/src/plugins/types.ts @@ -1,7 +1,7 @@ import type { IncomingMessage, ServerResponse } from "node:http"; import type { AgentMessage } from "@mariozechner/pi-agent-core"; import type { StreamFn } from "@mariozechner/pi-agent-core"; -import type { ExtensionFactory, ModelRegistry } from "@mariozechner/pi-coding-agent"; +import type { ModelRegistry } from "@mariozechner/pi-coding-agent"; import type { Command } from "commander"; import type { ApiKeyCredential, @@ -2152,16 +2152,15 @@ export type OpenClawPluginApi = { /** Register an agent harness implementation. */ registerAgentHarness: (harness: AgentHarness) => void; /** - * Register a Pi embedded extension factory for OpenClaw embedded runs. - * - * @deprecated This is a bundled compatibility seam. New tool-result transforms - * should use `registerAgentToolResultMiddleware(...)` and declare - * `contracts.agentToolResultMiddleware` for the targeted runtimes. + * Register a Codex app-server extension factory for Codex harness tool-result + * middleware. Only bundled plugins may use this seam, and + * `contracts.embeddedExtensionFactories` must include `"codex-app-server"`. */ - registerEmbeddedExtensionFactory: (factory: ExtensionFactory) => void; - /** Register a Codex app-server extension factory for Codex harness tool-result middleware. Only bundled plugins may use this seam, and `contracts.embeddedExtensionFactories` must include `"codex-app-server"`. */ registerCodexAppServerExtensionFactory: (factory: CodexAppServerExtensionFactory) => void; - /** Register runtime-neutral tool-result middleware. Declare `contracts.agentToolResultMiddleware` for every targeted runtime. */ + /** + * Register runtime-neutral tool-result middleware. Declare + * `contracts.agentToolResultMiddleware` for every targeted runtime. + */ registerAgentToolResultMiddleware: ( handler: AgentToolResultMiddleware, options?: AgentToolResultMiddlewareOptions, diff --git a/src/test-utils/channel-plugins.ts b/src/test-utils/channel-plugins.ts index ea73178109a..53062f220f9 100644 --- a/src/test-utils/channel-plugins.ts +++ b/src/test-utils/channel-plugins.ts @@ -35,7 +35,6 @@ export const createTestRegistry = (channels: TestChannelRegistration[] = []): Pl musicGenerationProviders: [], webFetchProviders: [], webSearchProviders: [], - embeddedExtensionFactories: [], codexAppServerExtensionFactories: [], agentToolResultMiddlewares: [], memoryEmbeddingProviders: [], diff --git a/test/helpers/plugins/plugin-api.ts b/test/helpers/plugins/plugin-api.ts index 7c2ec4890cc..e8fed03cf37 100644 --- a/test/helpers/plugins/plugin-api.ts +++ b/test/helpers/plugins/plugin-api.ts @@ -42,7 +42,6 @@ export function createTestPluginApi(api: TestPluginApiInput = {}): OpenClawPlugi registerContextEngine() {}, registerCompactionProvider() {}, registerAgentHarness() {}, - registerEmbeddedExtensionFactory() {}, registerCodexAppServerExtensionFactory() {}, registerAgentToolResultMiddleware() {}, registerDetachedTaskRuntime() {},