refactor: remove expired plugin compatibility surfaces (#111451)

* docs(secrets): remove retired web credential paths

* refactor(web): remove retired provider compatibility paths

* refactor(providers): delete retired compatibility routes

* refactor(secrets): remove retired credential aliases

* refactor(plugin-sdk): delete retired compatibility surfaces

* docs(plugin-sdk): remove retired migration guidance

* chore(plugin-sdk): refresh rebased surface budgets

* chore(plugin-sdk): refresh API removal baseline

* refactor(compat): migrate retired internal callers

* chore(plugin-sdk): refresh current-main baselines

* test(config): migrate plugin-owned secret assertions

* test(gateway): narrow plugin secret refs

* fix(plugin-sdk): preserve private boundary type identity

* chore(compat): remove stale sweep references

* chore(lint): lower max-lines budget

* refactor(secrets): remove unused web helper

* build(plugin-sdk): drop removed compat entries

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): use Linux API baseline hash

* fix(plugin-sdk): preserve private bundled build entries

* fix(plugin-sdk): package private runtime facades

* fix(plugins): preserve external credential contracts
This commit is contained in:
Peter Steinberger
2026-07-19 11:04:48 -07:00
committed by GitHub
parent e6d7aee41d
commit c7e7ac2728
526 changed files with 4009 additions and 13992 deletions
-1
View File
@@ -112,7 +112,6 @@ const PLUGIN_SDK_SELF_BUILT_ENTRY_DTS_CACHE_INPUTS = [
},
];
const PLUGIN_SDK_ENTRY_DTS_CACHE_OUTPUTS = [
"dist/plugin-sdk/webhook-path.js",
"dist/plugin-sdk/.boundary-entry-shims.stamp",
...pluginSdkEntrypoints.map((entry) => `packages/plugin-sdk/dist/src/plugin-sdk/${entry}.d.ts`),
];
-2
View File
@@ -211,10 +211,8 @@ const rules = [
"src/channels/message/inbound-reply-dispatch.ts",
"src/infra/outbound/deliver-runtime.ts",
"src/infra/outbound/deliver.ts",
"src/plugin-sdk/channel-message-runtime.ts",
"src/plugin-sdk/channel-message.ts",
"src/plugin-sdk/inbound-reply-dispatch.ts",
"src/plugin-sdk/outbound-runtime.ts",
],
message: "use sendDurableMessageBatch or deliverInboundReplyWithMessageSendContext",
},
@@ -4,15 +4,7 @@ import path from "node:path";
import { discoverOpenClawPlugins } from "../src/plugins/discovery.js";
import { collectFilesSync, isCodeFile, relativeToCwd } from "./check-file-utils.js";
// Match exact monolithic-root specifier in any code path:
// imports/exports, require/dynamic import, and test mocks (vi.mock/jest.mock).
const ROOT_IMPORT_PATTERN = /["']openclaw\/plugin-sdk["']/;
const LEGACY_COMPAT_IMPORT_PATTERN = /["']openclaw\/plugin-sdk\/compat["']/;
const LEGACY_BROAD_SUBPATH_PATTERNS = [
{
pattern: /["']openclaw\/plugin-sdk\/channel-runtime["']/,
label: "openclaw/plugin-sdk/channel-runtime",
},
{
pattern: /["']openclaw\/plugin-sdk\/config-runtime["']/,
label: "openclaw/plugin-sdk/config-runtime",
@@ -23,14 +15,6 @@ const LEGACY_BROAD_SUBPATH_PATTERNS = [
},
] as const;
function hasMonolithicRootImport(content: string): boolean {
return ROOT_IMPORT_PATTERN.test(content);
}
function hasLegacyCompatImport(content: string): boolean {
return LEGACY_COMPAT_IMPORT_PATTERN.test(content);
}
function findLegacyBroadSubpathImports(content: string): string[] {
return LEGACY_BROAD_SUBPATH_PATTERNS.filter(({ pattern }) => pattern.test(content)).map(
({ label }) => label,
@@ -90,8 +74,6 @@ function main() {
filesToCheck.add(extensionFile);
}
const monolithicOffenders: string[] = [];
const legacyCompatOffenders: string[] = [];
const legacyBroadSubpathOffenders = new Map<string, string[]>();
for (const entryFile of filesToCheck) {
let content;
@@ -100,37 +82,13 @@ function main() {
} catch {
continue;
}
if (hasMonolithicRootImport(content)) {
monolithicOffenders.push(entryFile);
}
if (hasLegacyCompatImport(content)) {
legacyCompatOffenders.push(entryFile);
}
const legacyBroadSubpaths = findLegacyBroadSubpathImports(content);
if (legacyBroadSubpaths.length > 0) {
legacyBroadSubpathOffenders.set(entryFile, legacyBroadSubpaths);
}
}
if (
monolithicOffenders.length > 0 ||
legacyCompatOffenders.length > 0 ||
legacyBroadSubpathOffenders.size > 0
) {
if (monolithicOffenders.length > 0) {
console.error("Bundled plugin source files must not import monolithic openclaw/plugin-sdk.");
for (const file of monolithicOffenders.toSorted()) {
console.error(`- ${relativeToCwd(file)}`);
}
}
if (legacyCompatOffenders.length > 0) {
console.error(
"Bundled plugin source files must not import legacy openclaw/plugin-sdk/compat.",
);
for (const file of legacyCompatOffenders.toSorted()) {
console.error(`- ${relativeToCwd(file)}`);
}
}
if (legacyBroadSubpathOffenders.size > 0) {
if (legacyBroadSubpathOffenders.size > 0) {
console.error(
"Bundled plugin source files must not import deprecated broad plugin-sdk subpaths.",
@@ -141,20 +99,12 @@ function main() {
console.error(`- ${relativeToCwd(file)} (${labels.join(", ")})`);
}
}
if (
monolithicOffenders.length > 0 ||
legacyCompatOffenders.length > 0 ||
legacyBroadSubpathOffenders.size > 0
) {
console.error(
"Use focused openclaw/plugin-sdk/<domain> subpaths for bundled plugins; root, compat, and broad runtime barrels are legacy surfaces only.",
);
}
console.error("Use focused openclaw/plugin-sdk/<domain> subpaths for bundled plugins.");
process.exit(1);
}
console.log(
`OK: bundled plugin source files use scoped plugin-sdk subpaths (${filesToCheck.size} checked).`,
`OK: bundled plugin source files avoid deprecated broad plugin-sdk subpaths (${filesToCheck.size} checked).`,
);
}
+5 -59
View File
@@ -1,11 +1,10 @@
#!/usr/bin/env node
/**
* Verifies that the root plugin-sdk runtime surface is present in the compiled
* dist output.
* Verifies that public plugin-sdk subpaths are present in the compiled dist output.
*
* Run after `pnpm build` to catch missing root exports or leaked repo-only type
* aliases before release.
* Run after `pnpm build` to catch missing exports or leaked repo-only type aliases
* before release.
*/
import { readFileSync, existsSync, statSync } from "node:fs";
@@ -21,34 +20,6 @@ import {
import { publicPluginSdkEntrypoints, publicPluginSdkSubpaths } from "./lib/plugin-sdk-entries.mjs";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const distFile = resolve(scriptDir, "..", "dist", "plugin-sdk", "index.js");
if (!existsSync(distFile)) {
console.error("ERROR: dist/plugin-sdk/index.js not found. Run `pnpm build` first.");
process.exit(1);
}
const content = readFileSync(distFile, "utf-8");
// Extract the final export statement from the compiled output.
// tsdown/rolldown emits a single `export { ... }` at the end of the file.
const exportMatch = content.match(/export\s*\{([^}]+)\}\s*;?\s*$/);
if (!exportMatch) {
console.error("ERROR: Could not find export statement in dist/plugin-sdk/index.js");
process.exit(1);
}
const exportedNames = exportMatch[1]
.split(",")
.map((s) => {
// Handle `foo as bar` aliases — the exported name is the `bar` part
const parts = s.trim().split(/\s+as\s+/);
return (parts[parts.length - 1] || "").trim();
})
.filter(Boolean);
const exportSet = new Set(exportedNames);
const requiredRuntimeShimEntries = ["compat.js", "root-alias.cjs"];
const forbiddenPublicDeclarationSpecifiers = ["@openclaw/llm-core"];
const FORBIDDEN_PUBLIC_PROTOCOL_REGISTRY_RE = /\bdeclare\s+const\s+ProtocolSchemas(?:\$\d+)?\b/u;
const RELATIVE_DECLARATION_SPECIFIER_RE = /\b(?:from|import)\s*(?:\(\s*)?["']([^"']+)["']/gu;
@@ -63,22 +34,7 @@ const requiredSubpathExports = {
],
};
// The root plugin-sdk entry intentionally stays tiny. Keep this list aligned
// with src/plugin-sdk/index.ts runtime exports.
const requiredExports = [
"emptyPluginConfigSchema",
"onDiagnosticEvent",
"registerContextEngine",
"delegateCompactionToRuntime",
];
let missing = 0;
for (const name of requiredExports) {
if (!exportSet.has(name)) {
console.error(`MISSING EXPORT: ${name}`);
missing += 1;
}
}
for (const entry of publicPluginSdkSubpaths) {
const jsPath = resolve(scriptDir, "..", "dist", "plugin-sdk", `${entry}.js`);
@@ -93,14 +49,6 @@ for (const entry of publicPluginSdkSubpaths) {
}
}
for (const entry of requiredRuntimeShimEntries) {
const shimPath = resolve(scriptDir, "..", "dist", "plugin-sdk", entry);
if (!existsSync(shimPath)) {
console.error(`MISSING RUNTIME SHIM: dist/plugin-sdk/${entry}`);
missing += 1;
}
}
for (const [entry, names] of Object.entries(requiredSubpathExports)) {
const jsPath = resolve(scriptDir, "..", "dist", "plugin-sdk", `${entry}.js`);
if (!existsSync(jsPath)) {
@@ -207,10 +155,8 @@ if (missing > 0) {
`\nERROR: ${missing} required plugin-sdk artifact(s) missing (named exports or subpath files).`,
);
console.error("This will break published plugin-sdk artifacts.");
console.error(
"Check src/plugin-sdk/index.ts, generated d.ts rewrites, subpath entries, and rebuild.",
);
console.error("Check generated d.ts rewrites, subpath entries, and rebuild.");
process.exit(1);
}
console.log(`OK: All ${requiredExports.length} required plugin-sdk exports verified.`);
console.log(`OK: All ${publicPluginSdkSubpaths.length} public plugin-sdk subpaths verified.`);
-20
View File
@@ -1,20 +0,0 @@
// Copies the CommonJS plugin SDK root alias into dist output.
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { pathToFileURL } from "node:url";
import { writeTextFileIfChanged } from "./runtime-postbuild-shared.mjs";
/**
* Copies the plugin SDK root alias source into the configured output path.
*/
export function copyPluginSdkRootAlias(params = {}) {
const cwd = params.cwd ?? process.cwd();
const source = resolve(cwd, "src/plugin-sdk/root-alias.cjs");
const target = resolve(cwd, "dist/plugin-sdk/root-alias.cjs");
writeTextFileIfChanged(target, readFileSync(source, "utf8"));
}
if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
copyPluginSdkRootAlias();
}
+1 -1
View File
@@ -99,7 +99,7 @@ COPY --from=functional-deps --chown=appuser:appuser /tmp/openclaw-deps/node_modu
# cycle through the link.
RUN tar -xzf /tmp/openclaw-current.tgz -C /app --strip-components=1 \
&& chmod +x /app/openclaw.mjs \
&& OPENCLAW_DISABLE_PLUGIN_REGISTRY_MIGRATION=1 node /app/scripts/postinstall-bundled-plugins.mjs \
&& node /app/scripts/postinstall-bundled-plugins.mjs \
&& ln -sfn /app /app/node_modules/openclaw \
&& mkdir -p "$HOME/.local/bin" \
&& ln -sf /app/openclaw.mjs "$HOME/.local/bin/openclaw" \
+1 -1
View File
@@ -297,7 +297,7 @@ export default definePluginEntry({
name: "OpenClaw Kitchen Sink",
description: "Docker E2E kitchen-sink plugin fixture",
register(api) {
api.on("before_agent_start", async (event, context) => ({
api.on("before_prompt_build", async (event, context) => ({
kitchenSink: true,
observedEventKeys: Object.keys(event || {}),
observedContextKeys: Object.keys(context || {}),
@@ -17,7 +17,13 @@ fs.writeFileSync(
name: "clickclack",
version: "0.0.1",
type: "module",
openclaw: { extensions: ["./index.mjs"] },
openclaw: {
extensions: ["./index.mjs"],
channel: {
id: "clickclack",
configuredState: { env: { anyOf: ["CLICKCLACK_BOT_TOKEN"] } },
},
},
},
null,
2,
@@ -30,7 +36,6 @@ fs.writeFileSync(
id: "clickclack",
activation: { onStartup: false },
channels: ["clickclack"],
channelEnvVars: { clickclack: ["CLICKCLACK_BOT_TOKEN"] },
channelConfigs: {
clickclack: {
schema: {
+1 -1
View File
@@ -397,7 +397,7 @@ fs.writeFileSync(
{
id: "brave",
activation: { onStartup: false },
providerAuthEnvVars: { brave: ["BRAVE_API_KEY"] },
setup: { providers: [{ id: "brave", envVars: ["BRAVE_API_KEY"] }] },
contracts: { webSearchProviders: ["brave"] },
configSchema: {
type: "object",
+6 -5
View File
@@ -24,7 +24,11 @@ cat > "$PLUGIN_DIR/package.json" <<'JSON'
"version": "1.0.0",
"openclaw": {
"extensions": ["./index.cjs"],
"setupEntry": "./setup-entry.cjs"
"setupEntry": "./setup-entry.cjs",
"channel": {
"id": "e2e-corrupt-chat",
"configuredState": { "env": { "anyOf": ["E2E_CORRUPT_CHAT_TOKEN"] } }
}
}
}
JSON
@@ -51,10 +55,7 @@ cat > "$PLUGIN_DIR/openclaw.plugin.json" <<'JSON'
}
}
},
"channels": ["e2e-corrupt-chat"],
"channelEnvVars": {
"e2e-corrupt-chat": ["E2E_CORRUPT_CHAT_TOKEN"]
}
"channels": ["e2e-corrupt-chat"]
}
JSON
+1 -1
View File
@@ -286,7 +286,7 @@ fs.writeFileSync(
{
id: "brave",
activation: { onStartup: false },
providerAuthEnvVars: { brave: ["BRAVE_API_KEY"] },
setup: { providers: [{ id: "brave", envVars: ["BRAVE_API_KEY"] }] },
contracts: { webSearchProviders: ["brave"] },
configSchema: {
type: "object",
@@ -1,9 +1,9 @@
// Packed Plugin Sdk Type Smoke script supports OpenClaw repository automation.
type PublicPluginSdkModules = [
typeof import("openclaw/plugin-sdk"),
typeof import("openclaw/plugin-sdk/core"),
typeof import("openclaw/plugin-sdk/channel-entry-contract"),
typeof import("openclaw/plugin-sdk/config-contracts"),
typeof import("openclaw/plugin-sdk/provider-entry"),
typeof import("openclaw/plugin-sdk/plugin-entry"),
typeof import("openclaw/plugin-sdk/runtime-env"),
];
@@ -16,7 +16,6 @@ type BundledPluginSource = {
manifest: {
id: string;
channels?: unknown;
channelEnvVars?: unknown;
name?: string;
description?: string;
} & Record<string, unknown>;
@@ -173,17 +172,25 @@ function resolveRootConfigurable(source: BundledPluginSource, channelId: string)
}
function resolveRootChannelEnvVars(source: BundledPluginSource, channelId: string): string[] {
const raw = source.manifest.channelEnvVars;
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
const channelMeta = resolvePackageChannelMeta(source);
if (channelMeta?.id !== channelId) {
return [];
}
const value = (raw as Record<string, unknown>)[channelId];
if (!Array.isArray(value)) {
const configuredState = channelMeta.configuredState;
if (!configuredState || typeof configuredState !== "object" || Array.isArray(configuredState)) {
return [];
}
const env = (configuredState as Record<string, unknown>).env;
if (!env || typeof env !== "object" || Array.isArray(env)) {
return [];
}
const envRecord = env as Record<string, unknown>;
const values = [envRecord.allOf, envRecord.anyOf].flatMap((value) =>
Array.isArray(value) ? value : [],
);
return [
...new Set(
value
values
.map((entry) => (typeof entry === "string" ? entry.trim() : ""))
.filter((entry) => entry.length > 0),
),
+4 -14
View File
@@ -1,11 +1,7 @@
// Builds the list of deprecated public plugin SDK specifiers guarded by scripts.
import deprecatedPublicPluginSdkSubpaths from "./plugin-sdk-deprecated-public-subpaths.json" with { type: "json" };
const DEPRECATED_PLUGIN_SDK_EXTRA_SPECIFIERS = [
"openclaw/plugin-sdk",
"openclaw/plugin-sdk/agent-dir-compat",
"openclaw/plugin-sdk/test-utils",
];
const DEPRECATED_PLUGIN_SDK_EXTRA_SPECIFIERS = [];
/** Build fully qualified deprecated plugin SDK module specifiers from subpath metadata. */
export function buildDeprecatedPluginSdkModuleSpecifiers(
@@ -17,7 +13,9 @@ export function buildDeprecatedPluginSdkModuleSpecifiers(
];
// tsconfig aliases the scoped @openclaw/plugin-sdk package to the same
// src/plugin-sdk modules, so ban both spellings of every deprecated specifier.
return [...new Set(unscoped.flatMap((specifier) => [specifier, `@${specifier}`]))].toSorted();
return [...new Set(unscoped.flatMap((specifier) => [specifier, `@${specifier}`]))].toSorted(
(a, b) => a.localeCompare(b),
);
}
/**
@@ -31,18 +29,10 @@ export function buildDeprecatedPluginSdkModuleSpecifiers(
export const BANNED_INTERNAL_PLUGIN_SDK_FACADE_MODULES = [
// Reply facades: canonical seams are openclaw/plugin-sdk/channel-inbound and
// openclaw/plugin-sdk/channel-outbound (defineChannelMessageAdapter family).
{
modulePath: "src/plugin-sdk/channel-envelope",
canonical: "openclaw/plugin-sdk/channel-inbound",
},
{
modulePath: "src/plugin-sdk/channel-message",
canonical: "openclaw/plugin-sdk/channel-outbound",
},
{
modulePath: "src/plugin-sdk/channel-message-runtime",
canonical: "openclaw/plugin-sdk/channel-outbound",
},
{
modulePath: "src/plugin-sdk/channel-reply-pipeline",
canonical: "openclaw/plugin-sdk/channel-outbound",
+17 -34
View File
@@ -54,8 +54,6 @@ function buildPackageBoundaryDtsPaths(params: {
}
export const EXTENSION_PACKAGE_BOUNDARY_BASE_PATHS = {
"openclaw/extension-api": ["../src/extensionAPI.ts"],
"openclaw/plugin-sdk": ["../dist/plugin-sdk/index.d.ts"],
"openclaw/plugin-sdk/*": ["../dist/plugin-sdk/*.d.ts"],
...privateLocalOnlyPluginSdkPackageDtsPaths,
"openclaw/plugin-sdk/account-id": ["../dist/plugin-sdk/account-id.d.ts"],
@@ -67,18 +65,8 @@ export const EXTENSION_PACKAGE_BOUNDARY_BASE_PATHS = {
"../dist/plugin-sdk/channel-secret-basic-runtime.d.ts",
],
"openclaw/plugin-sdk/channel-secret-runtime": ["../dist/plugin-sdk/channel-secret-runtime.d.ts"],
"openclaw/plugin-sdk/channel-secret-tts-runtime": [
"../dist/plugin-sdk/channel-secret-tts-runtime.d.ts",
],
"openclaw/plugin-sdk/channel-streaming": ["../dist/plugin-sdk/channel-streaming.d.ts"],
"openclaw/plugin-sdk/error-runtime": ["../dist/plugin-sdk/error-runtime.d.ts"],
"openclaw/plugin-sdk/provider-catalog-live-runtime": [
"../dist/plugin-sdk/provider-catalog-live-runtime.d.ts",
],
"openclaw/plugin-sdk/provider-catalog-shared": [
"../dist/plugin-sdk/provider-catalog-shared.d.ts",
],
"openclaw/plugin-sdk/provider-entry": ["../dist/plugin-sdk/provider-entry.d.ts"],
"openclaw/plugin-sdk/secret-ref-runtime": ["../dist/plugin-sdk/secret-ref-runtime.d.ts"],
"openclaw/plugin-sdk/ssrf-runtime": ["../dist/plugin-sdk/ssrf-runtime.d.ts"],
"@openclaw/qa-channel/api.js": ["../dist/plugin-sdk/extensions/qa-channel/api.d.ts"],
@@ -257,18 +245,25 @@ function prefixExtensionPackageBoundaryPaths(
);
}
function omitExtensionPackageBoundaryPaths(
paths: Record<string, readonly string[]>,
omittedKeys: readonly string[],
): Record<string, readonly string[]> {
const omitted = new Set(omittedKeys);
return Object.fromEntries(Object.entries(paths).filter(([key]) => !omitted.has(key)));
}
export const EXTENSION_PACKAGE_BOUNDARY_XAI_PATHS = {
...prefixExtensionPackageBoundaryPaths(
(({
"openclaw/plugin-sdk/channel-secret-basic-runtime": _omitBasic,
"openclaw/plugin-sdk/channel-secret-tts-runtime": _omitTts,
"@openclaw/matrix/test-api.js": _omitMatrix,
"@openclaw/discord/api.js": _omitDiscord,
"@openclaw/slack/api.js": _omitSlack,
"@openclaw/telegram/api.js": _omitTelegram,
"@openclaw/whatsapp/api.js": _omitWhatsApp,
...rest
}) => rest)(EXTENSION_PACKAGE_BOUNDARY_BASE_PATHS),
omitExtensionPackageBoundaryPaths(EXTENSION_PACKAGE_BOUNDARY_BASE_PATHS, [
"openclaw/plugin-sdk/channel-secret-basic-runtime",
"openclaw/plugin-sdk/channel-secret-tts-runtime",
"@openclaw/matrix/test-api.js",
"@openclaw/discord/api.js",
"@openclaw/slack/api.js",
"@openclaw/telegram/api.js",
"@openclaw/whatsapp/api.js",
]),
"../",
),
"openclaw/plugin-sdk/channel-entry-contract": [
@@ -277,18 +272,6 @@ export const EXTENSION_PACKAGE_BOUNDARY_XAI_PATHS = {
"openclaw/plugin-sdk/browser-maintenance": [
"../../dist/plugin-sdk/src/plugin-sdk/browser-maintenance.d.ts",
],
"openclaw/plugin-sdk/cli-runtime": ["../../dist/plugin-sdk/cli-runtime.d.ts"],
"openclaw/plugin-sdk/provider-catalog-live-runtime": [
"../../dist/plugin-sdk/provider-catalog-live-runtime.d.ts",
],
"openclaw/plugin-sdk/provider-catalog-shared": [
"../../dist/plugin-sdk/provider-catalog-shared.d.ts",
],
"openclaw/plugin-sdk/provider-env-vars": ["../../dist/plugin-sdk/provider-env-vars.d.ts"],
"openclaw/plugin-sdk/provider-entry": ["../../dist/plugin-sdk/provider-entry.d.ts"],
"openclaw/plugin-sdk/provider-web-search-contract": [
"../../dist/plugin-sdk/provider-web-search-contract.d.ts",
],
"@openclaw/qa-channel/api.js": ["../../dist/plugin-sdk/extensions/qa-channel/api.d.ts"],
"@openclaw/*.js": ["../../packages/plugin-sdk/dist/extensions/*.d.ts", "../*"],
"@openclaw/*": ["../*"],
@@ -7,12 +7,9 @@ function listContractTestFiles(rootDir = "src/plugins/contracts") {
const CONTRACT_FILE_WEIGHTS = new Map([
["plugin-sdk-subpaths.test.ts", 80],
["plugin-sdk-root-alias.test.ts", 90],
["tts.contract.test.ts", 70],
["boundary-invariants.test.ts", 36],
["extension-package-project-boundaries.test.ts", 34],
["plugin-sdk-index.test.ts", 32],
["plugin-sdk-index.bundle.test.ts", 32],
["plugin-sdk-package-contract-guardrails.test.ts", 46],
["providers.contract.test.ts", 30],
["registry.contract.test.ts", 30],
@@ -1,8 +1,5 @@
[
"channel-lifecycle",
"channel-runtime",
"compat",
"config-types",
"infra-runtime",
"text-runtime"
]
@@ -1,60 +1,20 @@
[
"agent-config-primitives",
"channel-config-schema-legacy",
"channel-envelope",
"channel-inbound-roots",
"channel-lifecycle",
"channel-location",
"channel-logging",
"channel-message",
"channel-message-runtime",
"channel-pairing-paths",
"channel-reply-options-runtime",
"channel-reply-pipeline",
"channel-runtime",
"channel-secret-runtime",
"channel-streaming",
"command-auth",
"command-gating",
"compat",
"config-runtime",
"config-schema",
"config-types",
"direct-dm",
"direct-dm-access",
"discord",
"group-access",
"inbound-reply-dispatch",
"infra-runtime",
"lmstudio",
"lmstudio-runtime",
"matrix",
"mattermost",
"media-generation-runtime-shared",
"messaging-targets",
"memory-core",
"memory-core-engine-runtime",
"memory-core-host-events",
"memory-core-host-multimodal",
"memory-core-host-query",
"memory-host-files",
"memory-host-status",
"music-generation-core",
"outbound-runtime",
"outbound-send-deps",
"provider-auth-login",
"provider-zai-endpoint",
"reply-dedupe",
"runtime-logger",
"runtime-secret-resolution",
"secret-provider-integration",
"self-hosted-provider-setup",
"setup-adapter-runtime",
"skills-runtime",
"telegram-account",
"telegram-command-config",
"text-runtime",
"webhook-path",
"zalouser",
"zod"
]
-66
View File
@@ -12,18 +12,12 @@ type PluginSdkDocMetadata = {
};
export const pluginSdkDocMetadata = {
index: {
category: "legacy",
},
core: {
category: "core",
},
health: {
category: "core",
},
sandbox: {
category: "runtime",
},
"approval-runtime": {
category: "runtime",
},
@@ -39,36 +33,21 @@ export const pluginSdkDocMetadata = {
"approval-gateway-runtime": {
category: "runtime",
},
"approval-reference-runtime": {
category: "runtime",
},
"approval-native-runtime": {
category: "runtime",
},
"approval-reaction-runtime": {
category: "runtime",
},
"approval-reply-runtime": {
category: "runtime",
},
"plugin-entry": {
category: "core",
},
"access-groups": {
category: "channel",
},
"channel-actions": {
category: "channel",
},
"channel-config-schema": {
category: "channel",
},
"channel-config-schema-legacy": {
category: "channel",
},
"chat-channel-ids": {
category: "channel",
},
"channel-contract": {
category: "channel",
},
@@ -87,78 +66,33 @@ export const pluginSdkDocMetadata = {
"command-auth": {
category: "channel",
},
zalouser: {
category: "channel",
},
"command-status": {
category: "channel",
},
"command-status-runtime": {
category: "runtime",
},
"secret-input": {
category: "channel",
},
"webhook-ingress": {
category: "channel",
},
"provider-onboard": {
category: "provider",
},
"provider-oauth-runtime": {
category: "provider",
},
"message-tool-delivery-hints": {
category: "runtime",
},
"tool-results": {
category: "utilities",
},
"widget-html": {
category: "utilities",
},
"provider-selection-runtime": {
category: "provider",
},
"provider-catalog-live-runtime": {
category: "provider",
},
"provider-model-types": {
category: "provider",
},
"runtime-store": {
category: "runtime",
},
"session-store-runtime": {
category: "runtime",
},
"session-transcript-runtime": {
category: "runtime",
},
"sqlite-runtime": {
category: "runtime",
},
"agent-runtime": {
category: "runtime",
},
"agent-harness-runtime": {
category: "runtime",
},
"speech-core": {
category: "provider",
},
"speech-settings": {
category: "provider",
},
"realtime-voice": {
category: "provider",
},
"tts-runtime": {
category: "runtime",
},
"inline-image-data-url-runtime": {
category: "runtime",
},
"allow-from": {
category: "utilities",
},
+3 -1
View File
@@ -1,6 +1,7 @@
export const pluginSdkEntrypoints: string[];
export const pluginSdkSubpaths: string[];
export const privateLocalOnlyPluginSdkEntrypoints: string[];
export const productionPluginSdkEntrypoints: string[];
export const publicPluginSdkEntrypoints: string[];
export const publicPluginSdkSubpaths: string[];
export const deprecatedPublicPluginSdkEntrypoints: string[];
@@ -15,4 +16,5 @@ export function buildPluginSdkPackageExports(): Record<
}
>;
export function listPluginSdkDistArtifacts(): string[];
export function listPrivateLocalOnlyPluginSdkDistArtifacts(): string[];
export function listPackagedPrivatePluginSdkRuntimeArtifacts(): string[];
export function listUnpackagedPrivatePluginSdkDistArtifacts(): string[];
+64 -13
View File
@@ -5,16 +5,16 @@ import pluginSdkEntryList from "./plugin-sdk-entrypoints.json" with { type: "jso
import privateLocalOnlyPluginSdkSubpathList from "./plugin-sdk-private-local-only-subpaths.json" with { type: "json" };
/**
* All plugin SDK entrypoints, including the package root index.
* All plugin SDK subpath entrypoints. The package root barrel has been removed.
* @internal Shared repository-script contract.
*/
export const pluginSdkEntrypoints = [...pluginSdkEntryList];
/**
* Plugin SDK subpath entrypoints, excluding the package root index.
* Plugin SDK subpath entrypoints.
* @internal Shared test-configuration contract.
*/
export const pluginSdkSubpaths = pluginSdkEntrypoints.filter((entry) => entry !== "index");
export const pluginSdkSubpaths = pluginSdkEntrypoints;
const privateLocalOnlyPluginSdkSubpathSet = new Set(
privateLocalOnlyPluginSdkSubpathList.filter(
@@ -32,15 +32,60 @@ export const privateLocalOnlyPluginSdkEntrypoints = pluginSdkSubpaths.filter((en
/** Public plugin SDK entrypoints that appear in package exports. */
export const publicPluginSdkEntrypoints = pluginSdkEntrypoints.filter(
(entry) => entry === "index" || !privateLocalOnlyPluginSdkSubpathSet.has(entry),
(entry) => !privateLocalOnlyPluginSdkSubpathSet.has(entry),
);
/**
* Public plugin SDK subpaths, excluding the package root index.
* Public plugin SDK subpaths.
* @internal Shared repository-script contract.
*/
export const publicPluginSdkSubpaths = publicPluginSdkEntrypoints.filter(
(entry) => entry !== "index",
export const publicPluginSdkSubpaths = publicPluginSdkEntrypoints;
// These local-only entries were already omitted from ordinary packaged builds
// before bundled runtime facades moved behind the same private-local boundary.
const nonProductionPluginSdkSubpathSet = new Set([
"agent-runtime-test-contracts",
"channel-contract-testing",
"channel-target-testing",
"channel-test-helpers",
"codex-native-task-runtime",
"plugin-test-api",
"plugin-test-contracts",
"plugin-state-test-runtime",
"plugin-test-runtime",
"provider-http-test-mocks",
"provider-test-contracts",
"qa-channel",
"qa-channel-protocol",
"qa-lab",
"qa-runtime",
"reply-payload-testing",
"sqlite-runtime-testing",
"ssrf-runtime-internal",
"test-env",
"test-fixtures",
"test-live",
"test-live-auth",
"test-media-generation",
"test-media-understanding",
"test-node-mocks",
]);
/** Plugin SDK entrypoints built in ordinary source and packaged runtime builds. */
export const productionPluginSdkEntrypoints = pluginSdkEntrypoints.filter(
(entry) => !nonProductionPluginSdkSubpathSet.has(entry),
);
const productionPluginSdkEntrypointSet = new Set(productionPluginSdkEntrypoints);
/** Private runtime facades required by core or bundled plugins in packaged builds. */
const packagedPrivatePluginSdkRuntimeEntrypoints = privateLocalOnlyPluginSdkEntrypoints.filter(
(entry) => productionPluginSdkEntrypointSet.has(entry),
);
/** Private entrypoints reserved for local tests and QA builds. */
const nonProductionPrivatePluginSdkEntrypoints = privateLocalOnlyPluginSdkEntrypoints.filter(
(entry) => !productionPluginSdkEntrypointSet.has(entry),
);
/**
@@ -74,7 +119,7 @@ export function buildPluginSdkEntrySources(entries = pluginSdkEntrypoints) {
export function buildPluginSdkPackageExports() {
return Object.fromEntries(
publicPluginSdkEntrypoints.map((entry) => [
entry === "index" ? "./plugin-sdk" : `./plugin-sdk/${entry}`,
`./plugin-sdk/${entry}`,
{
types: `./dist/plugin-sdk/${entry}.d.ts`,
default: `./dist/plugin-sdk/${entry}.js`,
@@ -98,9 +143,15 @@ export function listPluginSdkDistArtifacts() {
* List private local-only plugin SDK dist artifacts expected after local builds.
* @internal Shared repository-script contract.
*/
export function listPrivateLocalOnlyPluginSdkDistArtifacts() {
return privateLocalOnlyPluginSdkEntrypoints.flatMap((entry) => [
`dist/plugin-sdk/${entry}.js`,
`dist/plugin-sdk/${entry}.d.ts`,
]);
/** List private runtime facade artifacts required inside package output. */
export function listPackagedPrivatePluginSdkRuntimeArtifacts() {
return packagedPrivatePluginSdkRuntimeEntrypoints.map((entry) => `dist/plugin-sdk/${entry}.js`);
}
/** List private artifacts that must stay out of package output. */
export function listUnpackagedPrivatePluginSdkDistArtifacts() {
return [
...privateLocalOnlyPluginSdkEntrypoints.map((entry) => `dist/plugin-sdk/${entry}.d.ts`),
...nonProductionPrivatePluginSdkEntrypoints.map((entry) => `dist/plugin-sdk/${entry}.js`),
];
}
-41
View File
@@ -1,21 +1,14 @@
[
"index",
"core",
"lmstudio",
"lmstudio-runtime",
"provider-setup",
"sandbox",
"self-hosted-provider-setup",
"routing",
"runtime",
"health",
"runtime-doctor",
"runtime-env",
"runtime-logger",
"proxy-capture",
"runtime-secret-resolution",
"setup",
"setup-adapter-runtime",
"setup-runtime",
"channel-setup",
"channel-streaming",
@@ -35,15 +28,12 @@
"question-gateway-runtime",
"config-runtime",
"config-contracts",
"config-types",
"plugin-config-runtime",
"config-mutation",
"cron-store-runtime",
"config-schema",
"json-schema-runtime",
"json-unsafe-integers",
"reply-runtime",
"reply-dedupe",
"reply-dispatch-runtime",
"reply-reference",
"reply-chunking",
@@ -53,12 +43,8 @@
"inbound-reply-dispatch",
"inbound-envelope",
"channel-reply-pipeline",
"channel-reply-options-runtime",
"channel-runtime",
"interactive-runtime",
"outbound-media",
"outbound-send-deps",
"outbound-runtime",
"pair-loop-guard-runtime",
"poll-runtime",
"async-lock-runtime",
@@ -99,12 +85,10 @@
"speech-settings",
"tts-runtime",
"plugin-runtime",
"skills-runtime",
"channel-secret-basic-runtime",
"channel-secret-runtime",
"channel-secret-tts-runtime",
"secret-ref-runtime",
"secret-provider-integration",
"secret-file-runtime",
"security-runtime",
"gateway-method-runtime",
@@ -167,19 +151,14 @@
"dangerous-name-runtime",
"command-auth",
"command-auth-native",
"command-gating",
"command-primitives-runtime",
"command-status",
"command-status-runtime",
"command-detection",
"command-surface",
"collection-runtime",
"compat",
"direct-dm",
"direct-dm-access",
"direct-dm-guard-policy",
"discord",
"mattermost",
"matrix",
"device-bootstrap",
"diagnostic-runtime",
@@ -191,27 +170,21 @@
"channel-config-schema",
"bundled-channel-config-schema",
"chat-channel-ids",
"channel-config-schema-legacy",
"channel-actions",
"channel-plugin-common",
"channel-core",
"channel-entry-contract",
"channel-contract",
"channel-envelope",
"channel-feedback",
"channel-inbound",
"channel-inbound-debounce",
"channel-inbound-roots",
"channel-logging",
"channel-location",
"channel-mention-gating",
"channel-lifecycle",
"channel-ingress-runtime",
"channel-message",
"channel-message-runtime",
"channel-outbound",
"channel-pairing",
"channel-pairing-paths",
"channel-policy",
"channel-send-result",
"channel-route",
@@ -240,12 +213,10 @@
"global-singleton",
"directory-config-runtime",
"directory-runtime",
"media-generation-runtime-shared",
"image-generation",
"image-generation-runtime",
"image-generation-core",
"music-generation",
"music-generation-core",
"video-generation",
"video-generation-runtime",
"video-generation-core",
@@ -265,27 +236,20 @@
"ingress-effect-once",
"keyed-async-queue",
"qa-runner-runtime",
"memory-core",
"memory-core-engine-runtime",
"memory-core-host-embedding-registry",
"memory-core-host-engine-embeddings",
"memory-core-host-engine-foundation",
"memory-core-host-engine-qmd",
"memory-core-host-engine-storage",
"memory-core-host-multimodal",
"memory-core-host-query",
"memory-core-host-secret",
"memory-core-host-events",
"memory-core-host-status",
"memory-core-host-runtime-cli",
"memory-core-host-runtime-core",
"memory-core-host-runtime-files",
"memory-host-core",
"memory-host-events",
"memory-host-files",
"memory-host-markdown",
"memory-host-search",
"memory-host-status",
"message-tool-delivery-hints",
"models-provider-runtime",
"skill-commands-runtime",
@@ -297,7 +261,6 @@
"provider-auth-login-flow-runtime",
"provider-auth-api-key",
"provider-auth-result",
"provider-auth-login",
"provider-selection-runtime",
"plugin-entry",
"provider-catalog-live-runtime",
@@ -325,7 +288,6 @@
"retry-runtime",
"run-command",
"param-readers",
"provider-zai-endpoint",
"secret-input",
"secret-input-runtime",
"channel-status",
@@ -335,7 +297,6 @@
"state-paths",
"target-resolver-runtime",
"telegram-account",
"telegram-command-config",
"text-autolink-runtime",
"text-utility-runtime",
"widget-html",
@@ -346,9 +307,7 @@
"webhook-ingress",
"webhook-targets",
"webhook-request-guards",
"webhook-path",
"web-media",
"zalouser",
"zod",
"agent-core",
"agent-sessions",
@@ -1,22 +1,157 @@
[
"access-groups",
"account-resolution-runtime",
"acp-binding-resolve-runtime",
"acp-binding-runtime",
"acp-runtime",
"acp-runtime-backend",
"agent-core",
"agent-harness-exec-review-runtime",
"agent-harness-task-runtime",
"agent-harness-tool-runtime",
"agent-runtime-test-contracts",
"agent-sessions",
"approval-reaction-runtime",
"approval-reference-runtime",
"async-lock-runtime",
"browser-config",
"bundled-channel-config-schema",
"channel-activity-runtime",
"channel-config-writes",
"channel-contract-testing",
"channel-mention-gating",
"channel-route",
"channel-secret-tts-runtime",
"channel-target-testing",
"channel-targets",
"channel-test-helpers",
"chat-channel-ids",
"cli-backend",
"cli-runtime",
"codex-mcp-projection",
"codex-native-task-runtime",
"command-status-runtime",
"command-surface",
"concurrency-runtime",
"context-visibility-runtime",
"conversation-binding-runtime",
"cron-store-runtime",
"dangerous-name-runtime",
"delivery-queue-runtime",
"direct-dm-guard-policy",
"directory-config-runtime",
"document-extractor",
"embedding-providers",
"exec-approvals-runtime",
"expect-runtime",
"fetch-runtime",
"file-access-runtime",
"file-lock",
"global-singleton",
"group-activation",
"heartbeat-runtime",
"host-runtime",
"html-entity-runtime",
"image-generation",
"image-generation-core",
"image-generation-runtime",
"inline-image-data-url-runtime",
"json-schema-runtime",
"json-unsafe-integers",
"keyed-async-queue",
"llm",
"markdown-table-runtime",
"media-generation-runtime",
"memory-core-host-embedding-registry",
"memory-core-host-engine-embeddings",
"memory-core-host-engine-qmd",
"memory-core-host-engine-storage",
"memory-core-host-runtime-cli",
"memory-core-host-runtime-core",
"memory-core-host-runtime-files",
"memory-core-host-secret",
"memory-core-host-status",
"memory-host-events",
"memory-host-markdown",
"memory-host-search",
"message-tool-delivery-hints",
"migration",
"migration-runtime",
"music-generation",
"node-host",
"number-runtime",
"outbound-media",
"pair-loop-guard-runtime",
"plugin-state-runtime",
"plugin-state-test-runtime",
"plugin-test-api",
"plugin-test-contracts",
"plugin-state-test-runtime",
"plugin-test-runtime",
"poll-runtime",
"process-runtime",
"provider-auth-api-key",
"provider-auth-login-flow-runtime",
"provider-auth-result",
"provider-auth-runtime",
"provider-catalog-live-runtime",
"provider-catalog-shared",
"provider-entry",
"provider-env-vars",
"provider-http",
"provider-http-test-mocks",
"provider-model-shared",
"provider-model-types",
"provider-oauth-runtime",
"provider-onboard",
"provider-selection-runtime",
"provider-setup",
"provider-stream",
"provider-stream-family",
"provider-stream-shared",
"provider-test-contracts",
"provider-tools",
"provider-transport-runtime",
"provider-usage",
"provider-web-fetch",
"provider-web-fetch-contract",
"provider-web-search",
"provider-web-search-config-contract",
"provider-web-search-contract",
"qa-channel",
"qa-channel-protocol",
"qa-lab",
"qa-runner-runtime",
"qa-runtime",
"realtime-bootstrap-context",
"realtime-transcription",
"realtime-voice",
"reply-payload-testing",
"reply-reference",
"request-url",
"response-limit-runtime",
"retry-runtime",
"runtime-doctor",
"runtime-fetch",
"sandbox",
"secret-file-runtime",
"secure-random-runtime",
"session-binding-runtime",
"session-catalog",
"session-key-runtime",
"session-transcript-hit",
"session-transcript-runtime",
"session-visibility",
"simple-completion-runtime",
"speech",
"speech-core",
"sqlite-runtime",
"sqlite-runtime-testing",
"ssrf-dispatcher",
"ssrf-runtime-internal",
"string-normalization-runtime",
"system-event-runtime",
"talk-config-runtime",
"target-resolver-runtime",
"test-env",
"test-fixtures",
"test-live",
@@ -24,5 +159,21 @@
"test-media-generation",
"test-media-understanding",
"test-node-mocks",
"test-utils"
"text-autolink-runtime",
"text-utility-runtime",
"thread-bindings-runtime",
"thread-bindings-session-runtime",
"time-runtime",
"tool-payload",
"tool-results",
"transcripts",
"transport-ready-runtime",
"tts-runtime",
"types",
"video-generation",
"video-generation-core",
"video-generation-runtime",
"web-content-extractor",
"webhook-targets",
"windows-spawn"
]
@@ -12,7 +12,7 @@
"src/config/sessions/legacy-store-readonly.ts": 2,
"src/config/sessions/session-accessor.entry.ts": 2,
"src/config/sessions/store-load.ts": 3,
"src/config/sessions/store.ts": 10,
"src/config/sessions/store.ts": 9,
"src/config/sessions/transcript.ts": 2
},
"sessionAccessorWrite": {
+1 -2
View File
@@ -125,8 +125,7 @@ export function createPluginSdkScope(_repoRoot: string): TopologyScope {
const entrypoints = publicPluginSdkEntrypoints.map((entrypoint) => ({
entrypoint,
sourcePath: `src/plugin-sdk/${entrypoint}.ts`,
importSpecifier:
entrypoint === "index" ? "openclaw/plugin-sdk" : `openclaw/plugin-sdk/${entrypoint}`,
importSpecifier: `openclaw/plugin-sdk/${entrypoint}`,
}));
return buildScopeFromEntrypoints("plugin-sdk", "OpenClaw plugin-sdk public surface", entrypoints);
}
+1 -1
View File
@@ -539,7 +539,7 @@ function buildReport(options: Partial<Pick<CliOptions, "owner" | "summary">> = {
matchesOwner(options.owner, entry.owner) || matchesOwner(options.owner, entry.consumerOwner),
);
const usedReserved = new Set(reservedImports.map((entry) => entry.subpath));
const unusedReservedSubpaths = reservedBundledPluginSdkEntrypoints
const unusedReservedSubpaths = (reservedBundledPluginSdkEntrypoints as readonly string[])
.filter(
(subpath) =>
!usedReserved.has(subpath) &&
+17 -237
View File
@@ -92,120 +92,42 @@ function readPluginSdkEntrypointBudgetEnv(name, fallback, env = process.env) {
const defaultPublicDeprecatedExportsByEntrypointBudget = Object.freeze({
core: 2,
health: 1,
"command-gating": 5,
lmstudio: 37,
"lmstudio-runtime": 27,
"provider-setup": 1,
"self-hosted-provider-setup": 14,
routing: 1,
runtime: 3,
// Deprecated Telegram-named alias retained for plugin SDK compatibility.
"retry-runtime": 1,
"runtime-logger": 3,
"runtime-secret-resolution": 5,
"secret-provider-integration": 4,
"setup-adapter-runtime": 1,
"skills-runtime": 5,
"channel-streaming": 55,
health: 1,
"channel-streaming": 54,
"approval-gateway-runtime": 1,
"approval-handler-runtime": 1,
"approval-reply-runtime": 3,
"approval-runtime": 1,
"config-runtime": 123,
"approval-reply-runtime": 1,
"config-runtime": 116,
"config-contracts": 1,
// +1 each: unified implicit-mention config and AgentThinkingLevel types.
// +1: SwarmConfig mirrors the public tools.swarm config contract.
"config-types": 428,
"config-schema": 3,
"reply-dedupe": 1,
"inbound-reply-dispatch": 26,
"channel-reply-pipeline": 12,
"channel-reply-options-runtime": 2,
"channel-runtime": 144,
"interactive-runtime": 13,
"outbound-send-deps": 4,
"outbound-runtime": 16,
"file-access-runtime": 2,
"infra-runtime": 595,
"infra-runtime": 593,
"ssrf-policy": 1,
"ssrf-runtime": 1,
"media-runtime": 2,
"text-runtime": 191,
"agent-core": 1,
"agent-runtime": 7,
"plugin-runtime": 13,
"agent-runtime": 2,
"channel-secret-runtime": 23,
"secret-file-runtime": 1,
"security-runtime": 7,
"agent-harness": 7,
"agent-harness-runtime": 11,
types: 6,
"agent-harness-runtime": 5,
"agent-config-primitives": 2,
"command-auth": 81,
// +2: group scope encoder/key builder mirrored by deprecated compat.
// +5: shared channel setup, policy, and config schema helpers.
compat: 167,
"direct-dm": 9,
"direct-dm-access": 5,
"command-auth": 78,
discord: 48,
mattermost: 7,
matrix: 1,
// +3: shared multi-account and group-entry schema builders.
"channel-config-schema-legacy": 25,
"channel-actions": 2,
"channel-envelope": 3,
"channel-inbound": 21,
"channel-inbound-roots": 1,
"channel-inbound": 15,
"channel-logging": 4,
"channel-location": 4,
"channel-mention-gating": 7,
"channel-lifecycle": 23,
// Registry sweep: 77 packages, zero fetch failures; channel-ingress and dead aliases
// had zero consumers.
// +11 each: durable channel-ingress drain seam (drain/lifecycle/claim/retry) mirrored by compat (#108656).
// +3 each: shared ingress monitor factory and lifecycle/result contracts.
"channel-message": 244,
"channel-message-runtime": 241,
"channel-pairing-paths": 1,
// Deprecated pairing/conversation exports from the SQLite pairing migration
// landed on main (#105802) without entrypoint pins; not touched by this PR.
"channel-message": 129,
"channel-pairing": 1,
"conversation-runtime": 4,
"channel-policy": 8,
"channel-send-result": 1,
"channel-policy": 15,
"channel-route": 5,
"session-store-runtime": 4,
"session-transcript-runtime": 2,
"group-access": 13,
"media-generation-runtime-shared": 3,
"music-generation-core": 20,
"reply-history": 8,
"messaging-targets": 12,
"memory-core": 45,
"memory-core-engine-runtime": 15,
"memory-core-host-multimodal": 3,
"memory-core-host-query": 2,
"memory-core-host-events": 12,
"memory-core-host-status": 1,
"memory-core-host-runtime-core": 1,
"memory-host-core": 1,
"memory-host-files": 7,
"memory-host-status": 72,
"provider-auth": 20,
"provider-oauth-runtime": 2,
"provider-auth-login": 3,
"provider-model-shared": 30,
"provider-stream-family": 40,
"provider-stream-shared": 29,
"provider-stream": 40,
"provider-web-search": 1,
"provider-zai-endpoint": 3,
"provider-auth": 19,
"telegram-account": 3,
"telegram-command-config": 7,
"webhook-ingress": 2,
"webhook-path": 2,
zalouser: 5,
zod: 282,
});
@@ -213,174 +135,32 @@ export function readPluginSdkSurfaceBudgets(env = process.env) {
const budgets = {
publicEntrypoints: readPluginSdkSurfaceBudgetEnv(
"OPENCLAW_PLUGIN_SDK_MAX_PUBLIC_ENTRYPOINTS",
// Registry sweep: 77 packages, zero fetch failures; retired dead channel-ingress facade.
// +1: speech-settings keeps agent prompt imports off the synthesis/runtime graph.
// +1: meeting-runtime barrel: browser meeting-bot core behind MeetingPlatformAdapter.
// +1: question-gateway-runtime resolves ask_user choices for channel plugins.
// +1: ingress-effect-once gives drained channels a narrow durable side-effect guard.
// +1: session-discussion binds one external discussion provider to sessions.
333,
140,
env,
),
// ScopeTree adds six channel-policy exports, mirrored by compat, including three functions.
// Its flat channel-groups builder adds one function, also mirrored by compat.
// Its case-insensitive scope-key resolver adds one function, also mirrored by compat.
// Its length-prefixed segment encoder and scope-key builder add two functions, also mirrored.
// The focused HTML entity runtime and quote-aware HTML tokenizer add one public function each.
// Plugin service Gateway event scope and emitter types add four facade exports.
publicExports: readPluginSdkSurfaceBudgetEnv(
"OPENCLAW_PLUGIN_SDK_MAX_PUBLIC_EXPORTS",
// +4: registerMcpServerConnectionResolver context/result/resolver/registration types (#106229).
// +2: materializeRequesterScopedMcpToolsForHarnessRun (agent-harness-runtime + compat mirror).
// +1: matchesNoProxy exposes canonical Undici-compatible bypass selection to plugins.
// +4: group scope encoder/key builder (channel-policy + compat mirror).
// +1: runDetachedWebhookWork gives post-ack work an independently tracked admission root.
// +9: app-guided provider setup context/candidate/hook types and their public mirrors.
// +3: atomic SQLite STRICT migration function, options, and result for plugin stores.
// Harvest: channel-ingress -64; dead channel-message dispatch aliases -23.
// Harvest: retired qa-live-transport-scenarios subpath -6.
// +12: typed plan step/status and checklist formatter across channel barrels.
// +8: plan-step ingress union and normalizer across channel barrels.
// Harvest: retired dual-field plan payload builder -1.
// +12: active plan-step consumers pinned through channel-outbound and mirrors.
// +6: app-guided provider setup types retained by plugin-entry and mirrors.
// +3: widget HTML validation helpers and tool input error.
// Used-union narrowing: 31 wildcard barrels drop to explicit used exports;
// proxy stream API and codex marker/scaffold pins retained.
// +2: generic channel retry runner and Retry-After parser.
// +1: shared speech-provider API key resolver.
// +32: shared channel setup, config-schema, policy, and status helpers.
// +2: shared channel replay-guard factory and claim handle.
// +6: lightweight speech settings types, normalizers, and config resolver.
// +4: unified implicit-mention config, schema, resolved policy, and resolver.
// Harvest: retired AudioConfig type -1.
// +4: bounded plugin blob store options, entry, entry info, and store types.
// +6: shared progress receipt tracker + compositor snapshot across channel barrels.
// +1: selectPreferredLocalModelId shares app-guided local model ranking across providers.
// +4: shared audio-energy stats and speech-threshold gate through realtime-voice.
// +2: supplemental sender decision and outbound text chunk sequencer.
// +2: shared realtime voice session harness through realtime-voice.
// +24: narrowed durable channel-ingress drain seam — factory, lifecycle binding,
// tuning constants, and telegram-consumed claim helpers with compat mirrors,
// after harvesting exports orphaned by the split-out WhatsApp adapter (#108656).
// +10: supplemental sender helpers plus host-owned SQLite lease contracts.
// Harvest: retired dual-field plan payload builder -1.
// +23: core channel, envelope, direct-DM, feedback, legacy-payload, and memory contracts.
// +81: meeting-runtime barrel: browser meeting-bot core behind MeetingPlatformAdapter.
// +3: question-gateway-runtime resolver plus request/result types.
// +1: async memory prompt preparation registration.
// +1: canonical memory host event normalization for SQLite storage.
// +1: centralized remember-across-conversations effective-default resolver.
// +4: gateway-backed harness question runner, claim/cancel helpers, and caller type.
// Harvest: internal question runtime exports -2.
// +1: ingress-effect-once factory.
// +1: shared persistent-dedupe claim loop.
// +3: bounded raw transcript cursor request, result, and reader.
// +3: bounded visible transcript cursor request, result, and reader.
// +1: explicit AgentModelPolicyConfig shared with provider setup surfaces.
// +1: AgentHarnessSessionSupersededError lets harness plugins stop stale-owner fallback.
// +1: AgentThinkingLevel shared by default-turn and compaction config.
// +9: shared ingress monitor factory and lifecycle/result contracts across
// channel-outbound and its two deprecated compatibility barrels.
// +1: SwarmConfig exposes the tools.swarm contract through config-types.
// +3: harness sessionFork capability params, result, and failure-code contracts.
// +2: upstream-link registry write/delete for harness-owned session forks.
// Harvest: mention-pattern schemas and helper exports -3.
// +1: config-backed main-session resolver for Gateway-hosted plugin services.
// +9: outbound echo identity type and record/query helpers across
// channel-outbound and its two compatibility barrels.
// Net +1: public session catalog locator types after the protocol cleanup harvest.
// +2: lifecycle-owned prepared model catalog sync and async readers.
// Harvest: retired tuning-knob config types -10.
// Harvest: removed process-global API-provider publication functions -2.
// +4: session discussion state, info, provider, and registration contracts.
// +2: structured media placeholder formatter and its text-fact contract.
8186,
4721,
env,
),
publicFunctionExports: readPluginSdkSurfaceBudgetEnv(
"OPENCLAW_PLUGIN_SDK_MAX_PUBLIC_FUNCTION_EXPORTS",
// +2: materializeRequesterScopedMcpToolsForHarnessRun (agent-harness-runtime + compat mirror).
// +4: group scope encoder/key builder (channel-policy + compat mirror).
// +1: atomic SQLite STRICT migration for plugin stores.
// +1: runDetachedWebhookWork gives post-ack work an independently tracked admission root.
// Harvest: channel-ingress -19; dead channel-message dispatch aliases -23.
// Harvest: retired qa-live-transport-scenarios subpath -3.
// +4: shared plan checklist formatter across channel barrels.
// +4: plan-step normalizer across channel barrels.
// Harvest: retired dual-field plan payload builder -1.
// +6: active plan-step helpers pinned through channel-outbound and mirrors.
// +2: widget HTML document detection and size assertion.
// Used-union narrowing of the 31 wildcard barrels.
// +2: generic channel retry runner and Retry-After parser.
// +1: shared speech-provider API key resolver.
// +24: shared channel setup, config-schema, policy, and status helpers.
// +1: shared channel replay-guard factory.
// +3: receipt tracker/snapshot callables across channel barrels.
// +3: lightweight speech settings normalizers and config resolver.
// +1: unified implicit-mention policy resolver.
// +1: selectPreferredLocalModelId shares app-guided local model ranking across providers.
// +3: PCM16/mu-law energy readers and speech-threshold gate factory.
// +2: supplemental sender decision and outbound text chunk sequencer.
// +1: shared realtime voice session harness through realtime-voice.
// +9: narrowed drain seam functions and compat mirrors after the
// WhatsApp-split harvest (#108656).
// +3: supplemental sender helpers plus the PluginStateLeaseRunner callback.
// Harvest: retired dual-field plan payload builder -1.
// +13: core channel, envelope, direct-DM, feedback, legacy-payload, and memory operations.
// +32: meeting-runtime barrel: browser meeting-bot core behind MeetingPlatformAdapter.
// +1: question-gateway-runtime resolver.
// +1: async memory prompt preparation registration.
// +1: canonical memory host event normalization for SQLite storage.
// +1: centralized remember-across-conversations effective-default resolver.
// +3: gateway-backed harness question runner and claim/cancel helpers.
// Harvest: internal question runtime callable -1.
// +1: ingress-effect-once factory.
// +1: shared persistent-dedupe claim loop.
// +1: bounded raw transcript cursor reader.
// +1: bounded visible transcript cursor reader.
// +3: shared ingress monitor factory across channel-outbound and compat mirrors.
// +2: upstream-link registry write/delete for harness-owned session forks.
// +1: config-backed main-session resolver for Gateway-hosted plugin services.
// +6: outbound echo record/query helpers across channel-outbound and mirrors.
// +2: lifecycle-owned prepared model catalog sync and async readers.
// Harvest: removed process-global API-provider publication functions -2.
// +1: session discussion provider registration.
// +1: structured media placeholder formatter for text-only channel carriers.
4557,
2879,
env,
),
publicDeprecatedExports: readPluginSdkSurfaceBudgetEnv(
"OPENCLAW_PLUGIN_SDK_MAX_PUBLIC_DEPRECATED_EXPORTS",
// +2: group scope encoder/key builder mirrored by deprecated compat.
// Harvest: channel-ingress -8; dead channel-message dispatch aliases -23.
// +77: five zero-consumer subpaths enter their removal window.
// +9: typed plan exports and formatter through deprecated channel barrels.
// +6: plan-step ingress union and normalizer through deprecated channel barrels.
// +8: channel-outbound plan pins mirrored through deprecated barrels.
// Used-union narrowing drops inherited deprecated exports.
// +1: Telegram runner alias retained for plugin SDK compatibility.
// +8: shared channel helpers mirrored by deprecated barrels.
// +3: receipt/snapshot exports through deprecated channel barrels.
// +1: unified implicit-mention config type through deprecated config-types.
// +24: narrowed drain seam compat mirrors in the channel-message
// deprecation-window barrels (#108656).
// Harvest: retired dual-field plan payload builder -1; lower-only drift -8.
// +1: AgentModelPolicyConfig mirrored by deprecated config-types.
// +6: ingress monitor lifecycle/result contracts through deprecated channel barrels.
// +1: AgentThinkingLevel mirrored by deprecated config-types.
// +1: SwarmConfig mirrored by deprecated config-types.
// +2: outbound echo helpers inherited by deprecated channel barrels.
// +1: lifecycle-owned prepared model catalog contract mirrored by agent-runtime compat.
3017,
1697,
env,
),
publicWildcardReexports: readPluginSdkSurfaceBudgetEnv(
"OPENCLAW_PLUGIN_SDK_MAX_PUBLIC_WILDCARD_REEXPORTS",
// Used-union narrowing removes 103 wildcard re-exports.
// Harvest: freeze the compat config-schema barrel to explicit exports -1;
// retire the Memory Core facade's event-store wildcard -1.
103,
83,
env,
),
};
-13
View File
@@ -28,7 +28,6 @@ import { expandPackageDistImportClosure } from "./lib/package-dist-imports.mjs";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const DEFAULT_PACKAGE_ROOT = join(scriptDir, "..");
const DISABLE_POSTINSTALL_ENV = "OPENCLAW_DISABLE_BUNDLED_PLUGIN_POSTINSTALL";
const DISABLE_PLUGIN_REGISTRY_MIGRATION_ENV = "OPENCLAW_DISABLE_PLUGIN_REGISTRY_MIGRATION";
const DIST_INVENTORY_PATH = "dist/postinstall-inventory.json";
// One budget covers all three prune walks (legacy-deps prepass, file listing,
// empty-dir sweep). npm upgrades transiently hold old+new content-hashed dist
@@ -116,11 +115,6 @@ const NODE_COMPILE_CACHE_VERSION_DIR_RE = /^v\d+\.\d+\.\d+-/u;
class InstalledDistScanLimitError extends Error {}
function hasEnvFlag(env, key) {
const value = env?.[key]?.trim().toLowerCase();
return Boolean(value && value !== "0" && value !== "false" && value !== "no");
}
function normalizeRelativePath(filePath) {
return filePath.replace(/\\/g, "/");
}
@@ -830,10 +824,6 @@ export async function runPluginRegistryPostinstallMigration(params = {}) {
const packageRoot = params.packageRoot ?? DEFAULT_PACKAGE_ROOT;
const env = params.env ?? process.env;
if (hasEnvFlag(env, DISABLE_PLUGIN_REGISTRY_MIGRATION_ENV)) {
return { status: "disabled", migrated: false, reason: "disabled-env" };
}
try {
const migrationModule = await importInstalledDistModule(
params,
@@ -850,9 +840,6 @@ export async function runPluginRegistryPostinstallMigration(params = {}) {
env,
packageRoot,
});
for (const warning of result.preflight?.deprecationWarnings ?? []) {
log.warn(`[postinstall] ${warning}`);
}
if (result.migrated) {
log.log(
`[postinstall] migrated plugin registry: ${result.current.plugins.length} plugin(s) indexed`,
@@ -11,7 +11,7 @@ import {
resolveRepoToolBinPath,
} from "./lib/local-heavy-check-runtime.mjs";
import { parsePositiveInt } from "./lib/numeric-options.mjs";
import { pluginSdkEntrypoints, publicPluginSdkEntrypoints } from "./lib/plugin-sdk-entries.mjs";
import { pluginSdkEntrypoints, productionPluginSdkEntrypoints } from "./lib/plugin-sdk-entries.mjs";
import { resolveWindowsTaskkillPath } from "./lib/windows-taskkill.mjs";
const repoRoot = resolve(import.meta.dirname, "..");
@@ -311,21 +311,18 @@ const ENTRY_SHIMS_INPUTS = [
"scripts/lib/plugin-sdk-entrypoints.json",
"scripts/lib/plugin-sdk-entries.mjs",
];
const ENTRY_SHIM_RUNTIME_OUTPUTS = ["dist/plugin-sdk/webhook-path.js"];
/**
* Lists entry-shim artifacts written by scripts/write-plugin-sdk-entry-dts.ts.
*/
export function resolveBoundaryEntryShimRequiredOutputs(env = process.env) {
const entries =
env.OPENCLAW_BUILD_PRIVATE_QA === "1" ? pluginSdkEntrypoints : publicPluginSdkEntrypoints;
return [
...entries.flatMap((entry) => [
env.OPENCLAW_BUILD_PRIVATE_QA === "1" ? pluginSdkEntrypoints : productionPluginSdkEntrypoints;
return entries
.flatMap((entry) => [
`dist/plugin-sdk/${entry}.d.ts`,
`packages/plugin-sdk/dist/src/plugin-sdk/${entry}.d.ts`,
]),
...ENTRY_SHIM_RUNTIME_OUTPUTS,
].toSorted((a, b) => a.localeCompare(b));
])
.toSorted((a, b) => a.localeCompare(b));
}
function isRelevantTypeInput(filePath) {
+8 -14
View File
@@ -41,7 +41,8 @@ import {
import { collectBundledPluginPackageDependencySpecs } from "./lib/plugin-package-dependencies.mjs";
import {
listPluginSdkDistArtifacts,
listPrivateLocalOnlyPluginSdkDistArtifacts,
listPackagedPrivatePluginSdkRuntimeArtifacts,
listUnpackagedPrivatePluginSdkDistArtifacts,
} from "./lib/plugin-sdk-entries.mjs";
import {
runInstalledWorkspaceBootstrapSmoke,
@@ -87,6 +88,7 @@ const requiredPathGroups = [
["dist/index.js", "dist/index.mjs"],
["dist/entry.js", "dist/entry.mjs"],
...listPluginSdkDistArtifacts(),
...listPackagedPrivatePluginSdkRuntimeArtifacts(),
...listBundledPluginPackArtifacts(),
...listStaticExtensionAssetOutputs().filter((relativePath) => {
const match = /^dist\/extensions\/([^/]+)\//u.exec(relativePath);
@@ -107,8 +109,6 @@ const requiredPathGroups = [
"scripts/lib/recommended-tool-installs.json",
"scripts/lib/package-dist-imports.mjs",
"scripts/postinstall-bundled-plugins.mjs",
"dist/plugin-sdk/compat.js",
"dist/plugin-sdk/root-alias.cjs",
"dist/agents/compaction-planning.worker.js",
"dist/agents/model-provider-auth.worker.js",
"dist/audit/audit-event-writer.worker.js",
@@ -139,7 +139,11 @@ const forbiddenPrefixes = [
"dist/plugin-sdk/src/plugin-sdk/qa-channel-protocol.d.ts",
"dist/plugin-sdk/src/plugin-sdk/qa-lab.d.ts",
"dist/plugin-sdk/src/plugin-sdk/qa-runtime.d.ts",
...listPrivateLocalOnlyPluginSdkDistArtifacts(),
"dist/plugin-sdk/index.",
"dist/plugin-sdk/compat.",
"dist/plugin-sdk/root-alias.",
"dist/extensionAPI.",
...listUnpackagedPrivatePluginSdkDistArtifacts(),
"dist/qa-runtime-",
"dist/plugin-sdk/.tsbuildinfo",
"docs/.generated/",
@@ -161,7 +165,6 @@ const forbiddenPrivatePluginSdkDeclarationMarkers = [
"//#region src/test-utils/",
] as const;
const forbiddenPrivateQaContentScanPrefixes = ["dist/"] as const;
const forbiddenPluginSdkRootAliasMinifiedExportPattern = /\bmod\.[A-Za-z_$]\b/u;
const appcastPath = resolve("appcast.xml");
const laneBuildMin = 1_000_000_000;
const laneFloorAdoptionReleaseKey = 20260227;
@@ -671,15 +674,6 @@ export function collectPackedInstalledPackageVerificationErrors(params: {
`installed openclaw binary version mismatch: expected ${params.expectedVersion}, found ${params.installedBinaryVersion || "<missing>"}.`,
);
}
const rootAliasPath = join(params.packageRoot, "dist", "plugin-sdk", "root-alias.cjs");
if (existsSync(rootAliasPath)) {
const rootAliasSource = readFileSync(rootAliasPath, "utf8");
if (forbiddenPluginSdkRootAliasMinifiedExportPattern.test(rootAliasSource)) {
errors.push(
"installed package dist/plugin-sdk/root-alias.cjs depends on a single-letter bundled export alias.",
);
}
}
return errors;
}
-9
View File
@@ -47,7 +47,6 @@ const RUN_NODE_SIGNAL_FORCE_KILL_AFTER_MS = 5_000;
const runtimePostBuildWatchedPaths = [
"scripts/copy-bundled-plugin-metadata.mjs",
"scripts/copy-plugin-sdk-root-alias.mjs",
"scripts/lib",
"scripts/lib/local-build-metadata.mjs",
"scripts/lib/local-build-metadata-paths.mjs",
@@ -58,7 +57,6 @@ const runtimePostBuildWatchedPaths = [
"scripts/stage-bundled-plugin-runtime.mjs",
"scripts/windows-cmd-helpers.mjs",
"scripts/write-official-channel-catalog.mjs",
"src/plugin-sdk/root-alias.cjs",
BUNDLED_PLUGIN_ROOT_DIR,
];
const runtimePostBuildScriptPaths = new Set(
@@ -173,9 +171,6 @@ const hasDirtySourceTree = (deps) => {
const isRuntimePostBuildRelevantPath = (repoPath) => {
const normalizedPath = normalizePath(repoPath).replace(/^\.\/+/, "");
if (normalizedPath === "src/plugin-sdk/root-alias.cjs") {
return true;
}
if (runtimePostBuildStaticAssetPaths.has(normalizedPath)) {
return true;
}
@@ -434,10 +429,6 @@ const readPackageJsonPluginSdkAliasFileNames = (deps) => {
const fileNames = new Set();
for (const exportKey of Object.keys(packageExports)) {
if (exportKey === "./plugin-sdk") {
fileNames.add("index.js");
continue;
}
if (!exportKey.startsWith("./plugin-sdk/")) {
continue;
}
-11
View File
@@ -5,7 +5,6 @@ import path from "node:path";
import { performance } from "node:perf_hooks";
import { fileURLToPath, pathToFileURL } from "node:url";
import { copyBundledPluginMetadata } from "./copy-bundled-plugin-metadata.mjs";
import { copyPluginSdkRootAlias } from "./copy-plugin-sdk-root-alias.mjs";
import { escapeRegExp } from "./lib/regexp.mjs";
import {
copyStaticExtensionAssets,
@@ -24,7 +23,6 @@ const ROOT_RUNTIME_ALIAS_PATTERN = /^(?<base>.+\.(?:runtime|contract))-[A-Za-z0-
const ROOT_STABLE_RUNTIME_ALIAS_PATTERN = /^.+\.(?:runtime|contract)\.js$/u;
const ROOT_RUNTIME_IMPORT_SPECIFIER_PATTERN =
/(["'])\.\/([^"']+\.(?:runtime|contract)-[A-Za-z0-9_-]+\.js)\1/gu;
const PLUGIN_SDK_ROOT_ALIAS_OUTPUT = "dist/plugin-sdk/root-alias.cjs";
const OFFICIAL_CHANNEL_CATALOG_OUTPUT = "dist/channel-catalog.json";
const LEGACY_ROOT_RUNTIME_COMPAT_ALIASES = [
// v2026.4.29 dispatch lazy chunks. Package updates used to replace the
@@ -147,13 +145,6 @@ const LEGACY_CLI_EXIT_COMPAT_CHUNKS = [
},
];
/**
* Lists generated plugin SDK root-alias outputs.
*/
function listPluginSdkRootAliasOutputs() {
return [PLUGIN_SDK_ROOT_ALIAS_OUTPUT];
}
/**
* Lists generated official channel catalog outputs.
*/
@@ -292,7 +283,6 @@ function listLegacyRootRuntimeCompatOutputs(params = {}) {
*/
export function listCoreRuntimePostBuildOutputs(params = {}) {
return [
...listPluginSdkRootAliasOutputs(),
...listOfficialChannelCatalogOutputs(),
...listStableRootRuntimeAliasOutputs(params),
...listLegacyRootRuntimeCompatOutputs(params),
@@ -584,7 +574,6 @@ export function runRuntimePostBuild(params = {}) {
`runtime-postbuild: ${phaseTimings.length} phases completed in ${totalMs}ms (slowest: ${slowest.label} ${slowest.durationMs}ms)`,
);
};
runPhase("plugin SDK root alias", () => copyPluginSdkRootAlias(params));
runPhase("bundled plugin metadata", () => copyBundledPluginMetadata(params));
runPhase("official channel catalog", () => writeOfficialChannelCatalog(params));
runPhase("bundled plugin runtime overlay", () => stageBundledPluginRuntime(params));
+5 -21
View File
@@ -83,7 +83,6 @@ const PRIVATE_LOCAL_ONLY_PLUGIN_SDK_DIST_FILE_NAME_FALLBACK = [
"qa-lab.js",
"qa-runtime.js",
"ssrf-runtime-internal.js",
"test-utils.js",
];
function tryReadJsonFile(targetPath) {
@@ -141,10 +140,6 @@ function readPublicPluginSdkDistFileNames(params) {
const fileNames = new Set();
for (const exportKey of Object.keys(packageExports)) {
if (exportKey === "./plugin-sdk") {
fileNames.add("index.js");
continue;
}
if (!exportKey.startsWith("./plugin-sdk/")) {
continue;
}
@@ -159,27 +154,16 @@ function readPublicPluginSdkDistFileNames(params) {
function buildRuntimePluginSdkPackageExports(publicDistFileNames) {
if (!publicDistFileNames) {
return {
"./plugin-sdk": "./plugin-sdk/index.js",
};
return {};
}
const sortedFileNames = [...publicDistFileNames].toSorted((left, right) => {
if (left === "index.js") {
return -1;
}
if (right === "index.js") {
return 1;
}
return left.localeCompare(right);
});
const sortedFileNames = [...publicDistFileNames].toSorted((left, right) =>
left.localeCompare(right),
);
return Object.fromEntries(
sortedFileNames.map((fileName) => {
const subpath = fileName.slice(0, -".js".length);
return [
subpath === "index" ? "./plugin-sdk" : `./plugin-sdk/${subpath}`,
`./plugin-sdk/${fileName}`,
];
return [`./plugin-sdk/${subpath}`, `./plugin-sdk/${fileName}`];
}),
);
}
+1 -2
View File
@@ -78,8 +78,7 @@ fs.writeFileSync(
fs.writeFileSync(
path.join(distPluginDir, "index.js"),
[
"import sdk from 'openclaw/plugin-sdk';",
"const { emptyPluginConfigSchema } = sdk;",
"import { emptyPluginConfigSchema } from 'openclaw/plugin-sdk/plugin-entry';",
"",
"export default {",
` id: ${JSON.stringify(pluginId)},`,
-1
View File
@@ -427,7 +427,6 @@ const PRECISE_SOURCE_TEST_TARGETS = new Map([
]);
const PLUGIN_SDK_ENTRY_METADATA_TEST_TARGETS = [
"src/plugins/contracts/plugin-sdk-index.bundle.test.ts",
"src/plugins/contracts/plugin-sdk-index.test.ts",
"src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts",
"src/plugins/contracts/plugin-sdk-subpaths.test.ts",
"src/plugins/contracts/extension-package-project-boundaries.test.ts",
+2 -45
View File
@@ -6,44 +6,9 @@ import { build } from "tsdown";
import {
buildPluginSdkEntrySources,
pluginSdkEntrypoints,
publicPluginSdkEntrypoints,
productionPluginSdkEntrypoints,
} from "./lib/plugin-sdk-entries.mjs";
const RUNTIME_SHIMS: Partial<Record<string, string>> = {
"webhook-path": [
"/** Normalize webhook paths into the canonical registry form used by route lookup. */",
"export function normalizeWebhookPath(raw) {",
" const trimmed = raw.trim();",
" if (!trimmed) {",
' return "/";',
" }",
' const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;',
' if (withSlash.length > 1 && withSlash.endsWith("/")) {',
" return withSlash.slice(0, -1);",
" }",
" return withSlash;",
"}",
"",
"/** Resolve the effective webhook path from explicit path, URL, or default fallback. */",
"export function resolveWebhookPath(params) {",
" const trimmedPath = params.webhookPath?.trim();",
" if (trimmedPath) {",
" return normalizeWebhookPath(trimmedPath);",
" }",
" if (params.webhookUrl?.trim()) {",
" try {",
" const parsed = new URL(params.webhookUrl);",
' return normalizeWebhookPath(parsed.pathname || "/");',
" } catch {",
" return null;",
" }",
" }",
" return params.defaultPath ?? null;",
"}",
"",
].join("\n"),
};
const USE_CANONICAL_DECLARATIONS = process.env.OPENCLAW_PLUGIN_SDK_CANONICAL_DTS === "1";
function isBareImportSpecifier(id: string): boolean {
@@ -87,7 +52,7 @@ const distPluginSdkDir = path.join(process.cwd(), "dist/plugin-sdk");
const shouldBuildPrivateQaEntries = process.env.OPENCLAW_BUILD_PRIVATE_QA === "1";
const flatDeclarationEntrypoints = shouldBuildPrivateQaEntries
? pluginSdkEntrypoints
: publicPluginSdkEntrypoints;
: productionPluginSdkEntrypoints;
const flatDeclarationEntrypointSet = new Set(flatDeclarationEntrypoints);
if (USE_CANONICAL_DECLARATIONS) {
@@ -144,14 +109,6 @@ for (const entry of pluginSdkEntrypoints) {
`export * from "../../../../../dist/plugin-sdk/${entry}.js";\n`,
"utf8",
);
const runtimeShim = RUNTIME_SHIMS[entry];
if (!runtimeShim) {
continue;
}
const runtimeOut = path.join(process.cwd(), `dist/plugin-sdk/${entry}.js`);
fs.mkdirSync(path.dirname(runtimeOut), { recursive: true });
fs.writeFileSync(runtimeOut, runtimeShim, "utf8");
}
const stampPath = path.join(process.cwd(), "dist/plugin-sdk/.boundary-entry-shims.stamp");