mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:20:43 +00:00
fix(daemon): add Nix Home Manager PATH support
Add Nix Home Manager profile bin directories to generated gateway service PATHs on macOS and Linux. Includes ~/.nix-profile/bin fallback when NIX_PROFILES is absent, honors NIX_PROFILES right-to-left precedence when present, and covers the service PATH resolver with focused unit tests. Closes #44402.
This commit is contained in:
@@ -172,6 +172,102 @@ describe("getMinimalServicePathParts - Linux user directories", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("getMinimalServicePathParts - Nix Home Manager", () => {
|
||||
it("falls back to default Nix profile when NIX_PROFILES is absent on Linux", () => {
|
||||
const result = getMinimalServicePathParts({
|
||||
platform: "linux",
|
||||
home: "/home/testuser",
|
||||
});
|
||||
|
||||
expect(result).toContain("/home/testuser/.nix-profile/bin");
|
||||
});
|
||||
|
||||
it("falls back to default Nix profile when NIX_PROFILES is absent on macOS", () => {
|
||||
const result = getMinimalServicePathParts({
|
||||
platform: "darwin",
|
||||
home: "/Users/testuser",
|
||||
});
|
||||
|
||||
expect(result).toContain("/Users/testuser/.nix-profile/bin");
|
||||
});
|
||||
|
||||
it("places rightmost NIX_PROFILES entry before leftmost on Linux", () => {
|
||||
const result = getMinimalServicePathPartsFromEnv({
|
||||
platform: "linux",
|
||||
env: {
|
||||
HOME: "/home/testuser",
|
||||
NIX_PROFILES: "/nix/var/nix/profiles/default /home/testuser/.nix-profile",
|
||||
},
|
||||
});
|
||||
|
||||
const userIdx = result.indexOf("/home/testuser/.nix-profile/bin");
|
||||
const defaultIdx = result.indexOf("/nix/var/nix/profiles/default/bin");
|
||||
expect(userIdx).toBeGreaterThan(-1);
|
||||
expect(defaultIdx).toBeGreaterThan(-1);
|
||||
expect(userIdx).toBeLessThan(defaultIdx);
|
||||
});
|
||||
|
||||
it("places rightmost NIX_PROFILES entry before leftmost on macOS", () => {
|
||||
const result = getMinimalServicePathPartsFromEnv({
|
||||
platform: "darwin",
|
||||
env: {
|
||||
HOME: "/Users/testuser",
|
||||
NIX_PROFILES: "/nix/var/nix/profiles/default /Users/testuser/.nix-profile",
|
||||
},
|
||||
});
|
||||
|
||||
const userIdx = result.indexOf("/Users/testuser/.nix-profile/bin");
|
||||
const defaultIdx = result.indexOf("/nix/var/nix/profiles/default/bin");
|
||||
expect(userIdx).toBeGreaterThan(-1);
|
||||
expect(defaultIdx).toBeGreaterThan(-1);
|
||||
expect(userIdx).toBeLessThan(defaultIdx);
|
||||
});
|
||||
|
||||
it("includes single Nix profile from NIX_PROFILES on Linux", () => {
|
||||
const result = getMinimalServicePathPartsFromEnv({
|
||||
platform: "linux",
|
||||
env: {
|
||||
HOME: "/home/testuser",
|
||||
NIX_PROFILES: "/nix/var/nix/profiles/per-user/testuser/profile",
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toContain("/nix/var/nix/profiles/per-user/testuser/profile/bin");
|
||||
});
|
||||
|
||||
it("includes single Nix profile from NIX_PROFILES on macOS", () => {
|
||||
const result = getMinimalServicePathPartsFromEnv({
|
||||
platform: "darwin",
|
||||
env: {
|
||||
HOME: "/Users/testuser",
|
||||
NIX_PROFILES: "/nix/var/nix/profiles/per-user/testuser/profile",
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toContain("/nix/var/nix/profiles/per-user/testuser/profile/bin");
|
||||
});
|
||||
|
||||
it("preserves Nix precedence across three profiles", () => {
|
||||
const result = getMinimalServicePathPartsFromEnv({
|
||||
platform: "linux",
|
||||
env: {
|
||||
HOME: "/home/testuser",
|
||||
NIX_PROFILES:
|
||||
"/nix/var/nix/profiles/default /nix/var/nix/profiles/per-user/testuser/custom /home/testuser/.nix-profile",
|
||||
},
|
||||
});
|
||||
|
||||
const userIdx = result.indexOf("/home/testuser/.nix-profile/bin");
|
||||
const customIdx = result.indexOf("/nix/var/nix/profiles/per-user/testuser/custom/bin");
|
||||
const defaultIdx = result.indexOf("/nix/var/nix/profiles/default/bin");
|
||||
expect(userIdx).toBeGreaterThan(-1);
|
||||
expect(customIdx).toBeGreaterThan(-1);
|
||||
expect(defaultIdx).toBeGreaterThan(-1);
|
||||
expect(userIdx).toBeLessThan(customIdx);
|
||||
expect(customIdx).toBeLessThan(defaultIdx);
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildMinimalServicePath", () => {
|
||||
const splitPath = (value: string, platform: NodeJS.Platform) =>
|
||||
value.split(platform === "win32" ? path.win32.delimiter : path.posix.delimiter);
|
||||
|
||||
@@ -106,6 +106,23 @@ function addCommonEnvConfiguredBinDirs(
|
||||
addNonEmptyDir(dirs, appendSubdir(env?.ASDF_DATA_DIR, "shims"));
|
||||
}
|
||||
|
||||
// Nix shell precedence: rightmost profile in NIX_PROFILES = highest priority.
|
||||
// When NIX_PROFILES is absent, fall back to the default single-user profile.
|
||||
function addNixProfileBinDirs(
|
||||
dirs: string[],
|
||||
home: string,
|
||||
env: Record<string, string | undefined> | undefined,
|
||||
): void {
|
||||
const nixProfiles = env?.NIX_PROFILES?.trim();
|
||||
if (nixProfiles) {
|
||||
for (const profile of nixProfiles.split(/\s+/).toReversed()) {
|
||||
addNonEmptyDir(dirs, appendSubdir(profile, "bin"));
|
||||
}
|
||||
} else {
|
||||
dirs.push(`${home}/.nix-profile/bin`);
|
||||
}
|
||||
}
|
||||
|
||||
function resolveSystemPathDirs(platform: NodeJS.Platform): string[] {
|
||||
if (platform === "darwin") {
|
||||
return ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"];
|
||||
@@ -148,6 +165,9 @@ export function resolveDarwinUserBinDirs(
|
||||
// Common user bin directories
|
||||
addCommonUserBinDirs(dirs, home);
|
||||
|
||||
// Nix Home Manager (cross-platform)
|
||||
addNixProfileBinDirs(dirs, home, env);
|
||||
|
||||
// Node version managers - macOS specific paths
|
||||
// nvm: no stable default path, depends on user's shell configuration
|
||||
// fnm: macOS default is ~/Library/Application Support/fnm, not ~/.fnm
|
||||
@@ -182,6 +202,9 @@ export function resolveLinuxUserBinDirs(
|
||||
// Common user bin directories
|
||||
addCommonUserBinDirs(dirs, home);
|
||||
|
||||
// Nix Home Manager (cross-platform)
|
||||
addNixProfileBinDirs(dirs, home, env);
|
||||
|
||||
// Node version managers
|
||||
dirs.push(`${home}/.nvm/current/bin`); // nvm with current symlink
|
||||
dirs.push(`${home}/.fnm/current/bin`); // fnm
|
||||
|
||||
Reference in New Issue
Block a user