diff --git a/.github/workflows/e2e-vitest-scenarios.yaml b/.github/workflows/e2e-vitest-scenarios.yaml index 04415d83873..2def39a7962 100644 --- a/.github/workflows/e2e-vitest-scenarios.yaml +++ b/.github/workflows/e2e-vitest-scenarios.yaml @@ -421,6 +421,7 @@ jobs: E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/skill-agent NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: @@ -525,6 +526,7 @@ jobs: E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/openclaw-skill-cli NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_SANDBOX_NAME: "e2e-openclaw-skill-cli" OPENSHELL_GATEWAY: "nemoclaw" steps: @@ -572,7 +574,7 @@ jobs: - name: Run OpenClaw skill CLI live test env: - NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -744,6 +746,7 @@ jobs: E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/cloud-inference NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_SANDBOX_NAME: "e2e-cloud-inference" OPENSHELL_GATEWAY: "nemoclaw" steps: @@ -769,7 +772,7 @@ jobs: # request through sandbox inference.local, and reuses the skill # filesystem validators from the retained bash helpers. env: - NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -855,6 +858,7 @@ jobs: E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/agent-turn-latency NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" OPENSHELL_GATEWAY: "nemoclaw" @@ -959,6 +963,7 @@ jobs: E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/hermes-inference-switch NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_AGENT: "hermes" @@ -1114,6 +1119,7 @@ jobs: E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/cron-preflight-inference-local NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_SANDBOX_NAME: "e2e-cron-preflight" @@ -1178,6 +1184,7 @@ jobs: E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/issue-4434-tui-unreachable-inference NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_ISSUE_4434_LIVE: "1" NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" @@ -1493,7 +1500,7 @@ jobs: - name: Install OpenShell CLI run: | set -euo pipefail - env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u GITHUB_TOKEN \ + env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN \ bash scripts/install-openshell.sh - name: Run sessions/agents CLI live test @@ -1502,7 +1509,7 @@ jobs: # OpenClaw gateway dispatch, pending pairing/scope approval, and JSON # envelope handling for sessions/agents commands. env: - NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} run: | set -euo pipefail export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$PATH" @@ -1671,6 +1678,7 @@ jobs: E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/hermes-e2e NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_AGENT: hermes NEMOCLAW_NON_INTERACTIVE: "1" @@ -1848,7 +1856,7 @@ jobs: NEMOCLAW_NON_INTERACTIVE: "1" run: | set -euo pipefail - env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh + env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh - name: Run network-policy live test # Migrated from test/e2e/test-network-policy.sh. Free-standing anchor @@ -1883,6 +1891,7 @@ jobs: E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/common-egress-agent NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_RECREATE_SANDBOX: "1" @@ -1911,14 +1920,14 @@ jobs: NEMOCLAW_NON_INTERACTIVE: "1" run: | set -euo pipefail - env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh + env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh - name: Run common-egress agent live test # Migrated from test/e2e/test-common-egress-agent-e2e.sh. Preserves # OpenClaw balanced/open and Hermes open common-egress agent-turn # coverage against real sandbox policy and live hosted inference. env: - NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} run: | set -euo pipefail export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$PATH" @@ -1958,6 +1967,7 @@ jobs: FREE_STANDING_SCENARIO_ID: "shields-config" E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/shields-config NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_SANDBOX_NAME: e2e-shields @@ -2087,7 +2097,7 @@ jobs: NEMOCLAW_NON_INTERACTIVE: "1" run: | set -euo pipefail - env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh + env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh - name: Run OpenClaw rebuild live test env: @@ -2347,7 +2357,7 @@ jobs: NEMOCLAW_NON_INTERACTIVE: "1" run: | set -euo pipefail - env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh + env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh - name: Run sandbox rebuild live test env: @@ -2530,11 +2540,11 @@ jobs: NEMOCLAW_NON_INTERACTIVE: "1" run: | set -euo pipefail - env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh + env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh - name: Run state backup restore live test env: - NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} run: | set -euo pipefail export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$PATH" @@ -2629,7 +2639,7 @@ jobs: - name: Install OpenShell CLI run: | set -euo pipefail - env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_INFERENCE_API_KEY -u NVIDIA_API_KEY -u GITHUB_TOKEN \ + env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN \ bash scripts/install-openshell.sh - name: Run upgrade stale sandbox live Vitest test @@ -3636,7 +3646,7 @@ jobs: # the legacy fake-token defaults, optional _REAL secret overrides, # provider placeholder redaction checks, and WhatsApp QR-only parity. env: - NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} TELEGRAM_BOT_TOKEN_REAL: ${{ secrets.TELEGRAM_BOT_TOKEN_REAL }} DISCORD_BOT_TOKEN_REAL: ${{ secrets.DISCORD_BOT_TOKEN_REAL }} SLACK_BOT_TOKEN_REAL: ${{ secrets.SLACK_BOT_TOKEN_REAL }} @@ -3672,6 +3682,7 @@ jobs: FREE_STANDING_VITEST_JOB: "1" E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/launchable-smoke NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_SANDBOX_NAME: "e2e-launchable" NEMOCLAW_RECREATE_SANDBOX: "1" NEMOCLAW_MODEL: minimaxai/minimax-m2.7 @@ -3890,10 +3901,10 @@ jobs: - name: Run snapshot commands live test # Migrated from test/e2e/test-snapshot-commands.sh. Preserves the - # original ubuntu-latest + Docker/OpenShell + NVIDIA_API_KEY runner + # original ubuntu-latest + Docker/OpenShell + NVIDIA_INFERENCE_API_KEY runner # contract by driving install.sh and the real snapshot CLI lifecycle. env: - NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -3928,6 +3939,7 @@ jobs: DOCKER_CONFIG: ${{ github.workspace }}/.docker-config-sandbox-survival E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/sandbox-survival NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_SANDBOX_NAME: "e2e-survival" @@ -4041,11 +4053,11 @@ jobs: - name: Run diagnostics live test # Migrated from test/e2e/test-diagnostics.sh. This preserves the - # ubuntu-latest + Docker/OpenShell + NVIDIA_API_KEY lane by running + # ubuntu-latest + Docker/OpenShell + NVIDIA_INFERENCE_API_KEY lane by running # debug archives, install.sh/onboard, sandbox exec/status, and # gateway-backed credentials list/reset from Vitest. env: - NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live test/e2e-scenario/live/diagnostics.test.ts --silent=false --reporter=default @@ -4291,6 +4303,7 @@ jobs: E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/openclaw-inference-switch NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js NEMOCLAW_RUN_E2E_SCENARIOS: "1" + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_SANDBOX_NAME: "e2e-openclaw-inference-switch" @@ -4344,7 +4357,7 @@ jobs: # Vitest owns the route, config, registry, inference.local, and agent # assertions. env: - NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -4693,7 +4706,7 @@ jobs: NEMOCLAW_NON_INTERACTIVE: "1" run: | set -euo pipefail - env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh + env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh - name: Run channels add/remove live test # Migrated from test/e2e/test-channels-add-remove.sh. Preserves the @@ -4701,7 +4714,7 @@ jobs: # channels add, rebuild, gateway credential reuse, policy-list, and # channels remove cleanup. env: - NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} TELEGRAM_BOT_TOKEN: "test-fake-telegram-token-add-remove-e2e" TELEGRAM_ALLOWED_IDS: "123456789" TELEGRAM_REQUIRE_MENTION: "0" @@ -4910,7 +4923,7 @@ jobs: NEMOCLAW_NON_INTERACTIVE: "1" run: | set -euo pipefail - env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh + env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_API_KEY -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh - name: Run channels stop/start live test # Migrated from test/e2e/test-channels-stop-start.sh. Preserves the @@ -5423,7 +5436,7 @@ jobs: # install.sh/public curl|bash boundary, install-log retention, PATH # refresh, and post-install nemoclaw/openshell/--help checks. env: - NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ diff --git a/test/e2e-scenario/fixtures/hosted-inference.ts b/test/e2e-scenario/fixtures/hosted-inference.ts index 4efcbbddbd5..11f3c5987f7 100644 --- a/test/e2e-scenario/fixtures/hosted-inference.ts +++ b/test/e2e-scenario/fixtures/hosted-inference.ts @@ -49,10 +49,13 @@ export function requireHostedInferenceConfig( endpointUrl, model, env: { + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1", NEMOCLAW_PROVIDER: HOSTED_INFERENCE_PROVIDER, NEMOCLAW_ENDPOINT_URL: endpointUrl, NEMOCLAW_MODEL: model, NEMOCLAW_COMPAT_MODEL: model, + NEMOCLAW_PREFERRED_API: env.NEMOCLAW_PREFERRED_API || "openai-completions", + [HOSTED_INFERENCE_SECRET]: apiKey, [HOSTED_INFERENCE_CREDENTIAL_ENV]: apiKey, }, contractLabel: "NVIDIA_INFERENCE_API_KEY is staged as the compatible endpoint credential", diff --git a/test/e2e-scenario/live/agent-turn-latency-helpers.ts b/test/e2e-scenario/live/agent-turn-latency-helpers.ts index 327ebdfdc44..b8c54a881d1 100644 --- a/test/e2e-scenario/live/agent-turn-latency-helpers.ts +++ b/test/e2e-scenario/live/agent-turn-latency-helpers.ts @@ -58,7 +58,7 @@ export function env( OPENSHELL_GATEWAY: process.env.OPENSHELL_GATEWAY ?? "nemoclaw", }; agent === "hermes" && (out.NEMOCLAW_AGENT = "hermes"); - apiKey && Object.assign(out, { NVIDIA_INFERENCE_API_KEY: apiKey, NVIDIA_API_KEY: apiKey }); + apiKey && Object.assign(out, { NVIDIA_INFERENCE_API_KEY: apiKey }); PROVIDER === "custom" && Object.assign(out, { COMPATIBLE_API_KEY: apiKey, diff --git a/test/e2e-scenario/live/brave-search-helpers.ts b/test/e2e-scenario/live/brave-search-helpers.ts index 2b1aad85bdc..a579e538d79 100644 --- a/test/e2e-scenario/live/brave-search-helpers.ts +++ b/test/e2e-scenario/live/brave-search-helpers.ts @@ -185,7 +185,6 @@ export async function onboardBrave( env: commandEnv({ BRAVE_API_KEY: braveKey, NVIDIA_INFERENCE_API_KEY: inferenceKey, - NVIDIA_API_KEY: inferenceKey, }), redactionValues, timeoutMs: 20 * 60_000, diff --git a/test/e2e-scenario/live/channels-add-remove.test.ts b/test/e2e-scenario/live/channels-add-remove.test.ts index f55d1b0e18f..09826d8eb34 100644 --- a/test/e2e-scenario/live/channels-add-remove.test.ts +++ b/test/e2e-scenario/live/channels-add-remove.test.ts @@ -363,7 +363,7 @@ liveTest( `channels-add-remove live test is destructive and only accepts sandbox names with prefix ${TEST_SANDBOX_PREFIX}; got ${SANDBOX_NAME}`, ); } - const apiKey = secrets.required("NVIDIA_API_KEY"); + const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); const secretsToRedact = redactionValues(apiKey); const ready = await environment.assertReady({ @@ -381,7 +381,7 @@ liveTest( contract: [ "onboard creates an OpenClaw sandbox with no Telegram channel", "channels add telegram registers the bridge and persists messaging.plan", - "post-add rebuild reuses the gateway-stored inference credential when NVIDIA_API_KEY is absent", + "post-add rebuild reuses the gateway-stored inference credential when NVIDIA_INFERENCE_API_KEY is absent", "post-add rebuild applies the Telegram policy preset and renders openclaw.json channel state", "channels remove telegram removes provider, policy, registry plan, and rendered channel state after rebuild", ], @@ -489,7 +489,7 @@ liveTest( const remove = await host.nemoclaw([SANDBOX_NAME, "channels", "remove", "telegram"], { artifactName: "phase-5-channels-remove-telegram", - env: channelEnv({ NVIDIA_API_KEY: apiKey }), + env: channelEnv({ NVIDIA_INFERENCE_API_KEY: apiKey }), redactionValues: secretsToRedact, timeoutMs: COMMAND_TIMEOUT_MS, }); @@ -499,7 +499,7 @@ liveTest( const rebuildRemove = await host.nemoclaw([SANDBOX_NAME, "rebuild", "--yes"], { artifactName: "phase-5-rebuild-after-remove", - env: channelEnv({ NVIDIA_API_KEY: apiKey }), + env: channelEnv({ NVIDIA_INFERENCE_API_KEY: apiKey }), redactionValues: secretsToRedact, timeoutMs: REBUILD_TIMEOUT_MS, }); diff --git a/test/e2e-scenario/live/cloud-inference.test.ts b/test/e2e-scenario/live/cloud-inference.test.ts index 9af5ea9ebc0..6f5ee2e59ba 100644 --- a/test/e2e-scenario/live/cloud-inference.test.ts +++ b/test/e2e-scenario/live/cloud-inference.test.ts @@ -19,6 +19,7 @@ import type { HostCliClient } from "../fixtures/clients/host.ts"; import { type SandboxClient, validateSandboxName } from "../fixtures/clients/sandbox.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; +import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; import type { ShellProbeResult } from "../fixtures/shell-probe.ts"; import { buildPreContractExternalProviderSkipEvidence, @@ -50,7 +51,10 @@ const SANDBOX_SKILL_VALIDATOR = path.join( ); const SANDBOX_NAME = process.env.NEMOCLAW_SANDBOX_NAME ?? "e2e-cloud-inference"; const CLOUD_MODEL = - process.env.NEMOCLAW_CLOUD_EXPERIMENTAL_MODEL ?? "nvidia/nemotron-3-super-120b-a12b"; + process.env.NEMOCLAW_MODEL ?? + process.env.NEMOCLAW_COMPAT_MODEL ?? + process.env.NEMOCLAW_CLOUD_EXPERIMENTAL_MODEL ?? + "nvidia/nemotron-3-super-120b-a12b"; const INSTALL_TIMEOUT_MS = 25 * 60_000; const CHAT_TIMEOUT_MS = 120_000; const TEST_TIMEOUT_MS = 40 * 60_000; @@ -227,8 +231,8 @@ async function expectLiveChatPong( test.skipIf(!shouldRunLiveE2EScenarios())( "cloud inference: inference.local chat and OpenClaw skill filesystem validate", async ({ artifacts, cleanup, host, sandbox, secrets, skip }) => { - const apiKey = secrets.required("NVIDIA_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); + const hosted = requireHostedInferenceConfig(secrets); + const apiKey = hosted.apiKey; expect(fs.existsSync(CLI_ENTRYPOINT), `missing CLI entrypoint: ${CLI_ENTRYPOINT}`).toBe(true); expect( @@ -247,7 +251,7 @@ test.skipIf(!shouldRunLiveE2EScenarios())( legacySource: "test/e2e/test-cloud-inference-e2e.sh", contracts: [ "Docker is running before install/onboard", - "NVIDIA_API_KEY is present and nvapi-prefixed", + "NVIDIA_INFERENCE_API_KEY is staged as the compatible endpoint credential", "install.sh --non-interactive creates or recreates the named OpenClaw sandbox", "nemoclaw and openshell are available on PATH after install", "curl inside the sandbox reaches https://inference.local/v1/chat/completions and returns PONG", @@ -289,9 +293,8 @@ test.skipIf(!shouldRunLiveE2EScenarios())( artifactName: "phase-1-install-and-onboard-cloud-inference", cwd: REPO_ROOT, env: testEnv(home, { - NVIDIA_API_KEY: apiKey, + ...hosted.env, NEMOCLAW_AGENT: "openclaw", - NEMOCLAW_PROVIDER: "cloud", NEMOCLAW_RECREATE_SANDBOX: "1", NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, }), diff --git a/test/e2e-scenario/live/common-egress-agent.test.ts b/test/e2e-scenario/live/common-egress-agent.test.ts index 6c43098a391..5015ad4db2a 100644 --- a/test/e2e-scenario/live/common-egress-agent.test.ts +++ b/test/e2e-scenario/live/common-egress-agent.test.ts @@ -19,6 +19,10 @@ import { } from "../fixtures/clients/sandbox.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; +import { + type HostedInferenceConfig, + requireHostedInferenceConfig, +} from "../fixtures/hosted-inference.ts"; import type { SecretStore } from "../fixtures/secrets.ts"; import type { ShellProbeResult } from "../fixtures/shell-probe.ts"; import { isTransientProviderValidationFailure } from "./network-policy-transient-provider.ts"; @@ -233,7 +237,7 @@ async function assertPrerequisites( host: HostCliClient, secrets: SecretStore, skip: SkipFn, -): Promise { +): Promise { expect( fs.existsSync(CLI_DIST_ENTRYPOINT), "run `npm run build:cli` before live repo CLI scenarios", @@ -258,14 +262,13 @@ async function assertPrerequisites( }); expect(openshell.exitCode, text(openshell)).toBe(0); - const apiKey = secrets.required("NVIDIA_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); + const hosted = requireHostedInferenceConfig(secrets); expect(process.env.NEMOCLAW_NON_INTERACTIVE, "NEMOCLAW_NON_INTERACTIVE=1 is required").toBe("1"); expect( process.env.NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE, "NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 is required", ).toBe("1"); - return apiKey; + return hosted; } async function bestEffortDestroySandbox( @@ -336,8 +339,8 @@ async function runOnboard( host: HostCliClient, args: { agent: "openclaw" | "hermes"; - apiKey: string; artifacts: ArtifactSink; + hosted: HostedInferenceConfig; sandboxName: string; skip: SkipFn; tier: "balanced" | "open"; @@ -356,13 +359,13 @@ async function runOnboard( artifactName: `onboard-common-egress-${args.sandboxName}`, cwd: REPO_ROOT, env: commandEnv({ - NVIDIA_API_KEY: args.apiKey, + ...args.hosted.env, NEMOCLAW_AGENT: args.agent, NEMOCLAW_POLICY_MODE: "suggested", NEMOCLAW_POLICY_TIER: args.tier, NEMOCLAW_SANDBOX_NAME: args.sandboxName, }), - redactionValues: [args.apiKey], + redactionValues: [args.hosted.apiKey], timeoutMs: ONBOARD_TIMEOUT_MS, }, ); @@ -666,7 +669,8 @@ test("common-egress agent classifies pre-contract provider validation skips", () expect( classifyPreContractProviderValidationSkip({ stdout: "", - stderr: "NVIDIA Endpoints endpoint validation failed.\ninvalid NVIDIA_API_KEY credential", + stderr: + "NVIDIA Endpoints endpoint validation failed.\ninvalid NVIDIA_INFERENCE_API_KEY credential", }), ).toMatchObject({ matches: false }); }); @@ -676,7 +680,8 @@ describe.sequential("common-egress agent live scenarios", () => { "C1 OpenClaw balanced includes weather and agent fetches Open-Meteo", { timeout: TEST_TIMEOUT_MS }, async ({ artifacts, cleanup, host, sandbox, secrets, skip }) => { - const apiKey = await assertPrerequisites(host, secrets, skip); + const hosted = await assertPrerequisites(host, secrets, skip); + const apiKey = hosted.apiKey; await artifacts.writeJson("scenario.json", { id: "common-egress-agent", case: "openclaw-balanced-weather", @@ -691,8 +696,8 @@ describe.sequential("common-egress agent live scenarios", () => { await registerSandboxCleanup(cleanup, artifacts, host, sandbox, OPENCLAW_BALANCED_SANDBOX); await runOnboard(host, { agent: "openclaw", - apiKey, artifacts, + hosted, sandboxName: OPENCLAW_BALANCED_SANDBOX, skip, tier: "balanced", @@ -728,7 +733,8 @@ After web_fetch returns, reply exactly WEATHER_AGENT_OK if the fetched response "C2 OpenClaw open includes public reference and agent fetches Wikidata", { timeout: TEST_TIMEOUT_MS }, async ({ artifacts, cleanup, host, sandbox, secrets, skip }) => { - const apiKey = await assertPrerequisites(host, secrets, skip); + const hosted = await assertPrerequisites(host, secrets, skip); + const apiKey = hosted.apiKey; await artifacts.writeJson("scenario.json", { id: "common-egress-agent", case: "openclaw-open-public-reference", @@ -742,8 +748,8 @@ After web_fetch returns, reply exactly WEATHER_AGENT_OK if the fetched response await registerSandboxCleanup(cleanup, artifacts, host, sandbox, OPENCLAW_OPEN_SANDBOX); await runOnboard(host, { agent: "openclaw", - apiKey, artifacts, + hosted, sandboxName: OPENCLAW_OPEN_SANDBOX, skip, tier: "open", @@ -774,7 +780,8 @@ After web_fetch returns, reply exactly REFERENCE_AGENT_OK if the fetched respons "C3 Hermes open includes public reference plus Nous presets and agent fetches Wikidata", { timeout: TEST_TIMEOUT_MS }, async ({ artifacts, cleanup, host, sandbox, secrets, skip }) => { - const apiKey = await assertPrerequisites(host, secrets, skip); + const hosted = await assertPrerequisites(host, secrets, skip); + const apiKey = hosted.apiKey; await artifacts.writeJson("scenario.json", { id: "common-egress-agent", case: "hermes-open-public-reference", @@ -789,8 +796,8 @@ After web_fetch returns, reply exactly REFERENCE_AGENT_OK if the fetched respons await registerSandboxCleanup(cleanup, artifacts, host, sandbox, HERMES_SANDBOX); await runOnboard(host, { agent: "hermes", - apiKey, artifacts, + hosted, sandboxName: HERMES_SANDBOX, skip, tier: "open", diff --git a/test/e2e-scenario/live/credential-sanitization.test.ts b/test/e2e-scenario/live/credential-sanitization.test.ts index e12e57b2a17..1f311c83a3b 100644 --- a/test/e2e-scenario/live/credential-sanitization.test.ts +++ b/test/e2e-scenario/live/credential-sanitization.test.ts @@ -319,10 +319,6 @@ runCredentialSanitizationTest( assertBlueprintDigestContract(); const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); - const docker = await host.command("docker", ["info"], { artifactName: "prereq-docker-info-credential-sanitization", env: buildAvailabilityProbeEnv(), diff --git a/test/e2e-scenario/live/cron-preflight-inference-local.test.ts b/test/e2e-scenario/live/cron-preflight-inference-local.test.ts index a31658092b3..8d30e3390b5 100644 --- a/test/e2e-scenario/live/cron-preflight-inference-local.test.ts +++ b/test/e2e-scenario/live/cron-preflight-inference-local.test.ts @@ -18,6 +18,7 @@ import { resultText } from "../fixtures/clients/index.ts"; import { type SandboxClient, validateSandboxName } from "../fixtures/clients/sandbox.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; +import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; import type { ShellProbeResult } from "../fixtures/shell-probe.ts"; import { isTransientProviderValidationFailure } from "./network-policy-transient-provider.ts"; @@ -153,22 +154,16 @@ interface CronPreflightProbeJson { }; } -function commandEnv(apiKey?: string): NodeJS.ProcessEnv { - const env: NodeJS.ProcessEnv = { +function commandEnv(hostedEnv: NodeJS.ProcessEnv = {}): NodeJS.ProcessEnv { + return { ...buildAvailabilityProbeEnv(), + ...hostedEnv, NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1", - NEMOCLAW_MODEL: MODEL, NEMOCLAW_NON_INTERACTIVE: "1", - NEMOCLAW_PROVIDER: process.env.NEMOCLAW_PROVIDER ?? "build", NEMOCLAW_RECREATE_SANDBOX: "1", NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, OPENSHELL_GATEWAY: process.env.OPENSHELL_GATEWAY ?? "nemoclaw", }; - if (apiKey) { - env.NVIDIA_INFERENCE_API_KEY = apiKey; - env.NVIDIA_API_KEY = apiKey; - } - return env; } async function bestEffort(run: () => Promise): Promise { @@ -213,7 +208,8 @@ test.skipIf(!shouldRunLiveE2EScenarios())( "cron preflight reaches managed inference.local provider without EAI_AGAIN", { timeout: LIVE_TIMEOUT_MS }, async ({ artifacts, cleanup, host, sandbox, secrets, skip }) => { - const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); + const hosted = requireHostedInferenceConfig(secrets, process.env, { model: MODEL }); + const apiKey = hosted.apiKey; await artifacts.writeJson("scenario.json", { id: "cron-preflight-inference-local", @@ -274,7 +270,7 @@ test.skipIf(!shouldRunLiveE2EScenarios())( ? "phase-1-install-cron-preflight" : `phase-1-install-cron-preflight-attempt-${attempt}`, cwd: REPO_ROOT, - env: commandEnv(apiKey), + env: commandEnv(hosted.env), redactionValues: [apiKey], timeoutMs: 20 * 60_000, }, @@ -291,7 +287,7 @@ test.skipIf(!shouldRunLiveE2EScenarios())( const probe = await host.nemoclaw([SANDBOX_NAME, "exec", "--", "sh", "-c", probeShell()], { artifactName: "phase-2-cron-preflight-probe", - env: commandEnv(apiKey), + env: commandEnv(hosted.env), redactionValues: [apiKey], timeoutMs: 120_000, }); diff --git a/test/e2e-scenario/live/device-auth-health-helpers.ts b/test/e2e-scenario/live/device-auth-health-helpers.ts index bc809a6d810..5ab8f6a50c9 100644 --- a/test/e2e-scenario/live/device-auth-health-helpers.ts +++ b/test/e2e-scenario/live/device-auth-health-helpers.ts @@ -31,7 +31,7 @@ export function commandEnv(apiKey?: string): NodeJS.ProcessEnv { NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, OPENSHELL_GATEWAY: process.env.OPENSHELL_GATEWAY ?? "nemoclaw", }; - apiKey && Object.assign(env, { NVIDIA_INFERENCE_API_KEY: apiKey, NVIDIA_API_KEY: apiKey }); + apiKey && Object.assign(env, { NVIDIA_INFERENCE_API_KEY: apiKey }); return env; } diff --git a/test/e2e-scenario/live/diagnostics.test.ts b/test/e2e-scenario/live/diagnostics.test.ts index cba97623984..c94fb2af9d1 100644 --- a/test/e2e-scenario/live/diagnostics.test.ts +++ b/test/e2e-scenario/live/diagnostics.test.ts @@ -121,7 +121,9 @@ function assertNoSecretInExtractedArchive(extractDir: string, apiKey: string): v if (/nvapi-[A-Za-z0-9_-]{10,}/.test(text)) patternLeaks.push(path.relative(extractDir, file)); } - expect(leakedFiles, "debug archive must not contain the exact NVIDIA_API_KEY").toEqual([]); + expect(leakedFiles, "debug archive must not contain the exact NVIDIA_INFERENCE_API_KEY").toEqual( + [], + ); expect(patternLeaks, "debug archive must not contain nvapi-shaped credentials").toEqual([]); } @@ -136,9 +138,7 @@ runDiagnosticsTest( "run `npm run build:cli` before live repo CLI scenarios", ).toBe(true); - const apiKey = secrets.required("NVIDIA_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); - + const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); await artifacts.writeJson("scenario.json", { id: "diagnostics", runner: "vitest", @@ -195,7 +195,7 @@ runDiagnosticsTest( fs.rmSync(home, { recursive: true, force: true }); }); - const env = testEnv(home, { NVIDIA_API_KEY: apiKey }); + const env = testEnv(home, { NVIDIA_INFERENCE_API_KEY: apiKey }); await bestEffort(() => host.command("node", [CLI_ENTRYPOINT, SANDBOX_NAME, "destroy", "--yes"], { artifactName: "pre-cleanup-nemoclaw-destroy-diagnostics", @@ -351,7 +351,7 @@ runDiagnosticsTest( expect(rawCredentialsList.status, redactForAssertion(credentialsText, apiKey)).toBe(0); expect( credentialsText.includes(apiKey), - "credentials list must not expose the exact NVIDIA_API_KEY", + "credentials list must not expose the exact NVIDIA_INFERENCE_API_KEY", ).toBe(false); expect( /nvapi-[A-Za-z0-9_-]{10,}/.test(credentialsText), @@ -390,7 +390,7 @@ runDiagnosticsTest( expect(postResetText.includes("nvidia-prod")).toBe(false); expect( postResetText.includes(apiKey), - "post-reset credentials list must not expose the exact NVIDIA_API_KEY", + "post-reset credentials list must not expose the exact NVIDIA_INFERENCE_API_KEY", ).toBe(false); expect( /nvapi-[A-Za-z0-9_-]{10,}/.test(postResetText), diff --git a/test/e2e-scenario/live/hermes-discord.test.ts b/test/e2e-scenario/live/hermes-discord.test.ts index d6ad565b889..7c6a28aa55f 100644 --- a/test/e2e-scenario/live/hermes-discord.test.ts +++ b/test/e2e-scenario/live/hermes-discord.test.ts @@ -702,7 +702,7 @@ done`, const rebuildEnv = commandEnv(); delete rebuildEnv.NVIDIA_INFERENCE_API_KEY; - delete rebuildEnv.NVIDIA_API_KEY; + delete rebuildEnv.NVIDIA_INFERENCE_API_KEY; delete rebuildEnv.COMPATIBLE_API_KEY; const rebuild = await host.command("nemoclaw", [SANDBOX_NAME, "rebuild", "--yes"], { artifactName: "phase-8-rebuild-without-inference-env", diff --git a/test/e2e-scenario/live/hermes-e2e.test.ts b/test/e2e-scenario/live/hermes-e2e.test.ts index bd7fed651cd..db45e8549a6 100644 --- a/test/e2e-scenario/live/hermes-e2e.test.ts +++ b/test/e2e-scenario/live/hermes-e2e.test.ts @@ -11,6 +11,7 @@ import { trustedProviderEndpoint } from "../fixtures/clients/provider.ts"; import { trustedSandboxShellScript, validateSandboxName } from "../fixtures/clients/sandbox.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; +import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; import type { ShellProbeResult } from "../fixtures/shell-probe.ts"; // Migrated from test/e2e/test-hermes-e2e.sh. @@ -219,10 +220,8 @@ test.skipIf(!shouldRunLiveE2EScenarios())( "hermes-e2e: install.sh onboards Hermes and proves health plus live inference", { timeout: LIVE_TIMEOUT_MS }, async ({ artifacts, cleanup, host, provider, sandbox, secrets }) => { - const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); + const hosted = requireHostedInferenceConfig(secrets); + const apiKey = hosted.apiKey; await artifacts.writeJson("scenario.json", { id: "hermes-e2e", diff --git a/test/e2e-scenario/live/hermes-inference-switch-helpers.ts b/test/e2e-scenario/live/hermes-inference-switch-helpers.ts index 1c8e7272f78..23fca9fd9c6 100644 --- a/test/e2e-scenario/live/hermes-inference-switch-helpers.ts +++ b/test/e2e-scenario/live/hermes-inference-switch-helpers.ts @@ -22,8 +22,14 @@ export const REPO_ROOT = path.resolve(import.meta.dirname, "../../.."); export const CLI = path.join(REPO_ROOT, "bin", "nemoclaw.js"); export const SANDBOX_NAME = process.env.NEMOCLAW_SANDBOX_NAME ?? "e2e-hermes-inference-switch"; validateSandboxName(SANDBOX_NAME); -export const SWITCH_PROVIDER = process.env.NEMOCLAW_SWITCH_PROVIDER ?? "nvidia-prod"; -export const SWITCH_MODEL = process.env.NEMOCLAW_SWITCH_MODEL ?? "z-ai/glm-5.1"; +const USE_COMPATIBLE_HOSTED = process.env.NEMOCLAW_E2E_USE_HOSTED_INFERENCE === "1"; +const DEFAULT_COMPAT_MODEL = "nvidia/nvidia/nemotron-3-super-v3"; +export const SWITCH_PROVIDER = + process.env.NEMOCLAW_SWITCH_PROVIDER ?? + (USE_COMPATIBLE_HOSTED ? "compatible-endpoint" : "nvidia-prod"); +export const SWITCH_MODEL = + process.env.NEMOCLAW_SWITCH_MODEL ?? + (USE_COMPATIBLE_HOSTED ? DEFAULT_COMPAT_MODEL : "z-ai/glm-5.1"); export const SWITCH_API = process.env.NEMOCLAW_SWITCH_INFERENCE_API ?? "openai-completions"; const SWITCH_MOCK_ANTHROPIC = process.env.NEMOCLAW_SWITCH_MOCK_ANTHROPIC ?? "0"; const SWITCH_MOCK_PORT = Number.parseInt(process.env.NEMOCLAW_SWITCH_MOCK_PORT ?? "0", 10); @@ -44,7 +50,17 @@ export function env(apiKey?: string, extra: NodeJS.ProcessEnv = {}): NodeJS.Proc NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, OPENSHELL_GATEWAY: process.env.OPENSHELL_GATEWAY ?? "nemoclaw", }; - apiKey && Object.assign(out, { NVIDIA_INFERENCE_API_KEY: apiKey, NVIDIA_API_KEY: apiKey }); + apiKey && Object.assign(out, { NVIDIA_INFERENCE_API_KEY: apiKey }); + USE_COMPATIBLE_HOSTED && + apiKey && + Object.assign(out, { + COMPATIBLE_API_KEY: apiKey, + NEMOCLAW_COMPAT_MODEL: SWITCH_MODEL, + NEMOCLAW_ENDPOINT_URL: + process.env.NEMOCLAW_ENDPOINT_URL ?? "https://inference-api.nvidia.com/v1", + NEMOCLAW_PREFERRED_API: process.env.NEMOCLAW_PREFERRED_API ?? "openai-completions", + NEMOCLAW_PROVIDER: "custom", + }); return { ...out, ...extra }; } diff --git a/test/e2e-scenario/live/issue-4434-tui-unreachable-inference.test.ts b/test/e2e-scenario/live/issue-4434-tui-unreachable-inference.test.ts index b9160de08d0..b2359063633 100644 --- a/test/e2e-scenario/live/issue-4434-tui-unreachable-inference.test.ts +++ b/test/e2e-scenario/live/issue-4434-tui-unreachable-inference.test.ts @@ -8,6 +8,7 @@ import { buildAvailabilityProbeEnv } from "../fixtures/availability-env.ts"; import { trustedSandboxShellScript, validateSandboxName } from "../fixtures/clients/sandbox.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; +import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; import { ubuntuRepoDocker } from "../scenarios/matrix.ts"; // Migrated from test/e2e/test-issue-4434-tui-unreachable-inference.sh. @@ -138,10 +139,8 @@ runIssue4434LiveTest( skip("Linux host required for DOCKER-USER iptables repro"); } - const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); + const hosted = requireHostedInferenceConfig(secrets); + const apiKey = hosted.apiKey; await artifacts.writeJson("scenario.json", { id: "issue-4434-tui-unreachable-inference", diff --git a/test/e2e-scenario/live/launchable-smoke.test.ts b/test/e2e-scenario/live/launchable-smoke.test.ts index e81a30d36ca..c091448f8f2 100644 --- a/test/e2e-scenario/live/launchable-smoke.test.ts +++ b/test/e2e-scenario/live/launchable-smoke.test.ts @@ -13,6 +13,7 @@ import type { HostCliClient } from "../fixtures/clients/host.ts"; import { validateSandboxName } from "../fixtures/clients/sandbox.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; +import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; import type { ShellProbeResult } from "../fixtures/shell-probe.ts"; import { isTransientProviderValidationFailure } from "./network-policy-transient-provider.ts"; @@ -235,10 +236,8 @@ runLaunchableSmokeTest( workflowRetirement: "deferred to #5098 Phase 11", }); - const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); + const hosted = requireHostedInferenceConfig(secrets); + const apiKey = hosted.apiKey; expect(fs.existsSync(LAUNCHABLE_SCRIPT), `${LAUNCHABLE_SCRIPT} missing`).toBe(true); @@ -336,7 +335,7 @@ runLaunchableSmokeTest( cwd: cloneDir, env: runEnv({ PATH: `/usr/local/bin:${process.env.PATH ?? ""}`, - NVIDIA_INFERENCE_API_KEY: apiKey, + ...hosted.env, NEMOCLAW_MODEL: MODEL, NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, NEMOCLAW_RECREATE_SANDBOX: "1", diff --git a/test/e2e-scenario/live/messaging-providers-helpers.ts b/test/e2e-scenario/live/messaging-providers-helpers.ts index f315672c6ed..746a6405590 100644 --- a/test/e2e-scenario/live/messaging-providers-helpers.ts +++ b/test/e2e-scenario/live/messaging-providers-helpers.ts @@ -226,7 +226,7 @@ export function messagingEnv(): MessagingEnv { NEMOCLAW_RECREATE_SANDBOX: "1", NEMOCLAW_FRESH: "1", NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, - NVIDIA_API_KEY: process.env.NVIDIA_API_KEY, + NVIDIA_INFERENCE_API_KEY: process.env.NVIDIA_INFERENCE_API_KEY, TELEGRAM_BOT_TOKEN: telegram, DISCORD_BOT_TOKEN: discord, SLACK_BOT_TOKEN: slackBot, diff --git a/test/e2e-scenario/live/messaging-providers.test.ts b/test/e2e-scenario/live/messaging-providers.test.ts index d96d591987d..37d7f09a65e 100644 --- a/test/e2e-scenario/live/messaging-providers.test.ts +++ b/test/e2e-scenario/live/messaging-providers.test.ts @@ -64,8 +64,8 @@ runLiveTest( "messaging providers preserve placeholder, policy, runtime, and send contracts", testTimeoutOptions(LIVE_TIMEOUT_MS), async ({ artifacts, cleanup, host, sandbox, skip }) => { - if (!process.env.NVIDIA_API_KEY) { - skip("NVIDIA_API_KEY is required for live messaging-provider E2E"); + if (!process.env.NVIDIA_INFERENCE_API_KEY) { + skip("NVIDIA_INFERENCE_API_KEY is required for live messaging-provider E2E"); return; } if (!fs.existsSync(CLI_ENTRYPOINT)) { diff --git a/test/e2e-scenario/live/network-policy.test.ts b/test/e2e-scenario/live/network-policy.test.ts index d45c9f8be58..fde7dfa5493 100644 --- a/test/e2e-scenario/live/network-policy.test.ts +++ b/test/e2e-scenario/live/network-policy.test.ts @@ -402,10 +402,6 @@ RUN_NETWORK_POLICY_TEST( expect(openshellVersion.exitCode, text(openshellVersion)).toBe(0); const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); - cleanup.add(`destroy network-policy sandbox ${SANDBOX_NAME}`, async () => { await runNemoclaw(host, [SANDBOX_NAME, "destroy", "--yes"], { artifactName: "cleanup-nemoclaw-destroy-network-policy", diff --git a/test/e2e-scenario/live/openclaw-inference-switch.test.ts b/test/e2e-scenario/live/openclaw-inference-switch.test.ts index d834c357ee1..170967e9457 100644 --- a/test/e2e-scenario/live/openclaw-inference-switch.test.ts +++ b/test/e2e-scenario/live/openclaw-inference-switch.test.ts @@ -27,14 +27,21 @@ import { } from "../fixtures/clients/sandbox.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; +import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; import type { ShellProbeResult } from "../fixtures/shell-probe.ts"; const REPO_ROOT = path.resolve(import.meta.dirname, "../../.."); const CLI_ENTRYPOINT = path.join(REPO_ROOT, "bin", "nemoclaw.js"); const SANDBOX_NAME = process.env.NEMOCLAW_SANDBOX_NAME ?? uniqueSandboxName("e2e-openclaw-inference-switch"); -const SWITCH_PROVIDER = process.env.NEMOCLAW_SWITCH_PROVIDER ?? "nvidia-prod"; -const SWITCH_MODEL = process.env.NEMOCLAW_SWITCH_MODEL ?? "z-ai/glm-5.1"; +const USE_COMPATIBLE_HOSTED = process.env.NEMOCLAW_E2E_USE_HOSTED_INFERENCE === "1"; +const DEFAULT_COMPAT_MODEL = "nvidia/nvidia/nemotron-3-super-v3"; +const SWITCH_PROVIDER = + process.env.NEMOCLAW_SWITCH_PROVIDER ?? + (USE_COMPATIBLE_HOSTED ? "compatible-endpoint" : "nvidia-prod"); +const SWITCH_MODEL = + process.env.NEMOCLAW_SWITCH_MODEL ?? + (USE_COMPATIBLE_HOSTED ? DEFAULT_COMPAT_MODEL : "z-ai/glm-5.1"); const SWITCH_INFERENCE_API = process.env.NEMOCLAW_SWITCH_INFERENCE_API ?? "openai-completions"; const SWITCH_MOCK_ANTHROPIC = process.env.NEMOCLAW_SWITCH_MOCK_ANTHROPIC ?? "0"; const SWITCH_MOCK_PORT = parsePortEnv("NEMOCLAW_SWITCH_MOCK_PORT", 0); @@ -817,7 +824,7 @@ RUN_OPENCLAW_INFERENCE_SWITCH_TEST( switchModel: SWITCH_MODEL, switchInferenceApi: SWITCH_INFERENCE_API, contracts: [ - "Docker is running and NVIDIA_API_KEY is nvapi-prefixed", + "Docker is running and NVIDIA_INFERENCE_API_KEY is staged as the compatible endpoint credential", "install.sh --non-interactive onboards an OpenClaw sandbox", "nemoclaw inference set switches the running sandbox route", "OpenClaw gateway process stays running across the switch when its PID is observable", @@ -848,8 +855,8 @@ RUN_OPENCLAW_INFERENCE_SWITCH_TEST( skip("Docker is required for OpenClaw inference switch E2E"); } - const apiKey = secrets.required("NVIDIA_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); + const hosted = requireHostedInferenceConfig(secrets); + const apiKey = hosted.apiKey; const home = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-openclaw-switch-home-")); let mockProvider: MockAnthropicProvider | undefined; @@ -868,7 +875,7 @@ RUN_OPENCLAW_INFERENCE_SWITCH_TEST( artifactName: "install-and-onboard-openclaw-inference-switch", cwd: REPO_ROOT, env: commandEnv(home, { - NVIDIA_API_KEY: apiKey, + ...hosted.env, NEMOCLAW_RECREATE_SANDBOX: "1", }), redactionValues: [apiKey], diff --git a/test/e2e-scenario/live/openclaw-skill-cli.test.ts b/test/e2e-scenario/live/openclaw-skill-cli.test.ts index 9a3c7941dd6..cbd064abbf4 100644 --- a/test/e2e-scenario/live/openclaw-skill-cli.test.ts +++ b/test/e2e-scenario/live/openclaw-skill-cli.test.ts @@ -15,6 +15,7 @@ import { } from "../fixtures/clients/sandbox.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; +import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; import type { ShellProbeResult } from "../fixtures/shell-probe.ts"; // Live Vitest migration for test/e2e/test-openclaw-skill-cli-e2e.sh. @@ -160,7 +161,7 @@ runOpenClawSkillCliTest( sandboxName: SANDBOX_NAME, contracts: [ "Docker is available before install/onboard", - "NVIDIA_API_KEY is present and nvapi-prefixed", + "NVIDIA_INFERENCE_API_KEY is staged as the compatible endpoint credential", "install.sh creates/recreates a real OpenClaw sandbox", "OPENCLAW_HOME, OPENCLAW_STATE_DIR, and OPENCLAW_WORKSPACE_DIR reach the sandbox runtime shell", "openclaw skills install accepts a non-managed source directory inside the sandbox", @@ -171,8 +172,8 @@ runOpenClawSkillCliTest( ], }); - const apiKey = secrets.required("NVIDIA_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); + const hosted = requireHostedInferenceConfig(secrets); + const apiKey = hosted.apiKey; const docker = await host.command("docker", ["info"], { artifactName: "prereq-docker-info-openclaw-skill-cli", @@ -201,7 +202,7 @@ runOpenClawSkillCliTest( artifactName: "install-and-onboard-openclaw-skill-cli", cwd: REPO_ROOT, env: testEnv(home, { - NVIDIA_API_KEY: apiKey, + ...hosted.env, NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, NEMOCLAW_RECREATE_SANDBOX: "1", }), diff --git a/test/e2e-scenario/live/phase6-messaging-helpers.ts b/test/e2e-scenario/live/phase6-messaging-helpers.ts index bfa4c7c49ae..dd4ee5dd554 100644 --- a/test/e2e-scenario/live/phase6-messaging-helpers.ts +++ b/test/e2e-scenario/live/phase6-messaging-helpers.ts @@ -56,9 +56,7 @@ export function phase6Env(options: { NEMOCLAW_SANDBOX_NAME: options.sandboxName, OPENSHELL_GATEWAY: process.env.OPENSHELL_GATEWAY ?? "nemoclaw", ...(options.agent ? { NEMOCLAW_AGENT: options.agent } : {}), - ...(options.apiKey - ? { NVIDIA_INFERENCE_API_KEY: options.apiKey, NVIDIA_API_KEY: options.apiKey } - : {}), + ...(options.apiKey ? { NVIDIA_INFERENCE_API_KEY: options.apiKey } : {}), ...options.extra, }; } diff --git a/test/e2e-scenario/live/rebuild-openclaw.test.ts b/test/e2e-scenario/live/rebuild-openclaw.test.ts index 0c3418121e3..4cc68c6afd3 100644 --- a/test/e2e-scenario/live/rebuild-openclaw.test.ts +++ b/test/e2e-scenario/live/rebuild-openclaw.test.ts @@ -347,10 +347,6 @@ test.skipIf(!shouldRunLiveE2EScenarios())( "rebuild-openclaw: old OpenClaw sandbox rebuild preserves state and rotates gateway token", async ({ artifacts, cleanup, host, sandbox, secrets, skip }) => { const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); - expect( fs.existsSync(CLI_ENTRYPOINT), "bin/nemoclaw.js missing — run npm ci && npm run build:cli before live rebuild coverage", diff --git a/test/e2e-scenario/live/sandbox-rebuild.test.ts b/test/e2e-scenario/live/sandbox-rebuild.test.ts index 86003625cdb..876b4e56d0f 100644 --- a/test/e2e-scenario/live/sandbox-rebuild.test.ts +++ b/test/e2e-scenario/live/sandbox-rebuild.test.ts @@ -87,10 +87,6 @@ test.skipIf(!shouldRunLiveE2EScenarios())( }) => { assertTestOwnedSandboxName(); const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); - const dockerInfo = await host.command("docker", ["info"], { artifactName: "prereq-docker-info", env: buildAvailabilityProbeEnv(), diff --git a/test/e2e-scenario/live/sandbox-survival.test.ts b/test/e2e-scenario/live/sandbox-survival.test.ts index 52e415d9df0..6cf368684f7 100644 --- a/test/e2e-scenario/live/sandbox-survival.test.ts +++ b/test/e2e-scenario/live/sandbox-survival.test.ts @@ -17,6 +17,7 @@ import { buildAvailabilityProbeEnv } from "../fixtures/availability-env.ts"; import { assertExitZero, resultText, sandboxAccessEnv } from "../fixtures/clients/index.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; +import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; import type { NemoClawInstance } from "../fixtures/phases/index.ts"; import type { SandboxMarker } from "../fixtures/phases/state-validation.ts"; @@ -45,16 +46,15 @@ function extractSemver(raw: string): string | undefined { return raw.match(/\d+\.\d+\.\d+/)?.[0]; } -function installEnv(apiKey: string): NodeJS.ProcessEnv { +function installEnv(hostedEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv { return { ...buildAvailabilityProbeEnv(), - NVIDIA_INFERENCE_API_KEY: apiKey, + ...hostedEnv, NEMOCLAW_NON_INTERACTIVE: "1", NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1", NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, NEMOCLAW_RECREATE_SANDBOX: "1", NEMOCLAW_AGENT: "openclaw", - NEMOCLAW_PROVIDER: "cloud", }; } @@ -84,10 +84,8 @@ test.skipIf(!shouldRunLiveE2EScenarios())( skip, stateValidation, }) => { - const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); + const hosted = requireHostedInferenceConfig(secrets); + const apiKey = hosted.apiKey; await artifacts.writeJson("scenario.json", { id: "sandbox-survival", @@ -185,7 +183,7 @@ test.skipIf(!shouldRunLiveE2EScenarios())( const install = await host.command("bash", ["install.sh", "--non-interactive"], { artifactName: "install-sh-sandbox-survival", cwd: REPO_ROOT, - env: installEnv(apiKey), + env: installEnv(hosted.env), redactionValues: [apiKey], timeoutMs: 20 * 60_000, }); diff --git a/test/e2e-scenario/live/sessions-agents-cli.test.ts b/test/e2e-scenario/live/sessions-agents-cli.test.ts index 3744d367a37..2f0e8f71207 100644 --- a/test/e2e-scenario/live/sessions-agents-cli.test.ts +++ b/test/e2e-scenario/live/sessions-agents-cli.test.ts @@ -90,7 +90,7 @@ async function runNemoclaw( return await host.command("node", [CLI_ENTRYPOINT, ...args], { artifactName: options.artifactName, env: commandEnv({ - NVIDIA_API_KEY: apiKey, + NVIDIA_INFERENCE_API_KEY: apiKey, ...(options.env ?? {}), }), redactionValues: [apiKey, ...(options.redactionValues ?? [])], @@ -345,7 +345,7 @@ runSessionsAgentsCliTest( migratedFrom: "test/e2e/test-sessions-agents-cli.sh", sandboxName: SANDBOX_NAME, contracts: [ - "NVIDIA_API_KEY absence skips the live credential-gated scenario", + "NVIDIA_INFERENCE_API_KEY absence skips the live credential-gated scenario", "nemoclaw sessions --json defaults to OpenClaw sessions list", "nemoclaw sessions list --json returns a parseable JSON envelope", "sessions reset/delete gateway RPCs retry through pending pairing/scope approval", @@ -365,9 +365,7 @@ runSessionsAgentsCliTest( `Docker is required for sessions/agents E2E\n${resultText(docker)}`, ).toBe(0); - const apiKey = secrets.required("NVIDIA_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); - + const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); await ensureOpenshellAvailable(host); cleanup.add(`destroy sessions/agents sandbox ${SANDBOX_NAME}`, async () => bestEffort(() => cleanupSandbox(host, apiKey)), diff --git a/test/e2e-scenario/live/shields-config.test.ts b/test/e2e-scenario/live/shields-config.test.ts index 567e66c3b4d..7a1d331184b 100644 --- a/test/e2e-scenario/live/shields-config.test.ts +++ b/test/e2e-scenario/live/shields-config.test.ts @@ -24,6 +24,7 @@ import { } from "../fixtures/clients/sandbox.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; +import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; import type { ShellProbeResult } from "../fixtures/shell-probe.ts"; const REPO_ROOT = path.resolve(import.meta.dirname, "../../.."); @@ -245,10 +246,8 @@ RUN_SHIELDS_TEST( skip("Docker is required for shields-config live E2E"); } - const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); + const hosted = requireHostedInferenceConfig(secrets); + const apiKey = hosted.apiKey; await cleanupSandbox(host, sandbox, "pre-cleanup"); cleanup.add(`destroy shields-config sandbox ${SANDBOX_NAME}`, async () => { @@ -261,7 +260,7 @@ RUN_SHIELDS_TEST( { artifactName: "phase-1-install-shields-config", env: commandEnv({ - NVIDIA_INFERENCE_API_KEY: apiKey, + ...hosted.env, NEMOCLAW_RECREATE_SANDBOX: "1", }), redactionValues: [apiKey], diff --git a/test/e2e-scenario/live/skill-agent.test.ts b/test/e2e-scenario/live/skill-agent.test.ts index 82692c68313..cbc5c708021 100644 --- a/test/e2e-scenario/live/skill-agent.test.ts +++ b/test/e2e-scenario/live/skill-agent.test.ts @@ -12,6 +12,7 @@ import { } from "../fixtures/clients/sandbox.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; +import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; import { shellQuote } from "../../../src/lib/core/shell-quote"; // Focused Vitest live replacement coverage for test/e2e/test-skill-agent-e2e.sh. @@ -220,10 +221,8 @@ runSkillAgentTest( skip("Docker is required for skill-agent E2E"); } - const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); + const hosted = requireHostedInferenceConfig(secrets); + const apiKey = hosted.apiKey; await artifacts.writeJson("scenario.json", { id: "skill-agent", @@ -232,7 +231,7 @@ runSkillAgentTest( legacySource: "test/e2e/test-skill-agent-e2e.sh", contract: [ "Docker is available before onboarding", - "NVIDIA_INFERENCE_API_KEY is present and nvapi-prefixed", + "NVIDIA_INFERENCE_API_KEY is staged as the compatible endpoint credential", "nemoclaw onboard creates/recreates a real OpenClaw sandbox", "skill-smoke-fixture is injected into sandbox and home skill roots", "openclaw agent reads SKILL.md and returns SKILL_SMOKE_VERIFY_K9X2", @@ -298,9 +297,8 @@ runSkillAgentTest( artifactName: "onboard-skill-agent", env: { ...buildAvailabilityProbeEnv(), - NVIDIA_INFERENCE_API_KEY: apiKey, + ...hosted.env, NEMOCLAW_AGENT: "openclaw", - NEMOCLAW_PROVIDER: "cloud", NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, NEMOCLAW_RECREATE_SANDBOX: "1", // This migration targets skill injection + agent skill discovery, not @@ -353,7 +351,7 @@ runSkillAgentTest( cwd: REPO_ROOT, env: { ...buildAvailabilityProbeEnv(), - NVIDIA_INFERENCE_API_KEY: apiKey, + ...hosted.env, SANDBOX_NAME, SKILL_ID, VERIFY_TOKEN: VERIFY_PHRASE, diff --git a/test/e2e-scenario/live/snapshot-commands.test.ts b/test/e2e-scenario/live/snapshot-commands.test.ts index 7d8aa01d121..c69343083bf 100644 --- a/test/e2e-scenario/live/snapshot-commands.test.ts +++ b/test/e2e-scenario/live/snapshot-commands.test.ts @@ -36,7 +36,7 @@ const LIVE_TIMEOUT_MS = 30 * 60_000; const INSTALL_ATTEMPTS = process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true" ? 3 : 1; const CREDENTIAL_TOKEN_VALUE_PATTERN = /(?:nvapi-|sk-|Bearer )/; const CREDENTIAL_ENV_ASSIGNMENT_PATTERN = - /(?:^|\n)\s*(?:export\s+)?(?:NVIDIA_API_KEY|NVIDIA_INFERENCE_API_KEY|OPENAI_API_KEY|ANTHROPIC_API_KEY|COMPATIBLE_API_KEY|NGC_API_KEY|AWS_ACCESS_KEY_ID|AWS_SECRET_ACCESS_KEY)\s*=/i; + /(?:^|\n)\s*(?:export\s+)?(?:NVIDIA_INFERENCE_API_KEY|OPENAI_API_KEY|ANTHROPIC_API_KEY|COMPATIBLE_API_KEY|NGC_API_KEY|AWS_ACCESS_KEY_ID|AWS_SECRET_ACCESS_KEY)\s*=/i; const STRUCTURED_CREDENTIAL_KEY_PATTERN = /["']?(?:apiKey|api_key|accessToken|access_token|secretKey|secret_key|bearerToken|bearer_token)["']?\s*[:=]\s*["'][^"']+["']/i; @@ -53,7 +53,7 @@ function commandEnv(apiKey?: string): NodeJS.ProcessEnv { NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, OPENSHELL_GATEWAY: process.env.OPENSHELL_GATEWAY ?? "nemoclaw", }; - if (apiKey) env.NVIDIA_API_KEY = apiKey; + if (apiKey) env.NVIDIA_INFERENCE_API_KEY = apiKey; return env; } @@ -158,9 +158,7 @@ test.skipIf(!shouldRunLiveE2EScenarios())( "snapshot commands preserve create/list/latest restore/targeted restore/no-leak lifecycle", { timeout: LIVE_TIMEOUT_MS }, async ({ artifacts, cleanup, host, sandbox, secrets, skip }) => { - const apiKey = secrets.required("NVIDIA_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); - + const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); await artifacts.writeJson("scenario.json", { id: "snapshot-commands", runner: "vitest", diff --git a/test/e2e-scenario/live/spark-install.test.ts b/test/e2e-scenario/live/spark-install.test.ts index 2550a033aeb..62eda98ac1c 100644 --- a/test/e2e-scenario/live/spark-install.test.ts +++ b/test/e2e-scenario/live/spark-install.test.ts @@ -112,7 +112,7 @@ liveTest( assertRequiredInstallerEnv(process.env); - const apiKey = secrets.required("NVIDIA_API_KEY"); + const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); const redactionValues = [apiKey]; cleanup.add(`remove ${SANDBOX_NAME} after Spark install smoke`, () => bestEffortCleanup(host)); await bestEffortCleanup(host); @@ -141,7 +141,7 @@ liveTest( artifactName: `phase-1-${installer.mode}-install`, cwd: REPO_ROOT, env: env({ - NVIDIA_API_KEY: apiKey, + NVIDIA_INFERENCE_API_KEY: apiKey, }), redactionValues, timeoutMs: INSTALL_TIMEOUT_MS, diff --git a/test/e2e-scenario/live/state-backup-restore.test.ts b/test/e2e-scenario/live/state-backup-restore.test.ts index a7a7ec8f526..14e886041ea 100644 --- a/test/e2e-scenario/live/state-backup-restore.test.ts +++ b/test/e2e-scenario/live/state-backup-restore.test.ts @@ -142,8 +142,7 @@ test.skipIf(!shouldRunLiveE2EScenarios())( stateValidation, }) => { assertTestOwnedSandboxName(); - const apiKey = secrets.required("NVIDIA_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); + const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); expect(fs.existsSync(path.join(REPO_ROOT, "scripts", "backup-workspace.sh"))).toBe(true); const dockerInfo = await host.command("docker", ["info"], { diff --git a/test/e2e-scenario/live/upgrade-stale-sandbox-helpers.ts b/test/e2e-scenario/live/upgrade-stale-sandbox-helpers.ts index 8b6fecc2ffb..b14d4bc39a5 100644 --- a/test/e2e-scenario/live/upgrade-stale-sandbox-helpers.ts +++ b/test/e2e-scenario/live/upgrade-stale-sandbox-helpers.ts @@ -53,7 +53,7 @@ export function commandEnv(apiKey?: string): NodeJS.ProcessEnv { NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, OPENSHELL_GATEWAY: process.env.OPENSHELL_GATEWAY ?? "nemoclaw", }; - apiKey && Object.assign(env, { NVIDIA_INFERENCE_API_KEY: apiKey, NVIDIA_API_KEY: apiKey }); + apiKey && Object.assign(env, { NVIDIA_INFERENCE_API_KEY: apiKey }); return env; } diff --git a/test/e2e-scenario/support-tests/cloud-inference-provider-skip.test.ts b/test/e2e-scenario/support-tests/cloud-inference-provider-skip.test.ts index f5dda0199e6..dab649a8543 100644 --- a/test/e2e-scenario/support-tests/cloud-inference-provider-skip.test.ts +++ b/test/e2e-scenario/support-tests/cloud-inference-provider-skip.test.ts @@ -45,7 +45,7 @@ describe("cloud inference pre-contract provider skip classifier", () => { it("does not skip credential or auth endpoint-validation failures", () => { expect( classifyPreContractExternalProviderFailure( - probeOutput("endpoint validation failed: invalid NVIDIA_API_KEY credential"), + probeOutput("endpoint validation failed: invalid NVIDIA_INFERENCE_API_KEY credential"), ), ).toBeNull(); expect( diff --git a/test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts b/test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts index 37c1a21f5f5..ddf0a460fc5 100644 --- a/test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts +++ b/test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts @@ -1044,7 +1044,7 @@ jobs: const snapshotJob = parsedWorkflow.jobs["snapshot-commands-vitest"]; snapshotJob["timeout-minutes"] = 30; snapshotJob.env.DOCKER_CONFIG = "${{ github.workspace }}/.docker-config-shared"; - snapshotJob.env.NVIDIA_API_KEY = "${{ secrets.NVIDIA_API_KEY }}"; + snapshotJob.env.NVIDIA_INFERENCE_API_KEY = "${{ secrets.NVIDIA_INFERENCE_API_KEY }}"; for (const step of snapshotJob.steps) { if (typeof step.uses === "string" && step.uses.startsWith("actions/checkout@")) { step.with = { ...(step.with as Record), "persist-credentials": true }; @@ -1054,7 +1054,7 @@ jobs: 'echo "DOCKER_CONFIG=${{ github.workspace }}/.docker-config-shared" >> "$GITHUB_ENV"'; } if (step.name === "Set up Node") { - step.env = { NVIDIA_API_KEY: "${{ secrets.NVIDIA_API_KEY }}" }; + step.env = { NVIDIA_INFERENCE_API_KEY: "${{ secrets.NVIDIA_INFERENCE_API_KEY }}" }; } if (step.name === "Install root dependencies") { step.env = { @@ -1089,8 +1089,8 @@ jobs: "snapshot-commands-vitest job must not set DOCKER_CONFIG at job level", 'step \'Configure isolated Docker auth directory\' run script must include echo "DOCKER_CONFIG=${RUNNER_TEMP}/docker-config-snapshot-commands" >> "$GITHUB_ENV"', "snapshot-commands-vitest checkout step must set persist-credentials=false", - "snapshot-commands-vitest job env must not include NVIDIA_API_KEY", - "snapshot-commands-vitest step 'Set up Node' env must not include NVIDIA_API_KEY", + "snapshot-commands-vitest job env must not include NVIDIA_INFERENCE_API_KEY", + "snapshot-commands-vitest step 'Set up Node' env must not include NVIDIA_INFERENCE_API_KEY", "snapshot-commands-vitest step 'Install root dependencies' env must not include DOCKERHUB_USERNAME", "snapshot-commands-vitest step 'Install root dependencies' env must not include DOCKERHUB_TOKEN", "snapshot-commands-vitest artifact upload must set include-hidden-files: false", @@ -1118,13 +1118,13 @@ jobs: env: { FREE_STANDING_VITEST_JOB: "1", FREE_STANDING_SCENARIO_ID: "ad-hoc-derived", - NVIDIA_API_KEY: "${{ secrets.NVIDIA_API_KEY }}", + NVIDIA_INFERENCE_API_KEY: "${{ secrets.NVIDIA_INFERENCE_API_KEY }}", }, steps: [ { uses: "actions/checkout@v4" }, { name: "Run ad hoc", - run: "echo ${{ inputs.jobs }} && echo ${{ secrets.NVIDIA_API_KEY }}", + run: "echo ${{ inputs.jobs }} && echo ${{ secrets.NVIDIA_INFERENCE_API_KEY }}", }, ], }; @@ -1135,7 +1135,7 @@ jobs: expect.arrayContaining([ "ad-hoc-derived-vitest job must depend on generate-matrix", "ad-hoc-derived-vitest job must use the shared jobs selector condition", - "ad-hoc-derived-vitest job env must not include NVIDIA_API_KEY", + "ad-hoc-derived-vitest job env must not include NVIDIA_INFERENCE_API_KEY", "ad-hoc-derived-vitest step 'actions/checkout@v4' action must be pinned to a full commit SHA", "step 'Run ad hoc' run script must not interpolate dispatch inputs directly", "ad-hoc-derived-vitest step 'Run ad hoc' run script must not interpolate secrets directly", @@ -1196,7 +1196,7 @@ jobs: job.strategy.matrix.agent = ["openclaw"]; job.env.NEMOCLAW_SANDBOX_NAME = "personal-dev-${{ matrix.agent }}"; job.env.DOCKER_CONFIG = "${{ github.workspace }}/.docker-config-shared"; - job.env.NVIDIA_API_KEY = "${{ secrets.NVIDIA_API_KEY }}"; + job.env.NVIDIA_INFERENCE_API_KEY = "${{ secrets.NVIDIA_INFERENCE_API_KEY }}"; const checkoutStep = job.steps.find( (step) => typeof step.uses === "string" && step.uses.startsWith("actions/checkout@"), ); @@ -1222,7 +1222,6 @@ jobs: const runStep = job.steps.find((step) => step.name === "Run channels stop/start live test"); expect(runStep).toBeDefined(); runStep!.env = { - NVIDIA_API_KEY: "${{ secrets.NVIDIA_API_KEY }}", TELEGRAM_BOT_TOKEN: "real-token", }; runStep!.run = String(runStep!.run).replace( @@ -1258,11 +1257,10 @@ jobs: "channels-stop-start-vitest matrix.agent must be openclaw,hermes", "channels-stop-start-vitest job must derive NEMOCLAW_SANDBOX_NAME from matrix.agent with the e2e-channels-stop-start- prefix", "channels-stop-start-vitest job must isolate Docker auth by matrix agent", - "channels-stop-start-vitest job env must not include NVIDIA_API_KEY", + "channels-stop-start-vitest job env must not include NVIDIA_INFERENCE_API_KEY", "channels-stop-start-vitest checkout step must set persist-credentials=false", "step 'Install root dependencies' run script must include npm ci --ignore-scripts", "step 'Install OpenShell' run script must include env -u DOCKER_CONFIG", - "channels-stop-start-vitest step 'Run channels stop/start live test' env must not include NVIDIA_API_KEY", "channels-stop-start-vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets", "channels-stop-start-vitest step must set the fake Telegram token", "step 'Run channels stop/start live test' run script must include test/e2e-scenario/live/channels-stop-start.test.ts", @@ -1383,7 +1381,7 @@ jobs: job.env = { ...job.env, DOCKER_CONFIG: "${{ github.workspace }}/.docker-config-diagnostics", - NVIDIA_API_KEY: "${{ secrets.NVIDIA_API_KEY }}", + NVIDIA_INFERENCE_API_KEY: "${{ secrets.NVIDIA_INFERENCE_API_KEY }}", GITHUB_TOKEN: "${{ github.token }}", }; const setupNodeIndex = job.steps.findIndex((step) => step.name === "Set up Node"); @@ -1413,7 +1411,7 @@ jobs: expect(errors).toEqual( expect.arrayContaining([ "diagnostics-vitest job must not expose Docker auth to branch-controlled steps", - "diagnostics-vitest job env must not include NVIDIA_API_KEY", + "diagnostics-vitest job env must not include NVIDIA_INFERENCE_API_KEY", "diagnostics-vitest job env must not include GITHUB_TOKEN", "diagnostics-vitest job must not authenticate to Docker Hub before branch-controlled test code runs", "diagnostics-vitest step 'Authenticate to Docker Hub' env must not include DOCKERHUB_USERNAME", diff --git a/test/e2e-scenario/support-tests/hosted-inference.test.ts b/test/e2e-scenario/support-tests/hosted-inference.test.ts index 8a21df80667..e8f73c14b45 100644 --- a/test/e2e-scenario/support-tests/hosted-inference.test.ts +++ b/test/e2e-scenario/support-tests/hosted-inference.test.ts @@ -154,10 +154,13 @@ describe("hosted inference E2E config", () => { ); expect(cfg.env).toMatchObject({ + NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1", NEMOCLAW_PROVIDER: "custom", NEMOCLAW_ENDPOINT_URL: "https://inference-api.nvidia.com/v1", NEMOCLAW_MODEL: "nvidia/custom-model", NEMOCLAW_COMPAT_MODEL: "nvidia/custom-model", + NEMOCLAW_PREFERRED_API: "openai-completions", + NVIDIA_INFERENCE_API_KEY: "repo-hosted-key", COMPATIBLE_API_KEY: "repo-hosted-key", }); }); diff --git a/test/e2e-scenario/support-tests/network-policy-transient-provider.test.ts b/test/e2e-scenario/support-tests/network-policy-transient-provider.test.ts index c93bd30b1c2..1cd332c7272 100644 --- a/test/e2e-scenario/support-tests/network-policy-transient-provider.test.ts +++ b/test/e2e-scenario/support-tests/network-policy-transient-provider.test.ts @@ -33,7 +33,9 @@ describe("network-policy transient provider validation classifier", () => { ).toBe(false); expect( isTransientProviderValidationFailure( - probeOutput("endpoint validation failed: invalid NVIDIA_API_KEY credential quota exceeded"), + probeOutput( + "endpoint validation failed: invalid NVIDIA_INFERENCE_API_KEY credential quota exceeded", + ), ), ).toBe(false); expect( diff --git a/test/e2e-scenario/support-tests/openclaw-discord-workflow-boundary.test.ts b/test/e2e-scenario/support-tests/openclaw-discord-workflow-boundary.test.ts index 484e76b5b33..e35d7e04e36 100644 --- a/test/e2e-scenario/support-tests/openclaw-discord-workflow-boundary.test.ts +++ b/test/e2e-scenario/support-tests/openclaw-discord-workflow-boundary.test.ts @@ -47,10 +47,6 @@ describe("OpenClaw Discord pairing workflow boundary", () => { unknown >; Object.assign(buildCli, { run: "echo skipping build" }); - const liveStep = discordJob.steps.find( - (step) => step.name === "Run OpenClaw Discord pairing live test", - ) as { env: Record }; - liveStep.env.NVIDIA_API_KEY = "${{ secrets.NVIDIA_API_KEY }}"; const installOpenShell = discordJob.steps.find( (step) => step.name === "Install OpenShell CLI", ) as Record; @@ -66,7 +62,6 @@ describe("OpenClaw Discord pairing workflow boundary", () => { "openclaw-discord-pairing-vitest setup-node action must be pinned to a full commit SHA", "step 'Install root dependencies' run script must include npm ci --ignore-scripts", "step 'Build CLI' run script must include npm run build:cli", - "openclaw-discord-pairing-vitest step 'Run OpenClaw Discord pairing live test' env must not include NVIDIA_API_KEY", "step 'Install OpenShell CLI' run script must include env -u DOCKER_CONFIG", ]), ); diff --git a/test/e2e-scenario/support-tests/openclaw-slack-workflow-boundary.test.ts b/test/e2e-scenario/support-tests/openclaw-slack-workflow-boundary.test.ts index a466d3cbda3..4337729259a 100644 --- a/test/e2e-scenario/support-tests/openclaw-slack-workflow-boundary.test.ts +++ b/test/e2e-scenario/support-tests/openclaw-slack-workflow-boundary.test.ts @@ -54,7 +54,6 @@ describe("OpenClaw Slack pairing workflow boundary", () => { const liveStep = slackJob.steps.find( (step) => step.name === "Run OpenClaw Slack pairing live test", ) as { env: Record }; - liveStep.env.NVIDIA_API_KEY = "${{ secrets.NVIDIA_API_KEY }}"; liveStep.env.SLACK_APP_TOKEN = "real-ish-token"; const installOpenShell = slackJob.steps.find( (step) => step.name === "Install OpenShell CLI", @@ -73,7 +72,6 @@ describe("OpenClaw Slack pairing workflow boundary", () => { "openclaw-slack-pairing-vitest setup-node action must be pinned to a full commit SHA", "step 'Install root dependencies' run script must include npm ci --ignore-scripts", "step 'Build CLI' run script must include npm run build:cli", - "openclaw-slack-pairing-vitest step 'Run OpenClaw Slack pairing live test' env must not include NVIDIA_API_KEY", "openclaw-slack-pairing-vitest step must use fake Slack app token", "step 'Install OpenShell CLI' run script must include env -u DOCKER_CONFIG", ]), diff --git a/test/e2e-scenario/support-tests/spark-install-workflow-boundary.test.ts b/test/e2e-scenario/support-tests/spark-install-workflow-boundary.test.ts index 184f710bc9c..f3e30fef121 100644 --- a/test/e2e-scenario/support-tests/spark-install-workflow-boundary.test.ts +++ b/test/e2e-scenario/support-tests/spark-install-workflow-boundary.test.ts @@ -64,7 +64,7 @@ describe("spark install workflow boundary", () => { E2E_ARTIFACT_DIR: "tmp/spark-install", NEMOCLAW_CLI_BIN: "/usr/bin/nemoclaw", NEMOCLAW_RUN_E2E_SCENARIOS: "0", - NVIDIA_API_KEY: "${{ secrets.NVIDIA_API_KEY }}", + NVIDIA_INFERENCE_API_KEY: "${{ secrets.NVIDIA_INFERENCE_API_KEY }}", NEMOCLAW_NON_INTERACTIVE: "0", NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "0", NEMOCLAW_FRESH: "0", @@ -89,7 +89,7 @@ describe("spark install workflow boundary", () => { const install = job.steps.find((step) => step.name === "Install root dependencies"); expect(install).toBeDefined(); - install!.env = { NVIDIA_API_KEY: "${{ secrets.NVIDIA_API_KEY }}" }; + install!.env = { NVIDIA_INFERENCE_API_KEY: "${{ secrets.NVIDIA_INFERENCE_API_KEY }}" }; install!.run = "npm install"; const runSpark = job.steps.find((step) => step.name === "Run Spark install live test"); @@ -124,13 +124,13 @@ describe("spark install workflow boundary", () => { "spark-install-vitest job must use the stable e2e-spark-install-vitest sandbox name", "spark-install-vitest job must use the cloud provider", "spark-install-vitest job must force OPENSHELL_GATEWAY=nemoclaw", - "spark-install-vitest job env must not include NVIDIA_API_KEY", + "spark-install-vitest job env must not include NVIDIA_INFERENCE_API_KEY", "spark-install-vitest checkout action must be pinned to a full commit SHA", "spark-install-vitest checkout step must set persist-credentials=false", "spark-install-vitest setup-node action must be pinned to a full commit SHA", - "spark-install-vitest step 'Install root dependencies' env must not include NVIDIA_API_KEY", + "spark-install-vitest step 'Install root dependencies' env must not include NVIDIA_INFERENCE_API_KEY", "step 'Install root dependencies' run script must include npm ci --ignore-scripts", - "spark-install-vitest Vitest step must receive NVIDIA_API_KEY from secrets", + "spark-install-vitest Vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets", "step 'Run Spark install live test' run script must include set -euo pipefail", "step 'Run Spark install live test' run script must include test/e2e-scenario/live/spark-install.test.ts", "spark-install-vitest artifact upload name must be stable", diff --git a/test/e2e-scenario/support-tests/tunnel-lifecycle-workflow-boundary.test.ts b/test/e2e-scenario/support-tests/tunnel-lifecycle-workflow-boundary.test.ts index 35cc3d88e29..994a47806fc 100644 --- a/test/e2e-scenario/support-tests/tunnel-lifecycle-workflow-boundary.test.ts +++ b/test/e2e-scenario/support-tests/tunnel-lifecycle-workflow-boundary.test.ts @@ -99,7 +99,6 @@ describe("tunnel lifecycle workflow boundary", () => { expect(install).toBeDefined(); install!.env = { NVIDIA_INFERENCE_API_KEY: "${{ secrets.NVIDIA_INFERENCE_API_KEY }}", - NVIDIA_API_KEY: "${{ secrets.NVIDIA_API_KEY }}", }; install!.run = "npm install"; @@ -109,7 +108,6 @@ describe("tunnel lifecycle workflow boundary", () => { expect(cloudflared).toBeDefined(); cloudflared!.env = { NVIDIA_INFERENCE_API_KEY: "${{ secrets.NVIDIA_INFERENCE_API_KEY }}", - NVIDIA_API_KEY: "${{ secrets.NVIDIA_API_KEY }}", }; cloudflared!.run = "cloudflared --version"; @@ -139,12 +137,9 @@ describe("tunnel lifecycle workflow boundary", () => { "step 'Configure isolated Docker auth directory' run script must not include ${{ github.workspace }}", "tunnel-lifecycle-vitest checkout step must set persist-credentials=false", "tunnel-lifecycle-vitest step 'Install root dependencies' env must not include NVIDIA_INFERENCE_API_KEY", - "tunnel-lifecycle-vitest step 'Install root dependencies' env must not include NVIDIA_API_KEY", "step 'Install root dependencies' run script must include npm ci --ignore-scripts", "tunnel-lifecycle-vitest step 'Install and verify cloudflared prerequisite' env must not include NVIDIA_INFERENCE_API_KEY", - "tunnel-lifecycle-vitest step 'Install and verify cloudflared prerequisite' env must not include NVIDIA_API_KEY", "tunnel-lifecycle-vitest cloudflared prerequisite step env must not include NVIDIA_INFERENCE_API_KEY", - "tunnel-lifecycle-vitest cloudflared prerequisite step env must not include NVIDIA_API_KEY", "step 'Install and verify cloudflared prerequisite' run script must include test/e2e/lib/cloudflared-version-resolver.sh", "step 'Install and verify cloudflared prerequisite' run script must include sudo apt-get install -y", "step 'Install and verify cloudflared prerequisite' run script must include cloudflared=${cf_version}", diff --git a/tools/e2e-scenarios/workflow-boundary.mts b/tools/e2e-scenarios/workflow-boundary.mts index 6811e3bb65a..5101e5c2ee8 100644 --- a/tools/e2e-scenarios/workflow-boundary.mts +++ b/tools/e2e-scenarios/workflow-boundary.mts @@ -42,6 +42,7 @@ const FREE_STANDING_JOB_MARKER = "FREE_STANDING_VITEST_JOB"; const FREE_STANDING_SCENARIO_MARKER = "FREE_STANDING_SCENARIO_ID"; const COMMON_SECRET_ENV_NAMES = [ "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", "DOCKERHUB_USERNAME", "DOCKERHUB_TOKEN", "GITHUB_TOKEN", @@ -1157,7 +1158,7 @@ function validateCommonEgressAgentVitestJob( ); } for (const secret of [ - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", "DOCKERHUB_USERNAME", "DOCKERHUB_TOKEN", "GITHUB_TOKEN", @@ -1180,7 +1181,7 @@ function validateCommonEgressAgentVitestJob( errors, `common-egress-agent-vitest step '${stepName}'`, stepEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); } for (const secret of [ @@ -1247,7 +1248,7 @@ function validateCommonEgressAgentVitestJob( requireRunContains(errors, installOpenShell, "env -u DOCKER_CONFIG"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_USERNAME"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_TOKEN"); - requireRunContains(errors, installOpenShell, "-u NVIDIA_API_KEY"); + requireRunContains(errors, installOpenShell, "-u NVIDIA_INFERENCE_API_KEY"); requireRunContains(errors, installOpenShell, "-u GITHUB_TOKEN"); const runVitest = requireJobStep( @@ -1257,9 +1258,9 @@ function validateCommonEgressAgentVitestJob( "Run common-egress agent live test", ); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { errors.push( - "common-egress-agent-vitest step must receive NVIDIA_API_KEY from secrets", + "common-egress-agent-vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets", ); } requireRunContains(errors, runVitest, "OPENSHELL_BIN"); @@ -2233,7 +2234,7 @@ function validateStateBackupRestoreVitestJob( ); } for (const secret of [ - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", "DOCKERHUB_USERNAME", "DOCKERHUB_TOKEN", "GITHUB_TOKEN", @@ -2256,7 +2257,7 @@ function validateStateBackupRestoreVitestJob( errors, stepName, stepEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); } if (step.name !== "Authenticate to Docker Hub") { @@ -2351,7 +2352,7 @@ function validateStateBackupRestoreVitestJob( requireRunContains(errors, installOpenShell, "env -u DOCKER_CONFIG"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_USERNAME"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_TOKEN"); - requireRunContains(errors, installOpenShell, "-u NVIDIA_API_KEY"); + requireRunContains(errors, installOpenShell, "-u NVIDIA_INFERENCE_API_KEY"); requireRunContains(errors, installOpenShell, "-u GITHUB_TOKEN"); const runVitest = requireJobStep( @@ -2361,9 +2362,9 @@ function validateStateBackupRestoreVitestJob( "Run state backup restore live test", ); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { errors.push( - "state-backup-restore-vitest step must receive NVIDIA_API_KEY from secrets", + "state-backup-restore-vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets", ); } requireRunContains(errors, runVitest, "OPENSHELL_BIN"); @@ -2475,7 +2476,6 @@ function validateUpgradeStaleSandboxVitestJob( ); } for (const secret of [ - "NVIDIA_INFERENCE_API_KEY", ...COMMON_SECRET_ENV_NAMES, ]) { requireEnvDoesNotExposeSecret( @@ -2502,7 +2502,7 @@ function validateUpgradeStaleSandboxVitestJob( errors, stepName, stepEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); } if (step.name !== "Authenticate to Docker Hub") { @@ -2612,7 +2612,6 @@ function validateUpgradeStaleSandboxVitestJob( requireRunContains(errors, installOpenShell, "-u DOCKERHUB_USERNAME"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_TOKEN"); requireRunContains(errors, installOpenShell, "-u NVIDIA_INFERENCE_API_KEY"); - requireRunContains(errors, installOpenShell, "-u NVIDIA_API_KEY"); requireRunContains(errors, installOpenShell, "-u GITHUB_TOKEN"); const runVitest = requireJobStep( @@ -2943,7 +2942,7 @@ function validateMessagingCompatibleEndpointVitestJob( errors, "messaging-compatible-endpoint-vitest job", jobEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); requireEnvDoesNotExposeSecret( errors, @@ -2967,7 +2966,7 @@ function validateMessagingCompatibleEndpointVitestJob( errors, `messaging-compatible-endpoint-vitest step '${stepName}'`, stepEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); requireEnvDoesNotExposeSecret( errors, @@ -3049,7 +3048,7 @@ function validateMessagingCompatibleEndpointVitestJob( errors, "messaging-compatible-endpoint-vitest step", runVitestEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); if (runVitestEnv.NEMOCLAW_COMPAT_MOCK_API_KEY !== "fake-compatible-key-e2e") { errors.push( @@ -3321,7 +3320,7 @@ function validateCloudInferenceVitestJob( errors, "cloud-inference-vitest job", jobEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); const steps = asSteps(job.steps); @@ -3332,7 +3331,7 @@ function validateCloudInferenceVitestJob( errors, `cloud-inference-vitest step '${step.name ?? step.uses ?? ""}'`, asRecord(step.env), - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); } } @@ -3376,9 +3375,9 @@ function validateCloudInferenceVitestJob( "Run cloud inference live test", ); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { errors.push( - "cloud-inference-vitest run step must receive NVIDIA_API_KEY from secrets", + "cloud-inference-vitest run step must receive NVIDIA_INFERENCE_API_KEY from secrets", ); } requireRunContains( @@ -4343,7 +4342,7 @@ function validateDiagnosticsVitestJob( errors.push("diagnostics-vitest job must force OPENSHELL_GATEWAY=nemoclaw"); } for (const secret of [ - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", "DOCKERHUB_USERNAME", "DOCKERHUB_TOKEN", "GITHUB_TOKEN", @@ -4366,7 +4365,7 @@ function validateDiagnosticsVitestJob( errors, stepName, stepEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); } requireEnvDoesNotExposeSecret( @@ -4424,9 +4423,9 @@ function validateDiagnosticsVitestJob( "Run diagnostics live test", ); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { errors.push( - "diagnostics-vitest Vitest step must receive NVIDIA_API_KEY from secrets", + "diagnostics-vitest Vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets", ); } requireRunContains( @@ -4555,7 +4554,7 @@ function validateSparkInstallVitestJob( errors, stepName, stepEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); } requireEnvDoesNotExposeSecret( @@ -4606,9 +4605,9 @@ function validateSparkInstallVitestJob( "Run Spark install live test", ); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { errors.push( - "spark-install-vitest Vitest step must receive NVIDIA_API_KEY from secrets", + "spark-install-vitest Vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets", ); } requireRunContains(errors, runVitest, "set -euo pipefail"); @@ -4717,7 +4716,7 @@ function validateSnapshotCommandsVitestJob( ); } for (const secret of [ - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", "DOCKERHUB_USERNAME", "DOCKERHUB_TOKEN", "GITHUB_TOKEN", @@ -4740,7 +4739,7 @@ function validateSnapshotCommandsVitestJob( errors, stepName, stepEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); } if (step.name !== "Authenticate to Docker Hub") { @@ -4841,9 +4840,9 @@ function validateSnapshotCommandsVitestJob( "Run snapshot commands live test", ); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { errors.push( - "snapshot-commands-vitest Vitest step must receive NVIDIA_API_KEY from secrets", + "snapshot-commands-vitest Vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets", ); } requireRunContains( @@ -5245,7 +5244,7 @@ function validateTunnelLifecycleVitestJob( errors, stepName, stepEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); } if (step.name !== "Authenticate to Docker Hub") { @@ -5359,7 +5358,7 @@ function validateTunnelLifecycleVitestJob( errors, "tunnel-lifecycle-vitest cloudflared prerequisite step", cloudflaredPrereqEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); requireRunContains(errors, cloudflaredPrereq, "cloudflared --version"); requireRunContains( @@ -5501,7 +5500,6 @@ function validateIssue2478CrashLoopRecoveryVitestJob( } } for (const secret of [ - "NVIDIA_INFERENCE_API_KEY", ...COMMON_SECRET_ENV_NAMES, ]) { requireEnvDoesNotExposeSecret( @@ -5523,7 +5521,7 @@ function validateIssue2478CrashLoopRecoveryVitestJob( stepEnv, "NVIDIA_INFERENCE_API_KEY", ); - requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_API_KEY"); + requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_INFERENCE_API_KEY"); if (step.name !== "Authenticate to Docker Hub") { requireEnvDoesNotExposeSecret( errors, @@ -5784,7 +5782,7 @@ function validateChannelsAddRemoveVitestJob( ); } for (const secret of [ - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", "DOCKERHUB_USERNAME", "DOCKERHUB_TOKEN", "GITHUB_TOKEN", @@ -5807,7 +5805,7 @@ function validateChannelsAddRemoveVitestJob( errors, stepName, stepEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); } if (step.name !== "Authenticate to Docker Hub") { @@ -5898,7 +5896,7 @@ function validateChannelsAddRemoveVitestJob( requireRunContains(errors, installOpenShell, "env -u DOCKER_CONFIG"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_USERNAME"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_TOKEN"); - requireRunContains(errors, installOpenShell, "-u NVIDIA_API_KEY"); + requireRunContains(errors, installOpenShell, "-u NVIDIA_INFERENCE_API_KEY"); requireRunContains(errors, installOpenShell, "-u GITHUB_TOKEN"); const runVitest = requireJobStep( @@ -5908,9 +5906,9 @@ function validateChannelsAddRemoveVitestJob( "Run channels add/remove live test", ); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { errors.push( - "channels-add-remove-vitest step must receive NVIDIA_API_KEY from secrets", + "channels-add-remove-vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets", ); } if ( @@ -6014,8 +6012,6 @@ function validateOpenClawDiscordPairingVitestJob( ); } for (const secret of [ - "NVIDIA_INFERENCE_API_KEY", - "NVIDIA_API_KEY", ...COMMON_SECRET_ENV_NAMES, ]) { requireEnvDoesNotExposeSecret( @@ -6039,7 +6035,6 @@ function validateOpenClawDiscordPairingVitestJob( "NVIDIA_INFERENCE_API_KEY", ); } - requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_API_KEY"); if (step.name !== "Authenticate to Docker Hub") { requireEnvDoesNotExposeSecret( errors, @@ -6156,7 +6151,6 @@ function validateOpenClawDiscordPairingVitestJob( requireRunContains(errors, installOpenShell, "env -u DOCKER_CONFIG"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_USERNAME"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_TOKEN"); - requireRunContains(errors, installOpenShell, "-u NVIDIA_API_KEY"); requireRunContains(errors, installOpenShell, "-u NVIDIA_INFERENCE_API_KEY"); requireRunContains(errors, installOpenShell, "-u GITHUB_TOKEN"); @@ -6269,8 +6263,6 @@ function validateOpenClawSlackPairingVitestJob( ); } for (const secret of [ - "NVIDIA_INFERENCE_API_KEY", - "NVIDIA_API_KEY", ...COMMON_SECRET_ENV_NAMES, ]) { requireEnvDoesNotExposeSecret( @@ -6294,7 +6286,6 @@ function validateOpenClawSlackPairingVitestJob( "NVIDIA_INFERENCE_API_KEY", ); } - requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_API_KEY"); if (step.name !== "Authenticate to Docker Hub") { requireEnvDoesNotExposeSecret( errors, @@ -6409,7 +6400,6 @@ function validateOpenClawSlackPairingVitestJob( requireRunContains(errors, installOpenShell, "env -u DOCKER_CONFIG"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_USERNAME"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_TOKEN"); - requireRunContains(errors, installOpenShell, "-u NVIDIA_API_KEY"); requireRunContains(errors, installOpenShell, "-u NVIDIA_INFERENCE_API_KEY"); requireRunContains(errors, installOpenShell, "-u GITHUB_TOKEN"); @@ -6595,7 +6585,6 @@ function validateChannelsStopStartVitestJob( } for (const secret of [ "NVIDIA_INFERENCE_API_KEY", - "NVIDIA_API_KEY", "DOCKERHUB_USERNAME", "DOCKERHUB_TOKEN", "GITHUB_TOKEN", @@ -6620,12 +6609,6 @@ function validateChannelsStopStartVitestJob( stepEnv, "NVIDIA_INFERENCE_API_KEY", ); - requireEnvDoesNotExposeSecret( - errors, - stepName, - stepEnv, - "NVIDIA_API_KEY", - ); } if (step.name !== "Authenticate to Docker Hub") { requireEnvDoesNotExposeSecret( @@ -6718,7 +6701,7 @@ function validateChannelsStopStartVitestJob( requireRunContains(errors, installOpenShell, "env -u DOCKER_CONFIG"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_USERNAME"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_TOKEN"); - requireRunContains(errors, installOpenShell, "-u NVIDIA_API_KEY"); + requireRunContains(errors, installOpenShell, "-u NVIDIA_INFERENCE_API_KEY"); requireRunContains(errors, installOpenShell, "-u GITHUB_TOKEN"); const runVitest = requireJobStep( @@ -6728,12 +6711,6 @@ function validateChannelsStopStartVitestJob( "Run channels stop/start live test", ); const runVitestEnv = asRecord(runVitest?.env); - requireEnvDoesNotExposeSecret( - errors, - "channels-stop-start-vitest step 'Run channels stop/start live test'", - runVitestEnv, - "NVIDIA_API_KEY", - ); if ( runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}" @@ -6880,8 +6857,6 @@ function validateTelegramInjectionVitestJob( ); } for (const secret of [ - "NVIDIA_INFERENCE_API_KEY", - "NVIDIA_API_KEY", ...COMMON_SECRET_ENV_NAMES, ]) { requireEnvDoesNotExposeSecret( @@ -6908,7 +6883,7 @@ function validateTelegramInjectionVitestJob( errors, stepName, stepEnv, - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", ); } if (step.name !== "Authenticate to Docker Hub") { @@ -6985,7 +6960,6 @@ function validateTelegramInjectionVitestJob( requireRunContains(errors, installOpenShell, "env -u DOCKER_CONFIG"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_USERNAME"); requireRunContains(errors, installOpenShell, "-u DOCKERHUB_TOKEN"); - requireRunContains(errors, installOpenShell, "-u NVIDIA_API_KEY"); requireRunContains(errors, installOpenShell, "-u NVIDIA_INFERENCE_API_KEY"); requireRunContains(errors, installOpenShell, "-u GITHUB_TOKEN"); @@ -7156,7 +7130,7 @@ function validateBedrockRuntimeCompatibleAnthropicVitestJob( ); } for (const secret of [ - "NVIDIA_API_KEY", + "NVIDIA_INFERENCE_API_KEY", "DOCKERHUB_USERNAME", "DOCKERHUB_TOKEN", "GITHUB_TOKEN", @@ -7174,7 +7148,7 @@ function validateBedrockRuntimeCompatibleAnthropicVitestJob( for (const step of steps) { const stepName = `bedrock-runtime-compatible-anthropic-vitest step '${step.name ?? step.uses ?? ""}'`; const stepEnv = asRecord(step.env); - requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_API_KEY"); + requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_INFERENCE_API_KEY"); requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "GITHUB_TOKEN"); if (step.name !== "Authenticate to Docker Hub") { requireEnvDoesNotExposeSecret(