fix(plugin-sdk): remove relative extension boundary escapes (#51939)

* fix(plugin-sdk): remove relative extension boundary escapes

* Gate new plugin-sdk subpaths on host version

* Add changelog entry for #51939

* Fix local staging for plugin-sdk host version gate

* Raise host floor for line and googlechat plugins

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
Vincent Koc
2026-03-21 18:03:18 -07:00
committed by GitHub
parent daa042c9a0
commit 2b4c3c2057
47 changed files with 495 additions and 142 deletions

View File

@@ -137,6 +137,7 @@ Docs: https://docs.openclaw.ai
- Browser/profiles: drop the auto-created `chrome-relay` browser profile; users who need the Chrome extension relay must now create their own profile via `openclaw browser create-profile`. (#46596) Fixes #45777. Thanks @odysseus0.
- CI/channel test routing: move the built-in channel suites into `test:channels` and keep them out of `test:extensions`, so extension CI no longer fails after the channel migration while targeted test routing still sends Slack, Signal, and iMessage suites to the right lane. (#46066) Thanks @scoootscooob.
- Docs/Mintlify: fix MDX marker syntax on Perplexity, Model Providers, Moonshot, and exec approvals pages so local docs preview no longer breaks rendering or leaves stale pages unpublished. (#46695) Thanks @velvet-shark.
- Plugins/runtime barrels: route bundled extension runtime imports through public `openclaw/plugin-sdk/*` subpaths and block relative cross-package escapes so packaged extensions stop depending on monorepo-only relative paths. (#51939) Thanks @vincentkoc.
- Gateway/config validation: stop treating the implicit default memory slot as a required explicit plugin config, so startup no longer fails with `plugins.slots.memory: plugin not found: memory-core` when `memory-core` was only inferred. (#47494) Thanks @ngutman.
- Tlon: honor explicit empty allowlists and defer cite expansion. (#46788) Thanks @zpbrent and @vincentkoc.
- Tlon/DM auth: defer cited-message expansion until after DM authorization and owner command handling, so unauthorized DMs and owner approval/admin commands no longer trigger cross-channel cite fetches before the deny or command path.

View File

@@ -6,6 +6,17 @@
"dependencies": {
"zod": "^4.3.6"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -1 +1 @@
export * from "../../../src/plugin-sdk/bluebubbles.js";
export * from "openclaw/plugin-sdk/bluebubbles";

View File

@@ -5,7 +5,7 @@ import {
type ParsedChatTarget,
resolveServicePrefixedAllowTarget,
resolveServicePrefixedTarget,
} from "../../imessage/api.js";
} from "openclaw/plugin-sdk/imessage-core";
export type BlueBubblesService = "imessage" | "sms" | "auto";

View File

@@ -10,6 +10,17 @@
"https-proxy-agent": "^8.0.0",
"opusscript": "^0.1.1"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -4,7 +4,7 @@ export {
PAIRING_APPROVED_MESSAGE,
projectCredentialSnapshotFields,
resolveConfiguredFromCredentialStatuses,
} from "../../../src/plugin-sdk/discord.js";
} from "openclaw/plugin-sdk/discord";
export {
buildChannelConfigSchema,
getChatChannelMeta,
@@ -19,15 +19,15 @@ export {
type DiscordActionConfig,
type DiscordConfig,
type OpenClawConfig,
} from "../../../src/plugin-sdk/discord-core.js";
export { DiscordConfigSchema } from "../../../src/plugin-sdk/discord-core.js";
} from "openclaw/plugin-sdk/discord-core";
export { DiscordConfigSchema } from "openclaw/plugin-sdk/discord-core";
export { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
export {
assertMediaNotDataUrl,
parseAvailableTags,
readReactionParams,
withNormalizedTimestamp,
} from "../../../src/plugin-sdk/discord-core.js";
} from "openclaw/plugin-sdk/discord-core";
export {
createHybridChannelConfigAdapter,
createScopedChannelConfigAdapter,

View File

@@ -9,6 +9,17 @@
"https-proxy-agent": "^8.0.0",
"zod": "^4.3.6"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Feishu extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/feishu.js";
export * from "openclaw/plugin-sdk/feishu";

View File

@@ -7,8 +7,11 @@
"dependencies": {
"google-auth-library": "^10.6.2"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.11"
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Google Chat extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/googlechat.js";
export * from "openclaw/plugin-sdk/googlechat";

View File

@@ -13,7 +13,7 @@ export {
IMessageConfigSchema,
type ChannelPlugin,
type IMessageAccountConfig,
} from "../../src/plugin-sdk/imessage.js";
} from "openclaw/plugin-sdk/imessage";
export {
resolveIMessageGroupRequireMention,
resolveIMessageGroupToolPolicy,

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled IRC extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../../src/plugin-sdk/irc.js";
export * from "openclaw/plugin-sdk/irc";

View File

@@ -4,6 +4,17 @@
"private": true,
"description": "OpenClaw LINE channel plugin",
"type": "module",
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -1,7 +1,7 @@
// Private runtime barrel for the bundled LINE extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/line.js";
export * from "openclaw/plugin-sdk/line";
export {
DEFAULT_ACCOUNT_ID,
formatDocsLink,
@@ -10,4 +10,4 @@ export {
splitSetupEntries,
type ChannelSetupDmPolicy,
type ChannelSetupWizard,
} from "../../src/plugin-sdk/line-core.js";
} from "openclaw/plugin-sdk/line-core";

View File

@@ -14,6 +14,14 @@
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -16,7 +16,7 @@ export {
setMatrixThreadBindingIdleTimeoutBySessionKey,
setMatrixThreadBindingMaxAgeBySessionKey,
} from "./thread-bindings-runtime.js";
export { writeJsonFileAtomically } from "../../src/plugin-sdk/json-store.js";
export { writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
export type {
ChannelDirectoryEntry,
ChannelMessageActionContext,
@@ -25,5 +25,5 @@ export type {
RuntimeLogger,
RuntimeEnv,
WizardPrompter,
} from "../../src/plugin-sdk/matrix.js";
export { formatZonedTimestamp } from "../../src/plugin-sdk/matrix.js";
} from "openclaw/plugin-sdk/matrix";
export { formatZonedTimestamp } from "openclaw/plugin-sdk/matrix";

View File

@@ -1,4 +1,4 @@
export * from "../../../src/plugin-sdk/matrix.js";
export * from "openclaw/plugin-sdk/matrix";
export {
assertHttpUrlTargetsPrivateNetwork,
closeDispatcher,

View File

@@ -7,6 +7,17 @@
"ws": "^8.19.0",
"zod": "^4.3.6"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Mattermost extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/mattermost.js";
export * from "openclaw/plugin-sdk/mattermost";

View File

@@ -8,6 +8,17 @@
"express": "^5.2.1",
"uuid": "^11.1.0"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Microsoft Teams extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/msteams.js";
export * from "openclaw/plugin-sdk/msteams";

View File

@@ -6,6 +6,17 @@
"dependencies": {
"zod": "^4.3.6"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Nextcloud Talk extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/nextcloud-talk.js";
export * from "openclaw/plugin-sdk/nextcloud-talk";

View File

@@ -7,6 +7,17 @@
"nostr-tools": "^2.23.3",
"zod": "^4.3.6"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Nostr extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/nostr.js";
export * from "openclaw/plugin-sdk/nostr";

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Signal extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../../src/plugin-sdk/signal.js";
export * from "openclaw/plugin-sdk/signal";

View File

@@ -9,7 +9,7 @@ export {
type ChannelPlugin,
type OpenClawConfig,
type SlackAccountConfig,
} from "../../../src/plugin-sdk/slack.js";
} from "openclaw/plugin-sdk/slack";
export {
listSlackDirectoryGroupsFromConfig,
listSlackDirectoryPeersFromConfig,
@@ -25,5 +25,5 @@ export {
readStringParam,
SlackConfigSchema,
withNormalizedTimestamp,
} from "../../../src/plugin-sdk/slack-core.js";
} from "openclaw/plugin-sdk/slack-core";
export { isSlackInteractiveRepliesEnabled } from "./interactive-replies.js";

View File

@@ -7,7 +7,7 @@ export type {
TelegramAccountConfig,
TelegramActionConfig,
TelegramNetworkConfig,
} from "../../src/plugin-sdk/telegram.js";
} from "openclaw/plugin-sdk/telegram";
export type {
OpenClawPluginService,
OpenClawPluginServiceContext,
@@ -37,7 +37,7 @@ export {
projectCredentialSnapshotFields,
resolveConfiguredFromCredentialStatuses,
resolveTelegramPollVisibility,
} from "../../src/plugin-sdk/telegram.js";
} from "openclaw/plugin-sdk/telegram";
export {
buildChannelConfigSchema,
getChatChannelMeta,
@@ -49,7 +49,7 @@ export {
readStringParam,
resolvePollMaxSelections,
TelegramConfigSchema,
} from "../../src/plugin-sdk/telegram-core.js";
} from "openclaw/plugin-sdk/telegram-core";
export type { TelegramProbe } from "./src/probe.js";
export { auditTelegramGroupMembership, collectTelegramUnmentionedGroupIds } from "./src/audit.js";
export { telegramMessageActions } from "./src/channel-actions.js";

View File

@@ -10,6 +10,17 @@
"@urbit/aura": "^3.0.0",
"zod": "^4.3.6"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Tlon extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/tlon.js";
export * from "openclaw/plugin-sdk/tlon";

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Twitch extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/twitch.js";
export * from "openclaw/plugin-sdk/twitch";

View File

@@ -9,6 +9,17 @@
"ws": "^8.19.0",
"zod": "^4.3.6"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Voice Call extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/voice-call.js";
export * from "openclaw/plugin-sdk/voice-call";

View File

@@ -6,6 +6,17 @@
"dependencies": {
"@whiskeysockets/baileys": "7.0.0-rc.9"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -16,7 +16,7 @@ export {
WhatsAppConfigSchema,
type ChannelPlugin,
type OpenClawConfig,
} from "../../../src/plugin-sdk/whatsapp-core.js";
} from "openclaw/plugin-sdk/whatsapp-core";
export {
createWhatsAppOutboundBase,
@@ -31,6 +31,6 @@ export {
type DmPolicy,
type GroupPolicy,
type WhatsAppAccountConfig,
} from "../../../src/plugin-sdk/whatsapp-shared.js";
} from "openclaw/plugin-sdk/whatsapp-shared";
export { monitorWebChannel } from "./channel.runtime.js";

View File

@@ -7,6 +7,17 @@
"undici": "7.24.4",
"zod": "^4.3.6"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Zalo extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/zalo.js";
export * from "openclaw/plugin-sdk/zalo";

View File

@@ -8,6 +8,17 @@
"zca-js": "2.1.2",
"zod": "^4.3.6"
},
"devDependencies": {
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
},
"peerDependenciesMeta": {
"openclaw": {
"optional": true
}
},
"openclaw": {
"extensions": [
"./index.ts"

View File

@@ -1,4 +1,4 @@
// Private runtime barrel for the bundled Zalo Personal extension.
// Keep this barrel thin and aligned with the local extension surface.
export * from "../../src/plugin-sdk/zalouser.js";
export * from "openclaw/plugin-sdk/zalouser";

View File

@@ -221,6 +221,10 @@
"types": "./dist/plugin-sdk/allowlist-config-edit.d.ts",
"default": "./dist/plugin-sdk/allowlist-config-edit.js"
},
"./plugin-sdk/bluebubbles": {
"types": "./dist/plugin-sdk/bluebubbles.d.ts",
"default": "./dist/plugin-sdk/bluebubbles.js"
},
"./plugin-sdk/boolean-param": {
"types": "./dist/plugin-sdk/boolean-param.d.ts",
"default": "./dist/plugin-sdk/boolean-param.js"
@@ -245,6 +249,10 @@
"types": "./dist/plugin-sdk/discord.d.ts",
"default": "./dist/plugin-sdk/discord.js"
},
"./plugin-sdk/discord-core": {
"types": "./dist/plugin-sdk/discord-core.d.ts",
"default": "./dist/plugin-sdk/discord-core.js"
},
"./plugin-sdk/extension-shared": {
"types": "./dist/plugin-sdk/extension-shared.d.ts",
"default": "./dist/plugin-sdk/extension-shared.js"
@@ -293,6 +301,10 @@
"types": "./dist/plugin-sdk/channel-targets.d.ts",
"default": "./dist/plugin-sdk/channel-targets.js"
},
"./plugin-sdk/feishu": {
"types": "./dist/plugin-sdk/feishu.d.ts",
"default": "./dist/plugin-sdk/feishu.js"
},
"./plugin-sdk/group-access": {
"types": "./dist/plugin-sdk/group-access.d.ts",
"default": "./dist/plugin-sdk/group-access.js"
@@ -301,6 +313,42 @@
"types": "./dist/plugin-sdk/directory-runtime.d.ts",
"default": "./dist/plugin-sdk/directory-runtime.js"
},
"./plugin-sdk/googlechat": {
"types": "./dist/plugin-sdk/googlechat.d.ts",
"default": "./dist/plugin-sdk/googlechat.js"
},
"./plugin-sdk/image-generation": {
"types": "./dist/plugin-sdk/image-generation.d.ts",
"default": "./dist/plugin-sdk/image-generation.js"
},
"./plugin-sdk/imessage": {
"types": "./dist/plugin-sdk/imessage.d.ts",
"default": "./dist/plugin-sdk/imessage.js"
},
"./plugin-sdk/imessage-core": {
"types": "./dist/plugin-sdk/imessage-core.d.ts",
"default": "./dist/plugin-sdk/imessage-core.js"
},
"./plugin-sdk/irc": {
"types": "./dist/plugin-sdk/irc.d.ts",
"default": "./dist/plugin-sdk/irc.js"
},
"./plugin-sdk/reply-history": {
"types": "./dist/plugin-sdk/reply-history.d.ts",
"default": "./dist/plugin-sdk/reply-history.js"
},
"./plugin-sdk/media-understanding": {
"types": "./dist/plugin-sdk/media-understanding.d.ts",
"default": "./dist/plugin-sdk/media-understanding.js"
},
"./plugin-sdk/request-url": {
"types": "./dist/plugin-sdk/request-url.d.ts",
"default": "./dist/plugin-sdk/request-url.js"
},
"./plugin-sdk/runtime-store": {
"types": "./dist/plugin-sdk/runtime-store.d.ts",
"default": "./dist/plugin-sdk/runtime-store.js"
},
"./plugin-sdk/json-store": {
"types": "./dist/plugin-sdk/json-store.d.ts",
"default": "./dist/plugin-sdk/json-store.js"
@@ -309,10 +357,26 @@
"types": "./dist/plugin-sdk/keyed-async-queue.d.ts",
"default": "./dist/plugin-sdk/keyed-async-queue.js"
},
"./plugin-sdk/line": {
"types": "./dist/plugin-sdk/line.d.ts",
"default": "./dist/plugin-sdk/line.js"
},
"./plugin-sdk/line-core": {
"types": "./dist/plugin-sdk/line-core.d.ts",
"default": "./dist/plugin-sdk/line-core.js"
},
"./plugin-sdk/llm-task": {
"types": "./dist/plugin-sdk/llm-task.d.ts",
"default": "./dist/plugin-sdk/llm-task.js"
},
"./plugin-sdk/matrix": {
"types": "./dist/plugin-sdk/matrix.d.ts",
"default": "./dist/plugin-sdk/matrix.js"
},
"./plugin-sdk/mattermost": {
"types": "./dist/plugin-sdk/mattermost.d.ts",
"default": "./dist/plugin-sdk/mattermost.js"
},
"./plugin-sdk/memory-core": {
"types": "./dist/plugin-sdk/memory-core.d.ts",
"default": "./dist/plugin-sdk/memory-core.js"
@@ -321,6 +385,18 @@
"types": "./dist/plugin-sdk/memory-lancedb.d.ts",
"default": "./dist/plugin-sdk/memory-lancedb.js"
},
"./plugin-sdk/msteams": {
"types": "./dist/plugin-sdk/msteams.d.ts",
"default": "./dist/plugin-sdk/msteams.js"
},
"./plugin-sdk/nextcloud-talk": {
"types": "./dist/plugin-sdk/nextcloud-talk.d.ts",
"default": "./dist/plugin-sdk/nextcloud-talk.js"
},
"./plugin-sdk/nostr": {
"types": "./dist/plugin-sdk/nostr.d.ts",
"default": "./dist/plugin-sdk/nostr.js"
},
"./plugin-sdk/provider-auth": {
"types": "./dist/plugin-sdk/provider-auth.d.ts",
"default": "./dist/plugin-sdk/provider-auth.js"
@@ -373,57 +449,25 @@
"types": "./dist/plugin-sdk/provider-zai-endpoint.d.ts",
"default": "./dist/plugin-sdk/provider-zai-endpoint.js"
},
"./plugin-sdk/image-generation": {
"types": "./dist/plugin-sdk/image-generation.d.ts",
"default": "./dist/plugin-sdk/image-generation.js"
},
"./plugin-sdk/reply-history": {
"types": "./dist/plugin-sdk/reply-history.d.ts",
"default": "./dist/plugin-sdk/reply-history.js"
},
"./plugin-sdk/media-understanding": {
"types": "./dist/plugin-sdk/media-understanding.d.ts",
"default": "./dist/plugin-sdk/media-understanding.js"
},
"./plugin-sdk/request-url": {
"types": "./dist/plugin-sdk/request-url.d.ts",
"default": "./dist/plugin-sdk/request-url.js"
},
"./plugin-sdk/webhook-ingress": {
"types": "./dist/plugin-sdk/webhook-ingress.d.ts",
"default": "./dist/plugin-sdk/webhook-ingress.js"
},
"./plugin-sdk/webhook-path": {
"types": "./dist/plugin-sdk/webhook-path.d.ts",
"default": "./dist/plugin-sdk/webhook-path.js"
},
"./plugin-sdk/runtime-store": {
"types": "./dist/plugin-sdk/runtime-store.d.ts",
"default": "./dist/plugin-sdk/runtime-store.js"
},
"./plugin-sdk/status-helpers": {
"types": "./dist/plugin-sdk/status-helpers.d.ts",
"default": "./dist/plugin-sdk/status-helpers.js"
},
"./plugin-sdk/secret-input": {
"types": "./dist/plugin-sdk/secret-input.d.ts",
"default": "./dist/plugin-sdk/secret-input.js"
},
"./plugin-sdk/thread-ownership": {
"types": "./dist/plugin-sdk/thread-ownership.d.ts",
"default": "./dist/plugin-sdk/thread-ownership.js"
"./plugin-sdk/signal": {
"types": "./dist/plugin-sdk/signal.d.ts",
"default": "./dist/plugin-sdk/signal.js"
},
"./plugin-sdk/web-media": {
"types": "./dist/plugin-sdk/web-media.d.ts",
"default": "./dist/plugin-sdk/web-media.js"
"./plugin-sdk/slack": {
"types": "./dist/plugin-sdk/slack.d.ts",
"default": "./dist/plugin-sdk/slack.js"
},
"./plugin-sdk/zalo": {
"types": "./dist/plugin-sdk/zalo.d.ts",
"default": "./dist/plugin-sdk/zalo.js"
"./plugin-sdk/slack-core": {
"types": "./dist/plugin-sdk/slack-core.d.ts",
"default": "./dist/plugin-sdk/slack-core.js"
},
"./plugin-sdk/zalouser": {
"types": "./dist/plugin-sdk/zalouser.d.ts",
"default": "./dist/plugin-sdk/zalouser.js"
"./plugin-sdk/status-helpers": {
"types": "./dist/plugin-sdk/status-helpers.d.ts",
"default": "./dist/plugin-sdk/status-helpers.js"
},
"./plugin-sdk/speech": {
"types": "./dist/plugin-sdk/speech.d.ts",
@@ -433,10 +477,62 @@
"types": "./dist/plugin-sdk/state-paths.d.ts",
"default": "./dist/plugin-sdk/state-paths.js"
},
"./plugin-sdk/telegram": {
"types": "./dist/plugin-sdk/telegram.d.ts",
"default": "./dist/plugin-sdk/telegram.js"
},
"./plugin-sdk/telegram-core": {
"types": "./dist/plugin-sdk/telegram-core.d.ts",
"default": "./dist/plugin-sdk/telegram-core.js"
},
"./plugin-sdk/thread-ownership": {
"types": "./dist/plugin-sdk/thread-ownership.d.ts",
"default": "./dist/plugin-sdk/thread-ownership.js"
},
"./plugin-sdk/tlon": {
"types": "./dist/plugin-sdk/tlon.d.ts",
"default": "./dist/plugin-sdk/tlon.js"
},
"./plugin-sdk/tool-send": {
"types": "./dist/plugin-sdk/tool-send.d.ts",
"default": "./dist/plugin-sdk/tool-send.js"
},
"./plugin-sdk/twitch": {
"types": "./dist/plugin-sdk/twitch.d.ts",
"default": "./dist/plugin-sdk/twitch.js"
},
"./plugin-sdk/webhook-ingress": {
"types": "./dist/plugin-sdk/webhook-ingress.d.ts",
"default": "./dist/plugin-sdk/webhook-ingress.js"
},
"./plugin-sdk/webhook-path": {
"types": "./dist/plugin-sdk/webhook-path.d.ts",
"default": "./dist/plugin-sdk/webhook-path.js"
},
"./plugin-sdk/web-media": {
"types": "./dist/plugin-sdk/web-media.d.ts",
"default": "./dist/plugin-sdk/web-media.js"
},
"./plugin-sdk/voice-call": {
"types": "./dist/plugin-sdk/voice-call.d.ts",
"default": "./dist/plugin-sdk/voice-call.js"
},
"./plugin-sdk/whatsapp-core": {
"types": "./dist/plugin-sdk/whatsapp-core.d.ts",
"default": "./dist/plugin-sdk/whatsapp-core.js"
},
"./plugin-sdk/whatsapp-shared": {
"types": "./dist/plugin-sdk/whatsapp-shared.d.ts",
"default": "./dist/plugin-sdk/whatsapp-shared.js"
},
"./plugin-sdk/zalo": {
"types": "./dist/plugin-sdk/zalo.d.ts",
"default": "./dist/plugin-sdk/zalo.js"
},
"./plugin-sdk/zalouser": {
"types": "./dist/plugin-sdk/zalouser.d.ts",
"default": "./dist/plugin-sdk/zalouser.js"
},
"./extension-api": "./dist/extensionAPI.js",
"./cli-entry": "./openclaw.mjs"
},

59
pnpm-lock.yaml generated
View File

@@ -250,6 +250,10 @@ importers:
zod:
specifier: ^4.3.6
version: 4.3.6
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/brave: {}
@@ -326,6 +330,10 @@ importers:
opusscript:
specifier: ^0.1.1
version: 0.1.1
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/elevenlabs: {}
@@ -345,6 +353,10 @@ importers:
zod:
specifier: ^4.3.6
version: 4.3.6
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/firecrawl: {}
@@ -357,9 +369,10 @@ importers:
google-auth-library:
specifier: ^10.6.2
version: 10.6.2
devDependencies:
openclaw:
specifier: '>=2026.3.11'
version: 2026.3.13(@discordjs/opus@0.10.0)(@napi-rs/canvas@0.1.95)(@types/express@5.0.6)(audio-decode@2.2.3)(jimp@1.6.0)(node-llama-cpp@3.16.2(typescript@5.9.3))
specifier: workspace:*
version: link:../..
extensions/huggingface: {}
@@ -375,7 +388,11 @@ importers:
extensions/kimi-coding: {}
extensions/line: {}
extensions/line:
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/llm-task:
dependencies:
@@ -425,6 +442,10 @@ importers:
zod:
specifier: ^4.3.6
version: 4.3.6
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/memory-core:
dependencies:
@@ -465,12 +486,20 @@ importers:
uuid:
specifier: ^11.1.0
version: 11.1.0
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/nextcloud-talk:
dependencies:
zod:
specifier: ^4.3.6
version: 4.3.6
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/nostr:
dependencies:
@@ -480,6 +509,10 @@ importers:
zod:
specifier: ^4.3.6
version: 4.3.6
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/nvidia: {}
@@ -553,6 +586,10 @@ importers:
zod:
specifier: ^4.3.6
version: 4.3.6
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/together: {}
@@ -591,6 +628,10 @@ importers:
zod:
specifier: ^4.3.6
version: 4.3.6
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/volcengine: {}
@@ -599,6 +640,10 @@ importers:
'@whiskeysockets/baileys':
specifier: 7.0.0-rc.9
version: 7.0.0-rc.9(audio-decode@2.2.3)(jimp@1.6.0)(sharp@0.34.5)
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/xai: {}
@@ -614,6 +659,10 @@ importers:
zod:
specifier: ^4.3.6
version: 4.3.6
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
extensions/zalouser:
dependencies:
@@ -626,6 +675,10 @@ importers:
zod:
specifier: ^4.3.6
version: 4.3.6
devDependencies:
openclaw:
specifier: workspace:*
version: link:../..
packages/clawdbot:
dependencies:

View File

@@ -354,9 +354,20 @@ export async function runExtensionPluginSdkBoundaryCheck(argv = process.argv.sli
return 0;
}
writeLine(streams.stdout, formatInventoryHuman(mode, actual));
if (mode === "relative-outside-package") {
if (actual.length === 0) {
return 0;
}
writeLine(
streams.stderr,
`Relative outside-package violations found (${actual.length}); this mode no longer uses a baseline.`,
);
return 1;
}
const expected = await readExpectedInventory(mode);
const diff = diffInventory(expected, actual);
writeLine(streams.stdout, formatInventoryHuman(mode, actual));
if (diff.missing.length === 0 && diff.unexpected.length === 0) {
writeLine(streams.stdout, `Baseline matches (${actual.length} entries).`);
return 0;

View File

@@ -45,12 +45,14 @@
"account-resolution",
"allow-from",
"allowlist-config-edit",
"bluebubbles",
"boolean-param",
"command-auth",
"device-bootstrap",
"diagnostics-otel",
"diffs",
"discord",
"discord-core",
"extension-shared",
"channel-config-helpers",
"channel-config-schema",
@@ -63,13 +65,30 @@
"channel-policy",
"channel-send-result",
"channel-targets",
"feishu",
"group-access",
"directory-runtime",
"googlechat",
"image-generation",
"imessage",
"imessage-core",
"irc",
"reply-history",
"media-understanding",
"request-url",
"runtime-store",
"json-store",
"keyed-async-queue",
"line",
"line-core",
"llm-task",
"matrix",
"mattermost",
"memory-core",
"memory-lancedb",
"msteams",
"nextcloud-talk",
"nostr",
"provider-auth",
"provider-auth-api-key",
"provider-auth-login",
@@ -83,20 +102,25 @@
"provider-usage",
"provider-web-search",
"provider-zai-endpoint",
"image-generation",
"reply-history",
"media-understanding",
"request-url",
"webhook-ingress",
"webhook-path",
"runtime-store",
"status-helpers",
"secret-input",
"thread-ownership",
"web-media",
"zalo",
"zalouser",
"signal",
"slack",
"slack-core",
"status-helpers",
"speech",
"state-paths",
"tool-send"
"telegram",
"telegram-core",
"thread-ownership",
"tlon",
"tool-send",
"twitch",
"webhook-ingress",
"webhook-path",
"web-media",
"voice-call",
"whatsapp-core",
"whatsapp-shared",
"zalo",
"zalouser"
]

View File

@@ -7,6 +7,10 @@ function readJson(filePath) {
return JSON.parse(fs.readFileSync(filePath, "utf8"));
}
function writeJson(filePath, value) {
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
}
function removePathIfExists(targetPath) {
fs.rmSync(targetPath, { recursive: true, force: true });
}
@@ -35,7 +39,51 @@ function shouldStageRuntimeDeps(packageJson) {
return packageJson.openclaw?.bundle?.stageRuntimeDependencies === true;
}
function sanitizeBundledManifestForRuntimeInstall(pluginDir) {
const manifestPath = path.join(pluginDir, "package.json");
const packageJson = readJson(manifestPath);
let changed = false;
if (packageJson.peerDependencies?.openclaw) {
const nextPeerDependencies = { ...packageJson.peerDependencies };
delete nextPeerDependencies.openclaw;
if (Object.keys(nextPeerDependencies).length === 0) {
delete packageJson.peerDependencies;
} else {
packageJson.peerDependencies = nextPeerDependencies;
}
changed = true;
}
if (packageJson.peerDependenciesMeta?.openclaw) {
const nextPeerDependenciesMeta = { ...packageJson.peerDependenciesMeta };
delete nextPeerDependenciesMeta.openclaw;
if (Object.keys(nextPeerDependenciesMeta).length === 0) {
delete packageJson.peerDependenciesMeta;
} else {
packageJson.peerDependenciesMeta = nextPeerDependenciesMeta;
}
changed = true;
}
if (packageJson.devDependencies?.openclaw) {
const nextDevDependencies = { ...packageJson.devDependencies };
delete nextDevDependencies.openclaw;
if (Object.keys(nextDevDependencies).length === 0) {
delete packageJson.devDependencies;
} else {
packageJson.devDependencies = nextDevDependencies;
}
changed = true;
}
if (changed) {
writeJson(manifestPath, packageJson);
}
}
function installPluginRuntimeDeps(pluginDir, pluginId) {
sanitizeBundledManifestForRuntimeInstall(pluginDir);
const result = spawnSync(
"npm",
["install", "--omit=dev", "--silent", "--ignore-scripts", "--package-lock=false"],

View File

@@ -27,25 +27,25 @@ const RUNTIME_API_EXPORT_GUARDS: Record<string, readonly string[]> = {
'export * from "./src/send.js";',
],
"extensions/imessage/runtime-api.ts": [
'export { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildChannelConfigSchema, collectStatusIssuesFromLastError, formatTrimmedAllowFromEntries, getChatChannelMeta, looksLikeIMessageTargetId, normalizeIMessageMessagingTarget, resolveChannelMediaMaxBytes, resolveIMessageConfigAllowFrom, resolveIMessageConfigDefaultTo, IMessageConfigSchema, type ChannelPlugin, type IMessageAccountConfig } from "../../src/plugin-sdk/imessage.js";',
'export { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildChannelConfigSchema, collectStatusIssuesFromLastError, formatTrimmedAllowFromEntries, getChatChannelMeta, looksLikeIMessageTargetId, normalizeIMessageMessagingTarget, resolveChannelMediaMaxBytes, resolveIMessageConfigAllowFrom, resolveIMessageConfigDefaultTo, IMessageConfigSchema, type ChannelPlugin, type IMessageAccountConfig } from "openclaw/plugin-sdk/imessage";',
'export { resolveIMessageGroupRequireMention, resolveIMessageGroupToolPolicy } from "./src/group-policy.js";',
'export { monitorIMessageProvider } from "./src/monitor.js";',
'export type { MonitorIMessageOpts } from "./src/monitor.js";',
'export { probeIMessage } from "./src/probe.js";',
'export { sendMessageIMessage } from "./src/send.js";',
],
"extensions/googlechat/runtime-api.ts": ['export * from "../../src/plugin-sdk/googlechat.js";'],
"extensions/googlechat/runtime-api.ts": ['export * from "openclaw/plugin-sdk/googlechat";'],
"extensions/matrix/runtime-api.ts": [
'export * from "./src/auth-precedence.js";',
'export * from "./helper-api.js";',
'export { assertHttpUrlTargetsPrivateNetwork, closeDispatcher, createPinnedDispatcher, resolvePinnedHostnameWithPolicy, ssrfPolicyFromAllowPrivateNetwork, type LookupFn, type SsrFPolicy } from "openclaw/plugin-sdk/ssrf-runtime";',
'export { setMatrixThreadBindingIdleTimeoutBySessionKey, setMatrixThreadBindingMaxAgeBySessionKey } from "./thread-bindings-runtime.js";',
'export { writeJsonFileAtomically } from "../../src/plugin-sdk/json-store.js";',
'export type { ChannelDirectoryEntry, ChannelMessageActionContext, OpenClawConfig, PluginRuntime, RuntimeLogger, RuntimeEnv, WizardPrompter } from "../../src/plugin-sdk/matrix.js";',
'export { formatZonedTimestamp } from "../../src/plugin-sdk/matrix.js";',
'export { writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";',
'export type { ChannelDirectoryEntry, ChannelMessageActionContext, OpenClawConfig, PluginRuntime, RuntimeLogger, RuntimeEnv, WizardPrompter } from "openclaw/plugin-sdk/matrix";',
'export { formatZonedTimestamp } from "openclaw/plugin-sdk/matrix";',
],
"extensions/nextcloud-talk/runtime-api.ts": [
'export * from "../../src/plugin-sdk/nextcloud-talk.js";',
'export * from "openclaw/plugin-sdk/nextcloud-talk";',
],
"extensions/signal/runtime-api.ts": ['export * from "./src/runtime-api.js";'],
"extensions/slack/runtime-api.ts": [
@@ -56,12 +56,12 @@ const RUNTIME_API_EXPORT_GUARDS: Record<string, readonly string[]> = {
'export * from "./src/resolve-users.js";',
],
"extensions/telegram/runtime-api.ts": [
'export type { ChannelMessageActionAdapter, ChannelPlugin, OpenClawConfig, OpenClawPluginApi, PluginRuntime, TelegramAccountConfig, TelegramActionConfig, TelegramNetworkConfig } from "../../src/plugin-sdk/telegram.js";',
'export type { ChannelMessageActionAdapter, ChannelPlugin, OpenClawConfig, OpenClawPluginApi, PluginRuntime, TelegramAccountConfig, TelegramActionConfig, TelegramNetworkConfig } from "openclaw/plugin-sdk/telegram";',
'export type { OpenClawPluginService, OpenClawPluginServiceContext, PluginLogger } from "openclaw/plugin-sdk/core";',
'export type { AcpRuntime, AcpRuntimeCapabilities, AcpRuntimeDoctorReport, AcpRuntimeEnsureInput, AcpRuntimeEvent, AcpRuntimeHandle, AcpRuntimeStatus, AcpRuntimeTurnInput, AcpRuntimeErrorCode, AcpSessionUpdateTag } from "openclaw/plugin-sdk/acp-runtime";',
'export { AcpRuntimeError } from "openclaw/plugin-sdk/acp-runtime";',
'export { buildTokenChannelStatusSummary, clearAccountEntryFields, DEFAULT_ACCOUNT_ID, normalizeAccountId, PAIRING_APPROVED_MESSAGE, parseTelegramTopicConversation, projectCredentialSnapshotFields, resolveConfiguredFromCredentialStatuses, resolveTelegramPollVisibility } from "../../src/plugin-sdk/telegram.js";',
'export { buildChannelConfigSchema, getChatChannelMeta, jsonResult, readNumberParam, readReactionParams, readStringArrayParam, readStringOrNumberParam, readStringParam, resolvePollMaxSelections, TelegramConfigSchema } from "../../src/plugin-sdk/telegram-core.js";',
'export { buildTokenChannelStatusSummary, clearAccountEntryFields, DEFAULT_ACCOUNT_ID, normalizeAccountId, PAIRING_APPROVED_MESSAGE, parseTelegramTopicConversation, projectCredentialSnapshotFields, resolveConfiguredFromCredentialStatuses, resolveTelegramPollVisibility } from "openclaw/plugin-sdk/telegram";',
'export { buildChannelConfigSchema, getChatChannelMeta, jsonResult, readNumberParam, readReactionParams, readStringArrayParam, readStringOrNumberParam, readStringParam, resolvePollMaxSelections, TelegramConfigSchema } from "openclaw/plugin-sdk/telegram-core";',
'export type { TelegramProbe } from "./src/probe.js";',
'export { auditTelegramGroupMembership, collectTelegramUnmentionedGroupIds } from "./src/audit.js";',
'export { telegramMessageActions } from "./src/channel-actions.js";',

View File

@@ -95,44 +95,22 @@ const statusHelpersSdk = await import("openclaw/plugin-sdk/status-helpers");
describe("plugin-sdk subpath exports", () => {
it("keeps the curated public list free of internal implementation subpaths", () => {
expect(pluginSdkSubpaths).not.toContain("acpx");
expect(pluginSdkSubpaths).not.toContain("bluebubbles");
expect(pluginSdkSubpaths).not.toContain("compat");
expect(pluginSdkSubpaths).not.toContain("device-pair");
expect(pluginSdkSubpaths).not.toContain("feishu");
expect(pluginSdkSubpaths).not.toContain("google");
expect(pluginSdkSubpaths).not.toContain("googlechat");
expect(pluginSdkSubpaths).not.toContain("imessage");
expect(pluginSdkSubpaths).not.toContain("irc");
expect(pluginSdkSubpaths).not.toContain("imessage-core");
expect(pluginSdkSubpaths).not.toContain("line");
expect(pluginSdkSubpaths).not.toContain("line-core");
expect(pluginSdkSubpaths).not.toContain("lobster");
expect(pluginSdkSubpaths).not.toContain("mattermost");
expect(pluginSdkSubpaths).not.toContain("matrix");
expect(pluginSdkSubpaths).not.toContain("msteams");
expect(pluginSdkSubpaths).not.toContain("nextcloud-talk");
expect(pluginSdkSubpaths).not.toContain("nostr");
expect(pluginSdkSubpaths).not.toContain("pairing-access");
expect(pluginSdkSubpaths).not.toContain("qwen-portal-auth");
expect(pluginSdkSubpaths).not.toContain("reply-prefix");
expect(pluginSdkSubpaths).not.toContain("signal-core");
expect(pluginSdkSubpaths).not.toContain("slack");
expect(pluginSdkSubpaths).not.toContain("synology-chat");
expect(pluginSdkSubpaths).not.toContain("telegram");
expect(pluginSdkSubpaths).not.toContain("telegram-core");
expect(pluginSdkSubpaths).not.toContain("tlon");
expect(pluginSdkSubpaths).not.toContain("twitch");
expect(pluginSdkSubpaths).not.toContain("typing");
expect(pluginSdkSubpaths).not.toContain("voice-call");
expect(pluginSdkSubpaths).not.toContain("whatsapp");
expect(pluginSdkSubpaths).not.toContain("whatsapp-action-runtime");
expect(pluginSdkSubpaths).not.toContain("whatsapp-core");
expect(pluginSdkSubpaths).not.toContain("whatsapp-login-qr");
expect(pluginSdkSubpaths).not.toContain("whatsapp-shared");
expect(pluginSdkSubpaths).not.toContain("secret-input-runtime");
expect(pluginSdkSubpaths).not.toContain("secret-input-schema");
expect(pluginSdkSubpaths).not.toContain("zai");
expect(pluginSdkSubpaths).not.toContain("slack-core");
expect(pluginSdkSubpaths).not.toContain("provider-model-definitions");
});

View File

@@ -1,19 +1,9 @@
import fs from "node:fs";
import path from "node:path";
import { describe, expect, it } from "vitest";
import {
collectExtensionPluginSdkBoundaryInventory,
main,
} from "../scripts/check-extension-plugin-sdk-boundary.mjs";
const repoRoot = process.cwd();
const relativeOutsidePackageBaselinePath = path.join(
repoRoot,
"test",
"fixtures",
"extension-relative-outside-package-inventory.json",
);
function createCapturedIo() {
let stdout = "";
let stderr = "";
@@ -88,20 +78,18 @@ describe("extension plugin-sdk-internal boundary inventory", () => {
});
describe("extension relative-outside-package boundary inventory", () => {
it("matches the checked-in baseline", async () => {
it("is currently empty", async () => {
const inventory = await collectExtensionPluginSdkBoundaryInventory("relative-outside-package");
const expected = JSON.parse(fs.readFileSync(relativeOutsidePackageBaselinePath, "utf8"));
expect(inventory).toEqual(expected);
expect(inventory).toEqual([]);
});
it("script json output matches the checked-in baseline", async () => {
it("script json output is empty", async () => {
const captured = createCapturedIo();
const exitCode = await main(["--mode=relative-outside-package", "--json"], captured.io);
const expected = JSON.parse(fs.readFileSync(relativeOutsidePackageBaselinePath, "utf8"));
expect(exitCode).toBe(0);
expect(captured.readStderr()).toBe("");
expect(JSON.parse(captured.readStdout())).toEqual(expected);
expect(JSON.parse(captured.readStdout())).toEqual([]);
});
});