
















@@ -387,13 +387,24 @@ describe("update global helpers", () => {
387387const managedNpmRoot = path.join(base, ".openclaw", "npm", "node_modules");
388388const pkgRoot = path.join(managedNpmRoot, "openclaw");
389389const pathNpmRoot = path.join(base, "shell", "lib", "node_modules");
390+const otherPnpmRoot = path.join(base, "pnpm", "global", "5", "node_modules");
391+const customNpm = path.join(base, "bin", "npm");
390392await fs.mkdir(pkgRoot, { recursive: true });
393+await fs.mkdir(path.join(otherPnpmRoot, "openclaw"), { recursive: true });
391394392-const runCommand = createNpmRootRunner({ defaultNpmRoot: pathNpmRoot });
395+const runCommand: CommandRunner = async (argv) => {
396+if (argv[0] === "npm" || argv[0] === customNpm) {
397+return { stdout: `${pathNpmRoot}\n`, stderr: "", code: 0 };
398+}
399+if (argv[0] === "pnpm") {
400+return { stdout: `${otherPnpmRoot}\n`, stderr: "", code: 0 };
401+}
402+throw new Error(`unexpected command: ${argv.join(" ")}`);
403+};
393404394405await expect(
395406resolveGlobalInstallTarget({
396-manager: "npm",
407+manager: "pnpm",
397408 runCommand,
398409timeoutMs: 1000,
399410 pkgRoot,
@@ -406,6 +417,21 @@ describe("update global helpers", () => {
406417packageRoot: pkgRoot,
407418directNodeModulesRoot: true,
408419});
420+await expect(
421+resolveGlobalInstallTarget({
422+manager: { manager: "npm", command: customNpm },
423+ runCommand,
424+timeoutMs: 1000,
425+ pkgRoot,
426+honorPackageRoot: true,
427+}),
428+).resolves.toEqual({
429+manager: "npm",
430+command: customNpm,
431+globalRoot: managedNpmRoot,
432+packageRoot: pkgRoot,
433+directNodeModulesRoot: true,
434+});
409435410436expect(
411437resolveNpmGlobalPrefixLayoutFromGlobalRoot(managedNpmRoot, {
@@ -419,6 +445,34 @@ describe("update global helpers", () => {
419445});
420446});
421447448+it("preserves bun ownership for direct node_modules package roots", async () => {
449+await withTempDir({ prefix: "openclaw-update-managed-bun-root-" }, async (base) => {
450+envSnapshot = captureEnv(["BUN_INSTALL"]);
451+process.env.BUN_INSTALL = path.join(base, ".bun");
452+const bunRoot = path.join(process.env.BUN_INSTALL, "install", "global", "node_modules");
453+const pkgRoot = path.join(bunRoot, "openclaw");
454+const pathNpmRoot = path.join(base, "shell", "lib", "node_modules");
455+await fs.mkdir(pkgRoot, { recursive: true });
456+457+const runCommand = createNpmRootRunner({ defaultNpmRoot: pathNpmRoot });
458+459+await expect(
460+resolveGlobalInstallTarget({
461+manager: "bun",
462+ runCommand,
463+timeoutMs: 1000,
464+ pkgRoot,
465+honorPackageRoot: true,
466+}),
467+).resolves.toEqual({
468+manager: "bun",
469+command: "bun",
470+globalRoot: bunRoot,
471+packageRoot: pkgRoot,
472+});
473+});
474+});
475+422476it("prefers npm.cmd for win32-style global npm roots", async () => {
423477await withMockedWindowsPlatform(async () => {
424478await withTempDir({ prefix: "openclaw-update-win32-npm-prefix-" }, async (base) => {
@@ -487,14 +541,15 @@ describe("update global helpers", () => {
487541);
488542await expect(
489543resolveGlobalInstallTarget({
490-manager: "pnpm",
544+manager: { manager: "pnpm", command: "/custom/bin/pnpm" },
491545 runCommand,
492546timeoutMs: 1000,
493547 pkgRoot,
548+honorPackageRoot: true,
494549}),
495550).resolves.toEqual({
496551manager: "pnpm",
497-command: "pnpm",
552+command: "/custom/bin/pnpm",
498553globalRoot: customGlobalRoot,
499554packageRoot: pkgRoot,
500555});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。