From 5a81c4000c779c30868b8105bf5c9538cc3ffe75 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 27 Apr 2026 11:46:57 +0100 Subject: [PATCH] chore: tighten plugin boundary export audit --- docs/plugins/architecture.md | 2 + package.json | 4 + packages/plugin-sdk/package.json | 4 + .../check-extension-plugin-sdk-boundary.mjs | 10 +- scripts/lib/plugin-sdk-entrypoints.json | 1 + ...on-relative-outside-package-inventory.json | 202 ------------------ 6 files changed, 12 insertions(+), 211 deletions(-) delete mode 100644 test/fixtures/extension-relative-outside-package-inventory.json diff --git a/docs/plugins/architecture.md b/docs/plugins/architecture.md index 214561c27b1..a2a16ecb2c0 100644 --- a/docs/plugins/architecture.md +++ b/docs/plugins/architecture.md @@ -208,6 +208,8 @@ For channel-owned execution helpers, bundled plugins should keep the execution r The same boundary applies to provider-named SDK seams in general: core should not import channel-specific convenience barrels for Slack, Discord, Signal, WhatsApp, or similar extensions. If core needs a behavior, either consume the bundled plugin's own `api.ts` / `runtime-api.ts` barrel or promote the need into a narrow generic capability in the shared SDK. +Bundled plugins follow the same rule. A bundled plugin's `runtime-api.ts` should not re-export its own branded `openclaw/plugin-sdk/` facade. Those branded facades remain compatibility shims for external plugins and older consumers, but bundled plugins should use local exports plus narrow generic SDK subpaths such as `openclaw/plugin-sdk/channel-policy`, `openclaw/plugin-sdk/runtime-store`, or `openclaw/plugin-sdk/webhook-ingress`. New code should not add plugin-id-specific SDK facades unless the compatibility boundary for an existing external ecosystem requires it. + For polls specifically, there are two execution paths: - `outbound.sendPoll` is the shared baseline for channels that fit the common poll model diff --git a/package.json b/package.json index bb7191b85a4..548504bac5c 100644 --- a/package.json +++ b/package.json @@ -338,6 +338,10 @@ "types": "./dist/plugin-sdk/speech-core.d.ts", "default": "./dist/plugin-sdk/speech-core.js" }, + "./plugin-sdk/tts-runtime": { + "types": "./dist/plugin-sdk/tts-runtime.d.ts", + "default": "./dist/plugin-sdk/tts-runtime.js" + }, "./plugin-sdk/plugin-runtime": { "types": "./dist/plugin-sdk/plugin-runtime.d.ts", "default": "./dist/plugin-sdk/plugin-runtime.js" diff --git a/packages/plugin-sdk/package.json b/packages/plugin-sdk/package.json index f6e6bc7b46b..b00ab5a3dee 100644 --- a/packages/plugin-sdk/package.json +++ b/packages/plugin-sdk/package.json @@ -144,6 +144,10 @@ "types": "./dist/src/plugin-sdk/text-runtime.d.ts", "default": "./src/text-runtime.ts" }, + "./tts-runtime": { + "types": "./dist/src/plugin-sdk/tts-runtime.d.ts", + "default": "./src/tts-runtime.ts" + }, "./testing": { "types": "./dist/src/plugin-sdk/testing.d.ts", "default": "./src/testing.ts" diff --git a/scripts/check-extension-plugin-sdk-boundary.mjs b/scripts/check-extension-plugin-sdk-boundary.mjs index 7e552a13454..4bd08a612a1 100644 --- a/scripts/check-extension-plugin-sdk-boundary.mjs +++ b/scripts/check-extension-plugin-sdk-boundary.mjs @@ -38,12 +38,6 @@ const baselinePathByMode = { "fixtures", "extension-plugin-sdk-internal-inventory.json", ), - "relative-outside-package": path.join( - repoRoot, - "test", - "fixtures", - "extension-relative-outside-package-inventory.json", - ), }; let allInventoryByModePromise; @@ -264,9 +258,7 @@ export async function readExpectedInventory(mode) { return JSON.parse(await fs.readFile(baselinePathByMode[mode], "utf8")); } catch (error) { if ( - (mode === "plugin-sdk-internal" || - mode === "src-outside-plugin-sdk" || - mode === "relative-outside-package") && + (mode === "plugin-sdk-internal" || mode === "src-outside-plugin-sdk") && error && typeof error === "object" && "code" in error && diff --git a/scripts/lib/plugin-sdk-entrypoints.json b/scripts/lib/plugin-sdk-entrypoints.json index 38bfeb1ebed..5556b77f98a 100644 --- a/scripts/lib/plugin-sdk-entrypoints.json +++ b/scripts/lib/plugin-sdk-entrypoints.json @@ -68,6 +68,7 @@ "agent-runtime", "simple-completion-runtime", "speech-core", + "tts-runtime", "plugin-runtime", "skills-runtime", "channel-secret-basic-runtime", diff --git a/test/fixtures/extension-relative-outside-package-inventory.json b/test/fixtures/extension-relative-outside-package-inventory.json deleted file mode 100644 index 0f932579b0f..00000000000 --- a/test/fixtures/extension-relative-outside-package-inventory.json +++ /dev/null @@ -1,202 +0,0 @@ -[ - { - "file": "extensions/bluebubbles/src/runtime-api.ts", - "line": 1, - "kind": "export", - "specifier": "../../../src/plugin-sdk/bluebubbles.js", - "resolvedPath": "src/plugin-sdk/bluebubbles.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/bluebubbles/src/targets.ts", - "line": 8, - "kind": "import", - "specifier": "../../imessage/api.js", - "resolvedPath": "extensions/imessage/api.js", - "reason": "imports another extension via relative path outside the extension package" - }, - { - "file": "extensions/feishu/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/feishu.js", - "resolvedPath": "src/plugin-sdk/feishu.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/googlechat.js", - "resolvedPath": "src/plugin-sdk/googlechat.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/imessage/runtime-api.ts", - "line": 16, - "kind": "export", - "specifier": "../../src/plugin-sdk/imessage.js", - "resolvedPath": "src/plugin-sdk/imessage.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/irc/src/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../../src/plugin-sdk/irc.js", - "resolvedPath": "src/plugin-sdk/irc.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/line/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/line.js", - "resolvedPath": "src/plugin-sdk/line.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/line/runtime-api.ts", - "line": 13, - "kind": "export", - "specifier": "../../src/plugin-sdk/line-core.js", - "resolvedPath": "src/plugin-sdk/line-core.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/matrix/runtime-api.ts", - "line": 19, - "kind": "export", - "specifier": "../../src/plugin-sdk/json-store.js", - "resolvedPath": "src/plugin-sdk/json-store.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/matrix/runtime-api.ts", - "line": 28, - "kind": "export", - "specifier": "../../src/plugin-sdk/matrix.js", - "resolvedPath": "src/plugin-sdk/matrix.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/matrix/runtime-api.ts", - "line": 29, - "kind": "export", - "specifier": "../../src/plugin-sdk/matrix.js", - "resolvedPath": "src/plugin-sdk/matrix.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/matrix/src/runtime-api.ts", - "line": 1, - "kind": "export", - "specifier": "../../../src/plugin-sdk/matrix.js", - "resolvedPath": "src/plugin-sdk/matrix.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/mattermost/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/mattermost.js", - "resolvedPath": "src/plugin-sdk/mattermost.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/msteams/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/msteams.js", - "resolvedPath": "src/plugin-sdk/msteams.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/nextcloud-talk/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/nextcloud-talk.js", - "resolvedPath": "src/plugin-sdk/nextcloud-talk.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/nostr/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/nostr.js", - "resolvedPath": "src/plugin-sdk/nostr.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/telegram/runtime-api.ts", - "line": 10, - "kind": "export", - "specifier": "../../src/plugin-sdk/telegram.js", - "resolvedPath": "src/plugin-sdk/telegram.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/telegram/runtime-api.ts", - "line": 40, - "kind": "export", - "specifier": "../../src/plugin-sdk/telegram.js", - "resolvedPath": "src/plugin-sdk/telegram.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/tlon/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/tlon.js", - "resolvedPath": "src/plugin-sdk/tlon.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/twitch/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/twitch.js", - "resolvedPath": "src/plugin-sdk/twitch.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/voice-call/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/voice-call.js", - "resolvedPath": "src/plugin-sdk/voice-call.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/whatsapp/src/runtime-api.ts", - "line": 19, - "kind": "export", - "specifier": "../../../src/plugin-sdk/whatsapp-core.js", - "resolvedPath": "src/plugin-sdk/whatsapp-core.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/whatsapp/src/runtime-api.ts", - "line": 34, - "kind": "export", - "specifier": "../../../src/plugin-sdk/whatsapp-shared.js", - "resolvedPath": "src/plugin-sdk/whatsapp-shared.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/zalo/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/zalo.js", - "resolvedPath": "src/plugin-sdk/zalo.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - }, - { - "file": "extensions/zalouser/runtime-api.ts", - "line": 4, - "kind": "export", - "specifier": "../../src/plugin-sdk/zalouser.js", - "resolvedPath": "src/plugin-sdk/zalouser.js", - "reason": "re-exports plugin-sdk via relative path; use openclaw/plugin-sdk/" - } -]