fix(npm): avoid pnpm optional postinstall hangs

This commit is contained in:
Hunter Bown
2026-05-14 14:50:05 -05:00
parent ae9e4b4b24
commit 47f3c410d6
2 changed files with 46 additions and 0 deletions
+19
View File
@@ -103,6 +103,18 @@ function isInstallContext(context) {
return context === "install";
}
function isPnpmUserAgent(env = process.env) {
return String(env.npm_config_user_agent || "").toLowerCase().includes("pnpm/");
}
function shouldSkipOptionalPostinstall(
context,
argv = process.argv.slice(2),
env = process.env,
) {
return isInstallContext(context) && isOptionalInstall(argv, env) && isPnpmUserAgent(env);
}
// Optional install only relaxes npm postinstall behavior. Runtime downloads
// keep the normal retry/timeout budget so first-run recovery stays resilient.
function defaultTimeoutMs(context = "runtime", env = process.env) {
@@ -1089,6 +1101,12 @@ async function run(options = {}) {
if (process.env.DEEPSEEK_TUI_DISABLE_INSTALL === "1" || process.env.DEEPSEEK_DISABLE_INSTALL === "1") {
return;
}
if (shouldSkipOptionalPostinstall(context)) {
logInfo(
"pnpm optional postinstall detected; skipping install-time download. The binary will be checked on first run.",
);
return;
}
const version = resolvePackageVersion();
const repo = resolveRepo();
const paths = binaryPaths();
@@ -1129,6 +1147,7 @@ module.exports = {
isOptionalInstall,
adoptExistingBinaryIfValid,
shouldIgnoreInstallFailure,
shouldSkipOptionalPostinstall,
defaultTimeoutMs,
defaultStallMs,
ensureBinary,
+27
View File
@@ -24,6 +24,33 @@ test("optional mode only changes install-time defaults", () => {
assert.equal(_internal.defaultStallMs("runtime", { DEEPSEEK_TUI_OPTIONAL_INSTALL: "1" }), 30_000);
});
test("pnpm optional postinstall skips install-time download", () => {
assert.equal(
_internal.shouldSkipOptionalPostinstall("install", ["--optional"], {
npm_config_user_agent: "pnpm/10.11.0 npm/? node/v22.15.0 win32 x64",
}),
true,
);
assert.equal(
_internal.shouldSkipOptionalPostinstall("runtime", ["--optional"], {
npm_config_user_agent: "pnpm/10.11.0 npm/? node/v22.15.0 win32 x64",
}),
false,
);
assert.equal(
_internal.shouldSkipOptionalPostinstall("install", [], {
npm_config_user_agent: "pnpm/10.11.0 npm/? node/v22.15.0 win32 x64",
}),
false,
);
assert.equal(
_internal.shouldSkipOptionalPostinstall("install", ["--optional"], {
npm_config_user_agent: "npm/11.3.0 node/v22.15.0 win32 x64",
}),
false,
);
});
test("optional install only swallows retryable download failures", () => {
const socketHangUp = new Error("socket hang up");
assert.equal(