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

@@ -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"],