fix(packaging): include required peers in fresh npm installs (#160015)

This commit is contained in:
Peter Steinberger
2026-09-27 18:44:04 -07:00
committed by GitHub
parent cff990a848
commit ce73f2c8f2
4 changed files with 63 additions and 2 deletions
+2 -1
View File
@@ -2248,7 +2248,8 @@
},
"bundleDependencies": [
"@openclaw/proxyline",
"chrome-devtools-mcp"
"chrome-devtools-mcp",
"undici"
],
"dependencies": {
"@agentclientprotocol/sdk": "1.4.0",
+3 -1
View File
@@ -8,7 +8,9 @@ agent to retain per-request `NO_PROXY` routing even when every configured proxy
route is invalid. The patch changes only the package entrypoint and regenerated
entrypoint declarations; proxy behavior and the package version are unchanged.
The root package bundles the dependency so npm installations retain the export.
Remove this patch, its registration, and the bundle entry when an upstream release
Its pinned Undici peer is bundled too: npm infers that bundled peers are already
present and otherwise skips installing Undici, even though the root requires it.
Remove this patch, its registration, and both bundle entries when an upstream release
exports the standalone agent and passes `extensions/whatsapp/src/session.media-upload.test.ts`
and `src/infra/net/node-proxy-agent.test.ts` without the patch.
@@ -236,6 +236,18 @@ export function collectBundledDependencyErrors({
errors.push(`bundled ${name} package.json must name ${name}`);
continue;
}
// npm infers peers of bundled packages are already in the bundle, while
// packlist excludes them unless explicitly bundled. Missing peers are not
// installed, even when the root declares them as required dependencies.
const peers = isRecord(manifest.peerDependencies) ? manifest.peerDependencies : {};
for (const peer of Object.keys(peers)) {
if (
typeof dependencies[peer] === "string" &&
!runtime.entries.has(`node_modules/${peer}/package.json`)
) {
errors.push(`bundled ${name} is missing its root dependency peer ${peer}`);
}
}
const bundled = { ...runtime, name };
if (name === PATCHED_MCP_NAME) {
errors.push(...collectPatchedMcpErrors(bundled, manifest, dependencies[PATCHED_MCP_NAME]));
@@ -1085,6 +1085,52 @@ syncBuiltinESMExports();
);
const bundledRuntimeCases: NamedTarballCheck[] = [
...[
{ bundledPeer: false, optional: false },
{ bundledPeer: false, optional: true },
{ bundledPeer: true, optional: false },
].map(({ bundledPeer, optional }): NamedTarballCheck => ({
name: `${bundledPeer ? "accepts" : "rejects"} a bundled dependency with ${bundledPeer ? "a bundled" : "a missing"} root-required ${optional ? "optional" : "required"} peer`,
files: {
"dist/index.js": "export {};\n",
"node_modules/example/package.json": JSON.stringify({
name: "example",
version: "1.0.0",
peerDependencies: { host: "^1.0.0" },
...(optional ? { peerDependenciesMeta: { host: { optional: true } } } : {}),
}),
...(bundledPeer
? { "node_modules/host/package.json": '{"name":"host","version":"1.0.0"}\n' }
: {}),
},
options: {
packageJson: {
dependencies: { example: "1.0.0", host: "1.0.0" },
bundleDependencies: bundledPeer ? ["example", "host"] : ["example"],
},
},
status: bundledPeer ? 0 : "nonzero",
stderr: bundledPeer ? [] : ["bundled example is missing its root dependency peer host"],
})),
{
name: "accepts an absent optional peer of a bundled dependency",
files: {
"dist/index.js": "export {};\n",
"node_modules/example/package.json": JSON.stringify({
name: "example",
version: "1.0.0",
peerDependencies: { host: "^1.0.0" },
peerDependenciesMeta: { host: { optional: true } },
}),
},
options: {
packageJson: {
dependencies: { example: "1.0.0" },
bundleDependencies: ["example"],
},
},
status: 0,
},
{
name: "accepts npm-selected bundled and hoisted transitive dependency paths",
files: {