diff --git a/bin/lib/onboard.js b/bin/lib/onboard.js index 23f19b01a89..e70a386b0a2 100644 --- a/bin/lib/onboard.js +++ b/bin/lib/onboard.js @@ -647,11 +647,13 @@ async function setupInference(sandboxName, model, provider) { if (provider === "nvidia-nim") { // Create nvidia-nim provider + // Use bare key form (--credential NVIDIA_API_KEY) so the actual key value + // is passed via the child process environment, not visible in `ps aux`. run( `openshell provider create --name nvidia-nim --type openai ` + - `--credential "NVIDIA_API_KEY=${process.env.NVIDIA_API_KEY}" ` + + `--credential NVIDIA_API_KEY ` + `--config "OPENAI_BASE_URL=https://integrate.api.nvidia.com/v1" 2>&1 || true`, - { ignoreError: true } + { ignoreError: true, env: { NVIDIA_API_KEY: process.env.NVIDIA_API_KEY } } ); run( `openshell inference set --no-verify --provider nvidia-nim --model ${model} 2>/dev/null || true`, @@ -666,11 +668,11 @@ async function setupInference(sandboxName, model, provider) { const baseUrl = getLocalProviderBaseUrl(provider); run( `openshell provider create --name vllm-local --type openai ` + - `--credential "OPENAI_API_KEY=dummy" ` + + `--credential OPENAI_API_KEY ` + `--config "OPENAI_BASE_URL=${baseUrl}" 2>&1 || ` + - `openshell provider update vllm-local --credential "OPENAI_API_KEY=dummy" ` + + `openshell provider update vllm-local --credential OPENAI_API_KEY ` + `--config "OPENAI_BASE_URL=${baseUrl}" 2>&1 || true`, - { ignoreError: true } + { ignoreError: true, env: { OPENAI_API_KEY: "dummy" } } ); run( `openshell inference set --no-verify --provider vllm-local --model ${model} 2>/dev/null || true`, @@ -686,11 +688,11 @@ async function setupInference(sandboxName, model, provider) { const baseUrl = getLocalProviderBaseUrl(provider); run( `openshell provider create --name ollama-local --type openai ` + - `--credential "OPENAI_API_KEY=ollama" ` + + `--credential OPENAI_API_KEY ` + `--config "OPENAI_BASE_URL=${baseUrl}" 2>&1 || ` + - `openshell provider update ollama-local --credential "OPENAI_API_KEY=ollama" ` + + `openshell provider update ollama-local --credential OPENAI_API_KEY ` + `--config "OPENAI_BASE_URL=${baseUrl}" 2>&1 || true`, - { ignoreError: true } + { ignoreError: true, env: { OPENAI_API_KEY: "ollama" } } ); run( `openshell inference set --no-verify --provider ollama-local --model ${model} 2>/dev/null || true`, diff --git a/nemoclaw-blueprint/orchestrator/runner.py b/nemoclaw-blueprint/orchestrator/runner.py index 432c228c3be..4d5a5e3ac44 100644 --- a/nemoclaw-blueprint/orchestrator/runner.py +++ b/nemoclaw-blueprint/orchestrator/runner.py @@ -57,13 +57,18 @@ def run_cmd( *, check: bool = True, capture: bool = False, + extra_env: dict[str, str] | None = None, ) -> subprocess.CompletedProcess[str]: """Run a command as an argv list (never shell=True).""" + env = None + if extra_env: + env = {**os.environ, **extra_env} return subprocess.run( args, check=check, capture_output=capture, text=True, + env=env, ) @@ -209,12 +214,16 @@ def action_apply( "--type", provider_type, ] - if credential: - provider_args.extend(["--credential", f"OPENAI_API_KEY={credential}"]) + # Use bare key form (--credential OPENAI_API_KEY) so the actual credential + # value is passed via the child process environment, not visible in `ps aux`. + provider_env: dict[str, str] = {} + if credential and credential_env: + provider_args.extend(["--credential", credential_env]) + provider_env[credential_env] = credential if endpoint: provider_args.extend(["--config", f"OPENAI_BASE_URL={endpoint}"]) - run_cmd(provider_args, check=False, capture=True) + run_cmd(provider_args, check=False, capture=True, extra_env=provider_env) # Step 3: Set inference route progress(70, "Setting inference route") diff --git a/nemoclaw/src/commands/onboard.ts b/nemoclaw/src/commands/onboard.ts index 72fb9fcdd4c..6843adabc31 100644 --- a/nemoclaw/src/commands/onboard.ts +++ b/nemoclaw/src/commands/onboard.ts @@ -216,10 +216,11 @@ async function promptEndpoint( return (await promptSelect("Select your inference endpoint:", options)) as EndpointType; } -function execOpenShell(args: string[]): string { +function execOpenShell(args: string[], options?: { env?: Record }): string { return execFileSync("openshell", args, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], + env: { ...process.env, ...options?.env }, }); } @@ -450,10 +451,10 @@ export async function cliOnboard(opts: OnboardOptions): Promise { "--type", "openai", "--credential", - `${credentialEnv}=${apiKey}`, + credentialEnv, "--config", `OPENAI_BASE_URL=${endpointUrl}`, - ]); + ], { env: { [credentialEnv]: apiKey } }); logger.info(`Created provider: ${providerName}`); } catch (err) { const stderr = @@ -465,10 +466,10 @@ export async function cliOnboard(opts: OnboardOptions): Promise { "update", providerName, "--credential", - `${credentialEnv}=${apiKey}`, + credentialEnv, "--config", `OPENAI_BASE_URL=${endpointUrl}`, - ]); + ], { env: { [credentialEnv]: apiKey } }); logger.info(`Updated provider: ${providerName}`); } catch (updateErr) { const updateStderr =