← Files RivetARCHIVED FILE

node_modules/rivet-design/dist/utils/loginShellPath.js

4.54 KB · Nov 7, 2026 · 13:16 UTC

↓ Download file

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resetLoginShellPathForTests = exports.ensureLoginShellPath = exports.mergePathValues = exports.loginShellPath = exports.isBinaryOnPathValue = void 0;
const child_process_1 = require("child_process");
const subprocessEnvironment_1 = require("./subprocessEnvironment");
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const logger_1 = require("./logger");
const log = (0, logger_1.createLogger)('LoginShellPath');
const SENTINEL = '__RIVET_PATH__';
const rcFileForShell = (shell) => {
    const name = path_1.default.basename(shell);
    if (name === 'zsh')
        return '~/.zshrc';
    if (name === 'bash')
        return '~/.bashrc';
    return null;
};
const defaultExec = (shell, args) => (0, child_process_1.execFileSync)(shell, args, {
    timeout: 4_000,
    env: (0, subprocessEnvironment_1.subprocessEnvironment)('verifier'),
    stdio: ['ignore', 'pipe', 'ignore'],
    encoding: 'utf8',
});
const PRINT_PATH = `printf "%s%s%s" "${SENTINEL}" "$PATH" "${SENTINEL}"`;
const DEFAULT_GOAL_BINARIES = ['claude', 'node'];
const isBinaryOnPathValue = (binary, pathValue) => pathValue.split(':').some((dir) => {
    if (!dir)
        return false;
    try {
        fs_1.default.accessSync(path_1.default.join(dir, binary), fs_1.default.constants.X_OK);
        return true;
    }
    catch {
        return false;
    }
});
exports.isBinaryOnPathValue = isBinaryOnPathValue;
const loginShellPath = (options) => {
    if (process.platform === 'win32')
        return null;
    const shell = options?.shell ?? process.env.SHELL ?? '/bin/zsh';
    const exec = options?.exec ?? defaultExec;
    const basePath = options?.basePath ?? process.env.PATH ?? '';
    const goalBinaries = options?.goalBinaries ?? DEFAULT_GOAL_BINARIES;
    const rcFile = rcFileForShell(shell);
    const probes = [
        ['-lc', PRINT_PATH],
        ...(rcFile
            ? [['-lc', `. ${rcFile} >/dev/null 2>&1 || true; ${PRINT_PATH}`]]
            : []),
        ['-ilc', PRINT_PATH],
    ];
    let union = '';
    for (const args of probes) {
        let value;
        try {
            const output = exec(shell, args);
            value = output
                .match(new RegExp(`${SENTINEL}([\\s\\S]*?)${SENTINEL}`))?.[1]
                ?.trim();
        }
        catch (error) {
            log.warn(`login-shell PATH probe (${args[0]}) failed for ${shell}`, error instanceof Error ? error.message : error);
            continue;
        }
        if (!value)
            continue;
        union = union ? (0, exports.mergePathValues)(union, value) : value;
        if (areBinariesOnPathValue(goalBinaries, (0, exports.mergePathValues)(basePath, union))) {
            break;
        }
    }
    return union || null;
};
exports.loginShellPath = loginShellPath;
const areBinariesOnPathValue = (binaries, pathValue) => binaries.every((binary) => (0, exports.isBinaryOnPathValue)(binary, pathValue));
const mergePathValues = (base, extra) => {
    const baseDirs = base.split(':').filter(Boolean);
    const seen = new Set(baseDirs);
    const additions = extra.split(':').filter((dir) => dir && !seen.has(dir));
    return [...baseDirs, ...additions].join(':');
};
exports.mergePathValues = mergePathValues;
const APPLIED_ENV_FLAG = 'RIVET_LOGIN_SHELL_PATH_APPLIED';
let enriched = false;
const ensureLoginShellPath = (options) => {
    if (enriched)
        return;
    enriched = true;
    if (process.env[APPLIED_ENV_FLAG] === '1')
        return;
    const current = process.env.PATH ?? '';
    if (areBinariesOnPathValue(options?.goalBinaries ?? DEFAULT_GOAL_BINARIES, current)) {
        process.env[APPLIED_ENV_FLAG] = '1';
        return;
    }
    const shellPath = (0, exports.loginShellPath)({ ...options, basePath: current });
    if (!shellPath)
        return;
    process.env[APPLIED_ENV_FLAG] = '1';
    const merged = (0, exports.mergePathValues)(current, shellPath);
    if (merged !== current) {
        log.info(`merged ${merged.split(':').length - current.split(':').filter(Boolean).length} login-shell PATH entries into the server environment`);
        process.env.PATH = merged;
    }
};
exports.ensureLoginShellPath = ensureLoginShellPath;
const resetLoginShellPathForTests = () => {
    enriched = false;
    delete process.env[APPLIED_ENV_FLAG];
};
exports.resetLoginShellPathForTests = resetLoginShellPathForTests;
//# sourceMappingURL=loginShellPath.js.map

SHA-256: 3089cbb1896ab33f3f5308bc3b6d6eab5d21d10a47f0dff27497f3ee8baaa2a2