diff --git a/.github/workflows/brev-nightly-e2e.yaml b/.github/workflows/brev-nightly-e2e.yaml index 4e07e8e156b..213f0b47405 100644 --- a/.github/workflows/brev-nightly-e2e.yaml +++ b/.github/workflows/brev-nightly-e2e.yaml @@ -49,4 +49,4 @@ jobs: secrets: BREV_API_KEY: ${{ secrets.BREV_API_KEY }} BREV_ORG_ID: ${{ secrets.BREV_ORG_ID }} - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} diff --git a/.github/workflows/e2e-branch-validation.yaml b/.github/workflows/e2e-branch-validation.yaml index 5110a6a5274..4524405a2b6 100644 --- a/.github/workflows/e2e-branch-validation.yaml +++ b/.github/workflows/e2e-branch-validation.yaml @@ -48,7 +48,7 @@ name: E2E / Branch Validation # all — Runs credential-sanitization + telegram-injection (NOT full, # which destroys the sandbox the security tests need). # -# Required secrets: BREV_API_KEY + BREV_ORG_ID (or legacy BREV_API_TOKEN), NVIDIA_INFERENCE_API_KEY +# Required secrets: BREV_API_KEY + BREV_ORG_ID (or legacy BREV_API_TOKEN), NVIDIA_API_KEY # Instance cost: Brev CPU credits (~$0.10/run for 4x16 instance) on: @@ -157,7 +157,7 @@ on: required: false BREV_ORG_ID: required: false - NVIDIA_INFERENCE_API_KEY: + NVIDIA_API_KEY: required: true permissions: @@ -253,7 +253,7 @@ jobs: env: NEMOCLAW_RUN_BRANCH_VALIDATION_E2E: "1" BREV_API_TOKEN: ${{ inputs.brev_token || secrets.BREV_API_TOKEN }} - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} GITHUB_TOKEN: ${{ github.token }} INSTANCE_NAME: ${{ env.BREV_E2E_INSTANCE_NAME }} TEST_SUITE: ${{ inputs.test_suite }} diff --git a/.github/workflows/e2e-script.yaml b/.github/workflows/e2e-script.yaml index 0b729fead78..2071ade9887 100644 --- a/.github/workflows/e2e-script.yaml +++ b/.github/workflows/e2e-script.yaml @@ -58,7 +58,7 @@ on: type: string default: "" nvidia_api_key: - description: Pass the hosted inference source secret as the CI custom endpoint credential. + description: Pass the NVIDIA_API_KEY secret to the script. required: false type: boolean default: false @@ -78,7 +78,7 @@ on: type: boolean default: false secrets: - NVIDIA_INFERENCE_API_KEY: + NVIDIA_API_KEY: required: false BRAVE_API_KEY: required: false @@ -212,29 +212,6 @@ jobs: echo "::warning::Docker Hub login failed after 3 attempts; continuing with anonymous pulls." fi - - name: Export hosted CI inference environment - if: ${{ inputs.nvidia_api_key }} - env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} - shell: bash - run: | - set -euo pipefail - - if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - echo "::error::NVIDIA_INFERENCE_API_KEY secret is required for hosted CI inference; it is withheld for workflow_dispatch target_ref runs." >&2 - exit 1 - fi - - { - printf 'NEMOCLAW_E2E_USE_HOSTED_INFERENCE=1\n' - printf 'NEMOCLAW_PROVIDER=custom\n' - printf 'NEMOCLAW_ENDPOINT_URL=https://inference-api.nvidia.com/v1\n' - printf 'NEMOCLAW_MODEL=nvidia/nvidia/nemotron-3-super-v3\n' - printf 'NEMOCLAW_COMPAT_MODEL=nvidia/nvidia/nemotron-3-super-v3\n' - printf 'NEMOCLAW_PREFERRED_API=openai-completions\n' - printf 'COMPATIBLE_API_KEY=%s\n' "${NVIDIA_INFERENCE_API_KEY}" - } >> "$GITHUB_ENV" - - name: Run E2E script uses: ./workflow-actions/.github/actions/run-e2e-script with: @@ -248,7 +225,7 @@ jobs: env: BRAVE_API_KEY: ${{ inputs.brave_api_key && secrets.BRAVE_API_KEY || '' }} GITHUB_TOKEN: ${{ inputs.github_token && github.token || '' }} - NVIDIA_INFERENCE_API_KEY: ${{ inputs.nvidia_api_key && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ inputs.nvidia_api_key && secrets.NVIDIA_API_KEY || '' }} TELEGRAM_BOT_TOKEN_REAL: ${{ inputs.messaging_live_secrets && secrets.TELEGRAM_BOT_TOKEN_REAL || '' }} TELEGRAM_CHAT_ID_E2E: ${{ inputs.messaging_live_secrets && secrets.TELEGRAM_CHAT_ID_E2E || '' }} DISCORD_BOT_TOKEN_REAL: ${{ inputs.messaging_live_secrets && secrets.DISCORD_BOT_TOKEN_REAL || '' }} diff --git a/.github/workflows/e2e-vitest-scenarios.yaml b/.github/workflows/e2e-vitest-scenarios.yaml index a77db9295df..ac3a451cf7e 100644 --- a/.github/workflows/e2e-vitest-scenarios.yaml +++ b/.github/workflows/e2e-vitest-scenarios.yaml @@ -247,7 +247,7 @@ jobs: - name: Run Vitest live E2E scenarios env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} SCENARIO_ID: ${{ matrix.id }} run: | set -euo pipefail @@ -473,7 +473,7 @@ jobs: - name: Run skill-agent live test env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$PATH" @@ -811,7 +811,7 @@ jobs: - name: Run issue #4434 TUI unreachable inference live test env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$PATH" @@ -899,11 +899,11 @@ jobs: - name: Run credential sanitization live test # Migrated from test/e2e/test-credential-sanitization.sh. Preserves the - # same ubuntu-latest + Docker/OpenShell + NVIDIA_INFERENCE_API_KEY lane by running + # same ubuntu-latest + Docker/OpenShell + NVIDIA_API_KEY lane by running # install.sh, onboarding a real sandbox, and probing sandbox state from # Vitest while fixture redaction owns evidence logs. env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -982,17 +982,11 @@ jobs: - name: Run credential migration live test # Migrated from test/e2e/test-credential-migration.sh. This live test - # stages NVIDIA_INFERENCE_API_KEY through legacy credentials.json as the - # custom provider's COMPATIBLE_API_KEY. The hosted service behind this - # repo-scoped secret is inference-api.nvidia.com, not Build/NVIDIA - # Endpoints, so the test must exercise the compatible-provider route. + # needs NVIDIA_API_KEY only as the staged legacy credential value; it + # preserves the default NVIDIA provider/key migration path while + # pinning a lower-quota catalog model in the test fixture. env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -1175,7 +1169,7 @@ jobs: - name: Run Hermes live Vitest test env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -1225,21 +1219,21 @@ jobs: run: npm run build:cli - name: Install OpenShell - # Runs without workflow tokens, Docker credentials, or NVIDIA_INFERENCE_API_KEY. + # Runs without workflow tokens, Docker credentials, or NVIDIA_API_KEY. # scripts/install-openshell.sh pins the OpenShell version and verifies # release SHA-256 checksums before installation. env: 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 GITHUB_TOKEN bash scripts/install-openshell.sh - name: Run network-policy live test # Migrated from test/e2e/test-network-policy.sh. Free-standing anchor # for live network policy allow/deny probes; shell retirement remains # deferred to #5098 Phase 11. env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -1391,7 +1385,7 @@ jobs: # bash install.sh to preserve installer/onboard fidelity, then probes # real shields/config behavior against the live sandbox. env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -1471,11 +1465,11 @@ 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 GITHUB_TOKEN bash scripts/install-openshell.sh - name: Run OpenClaw rebuild live test env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$PATH" @@ -1566,11 +1560,11 @@ 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 GITHUB_TOKEN bash scripts/install-openshell.sh - name: Run sandbox rebuild live test env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$PATH" @@ -2068,7 +2062,7 @@ jobs: - name: Run launchable smoke live test env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -2155,7 +2149,7 @@ jobs: # sandbox inference.local completion boundaries without adding registry # or migration-ledger wiring. env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -2245,7 +2239,7 @@ jobs: # fidelity before exercising gateway restart, state survival, and live # inference.local before and after restart. env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -2378,7 +2372,7 @@ jobs: - name: Run OpenClaw TUI chat correlation live test env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail npx vitest run --project e2e-scenarios-live \ @@ -2453,7 +2447,7 @@ jobs: - name: Run Vitest gateway-guard-recovery scenario env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | set -euo pipefail # OpenShell installs to /usr/local/bin on GitHub-hosted runners diff --git a/.github/workflows/macos-e2e.yaml b/.github/workflows/macos-e2e.yaml index d3e9b5cf5db..fca322e4318 100644 --- a/.github/workflows/macos-e2e.yaml +++ b/.github/workflows/macos-e2e.yaml @@ -85,7 +85,7 @@ jobs: - name: Run macOS full E2E if: steps.docker.outputs.docker_ok == 'true' env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} GITHUB_TOKEN: ${{ github.token }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" diff --git a/.github/workflows/nightly-e2e.yaml b/.github/workflows/nightly-e2e.yaml index 98619d67d4f..b448fccf9f8 100644 --- a/.github/workflows/nightly-e2e.yaml +++ b/.github/workflows/nightly-e2e.yaml @@ -3,9 +3,9 @@ # # Nightly E2E tests: # -# cloud-e2e Hosted inference (OpenAI-compatible endpoint) on ubuntu-latest. +# cloud-e2e Cloud inference (NVIDIA Endpoint API) on ubuntu-latest. # agent-turn-latency-e2e Times one real OpenClaw turn and one real Hermes -# turn through the configured hosted inference model. +# turn through the configured NVIDIA Build model. # messaging-providers-e2e Validates messaging credential provider/placeholder/L7-proxy chain # for Telegram + Discord + Slack. Uses fake tokens. Slack additionally # exercises OpenShell provider-shaped alias resolution (#2085 follow-up). @@ -99,10 +99,10 @@ # Runs directly on the runner (not inside Docker) because OpenShell bootstraps # a K3s cluster inside a privileged Docker container — nesting would break networking. # -# NVIDIA_INFERENCE_API_KEY for hosted CI inference: +# NVIDIA_API_KEY for cloud-e2e: # - Repository secret: Settings → Secrets and variables → Actions → Repository secrets. # - Environment secret: only available if the job sets `environment: `. -# (Storing the key under Environments / NVIDIA_INFERENCE_API_KEY without `environment:` here leaves the +# (Storing the key under Environments / NVIDIA_API_KEY without `environment:` here leaves the # variable empty in the job — repository secrets and environment secrets are separate.) # Only runs on schedule and manual dispatch — never on PRs (secret protection). @@ -206,7 +206,7 @@ jobs: nvidia_api_key: true github_token: true secrets: &nightly-e2e-default-secrets - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} BRAVE_API_KEY: ${{ secrets.BRAVE_API_KEY }} DOCKERHUB_USERNAME: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.DOCKERHUB_USERNAME || '' }} DOCKERHUB_TOKEN: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.DOCKERHUB_TOKEN || '' }} @@ -274,7 +274,7 @@ jobs: /tmp/nemoclaw-e2e-openclaw-turn-latency-install.log /tmp/nemoclaw-e2e-hermes-turn-latency-install.log /tmp/nemoclaw-e2e-agent-turn-latency.json - env_json: '{"NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE":"1","NEMOCLAW_NON_INTERACTIVE":"1","NEMOCLAW_RECREATE_SANDBOX":"1"}' + env_json: '{"NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE":"1","NEMOCLAW_NON_INTERACTIVE":"1","NEMOCLAW_RECREATE_SANDBOX":"1","NEMOCLAW_TURN_LATENCY_MODEL":"nvidia/nemotron-3-ultra-550b-a55b"}' nvidia_api_key: true secrets: *nightly-e2e-default-secrets skill-agent-e2e: @@ -379,7 +379,7 @@ jobs: github_token: true messaging_live_secrets: ${{ github.event_name != 'workflow_dispatch' || inputs.target_ref == '' }} secrets: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} BRAVE_API_KEY: ${{ secrets.BRAVE_API_KEY }} DOCKERHUB_USERNAME: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.DOCKERHUB_USERNAME || '' }} DOCKERHUB_TOKEN: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.DOCKERHUB_TOKEN || '' }} @@ -464,14 +464,7 @@ jobs: - name: Run OpenClaw TUI chat correlation E2E test env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_RECREATE_SANDBOX: "1" @@ -501,7 +494,7 @@ jobs: uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: # This privileged proof mutates host firewall state and receives - # NVIDIA_INFERENCE_API_KEY. Keep the runner script from the trusted workflow ref; + # NVIDIA_API_KEY. Keep the runner script from the trusted workflow ref; # the product under test is selected separately via # NEMOCLAW_PUBLIC_INSTALL_REF. ref: ${{ github.ref }} @@ -540,14 +533,7 @@ jobs: - name: "Run issue #4434 TUI unreachable inference E2E test" env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_ISSUE_4434_LIVE: "1" NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" @@ -561,19 +547,19 @@ jobs: if: failure() shell: bash env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} GITHUB_TOKEN: ${{ github.token }} run: | set -euo pipefail for file in /tmp/nemoclaw-e2e-issue-4434-install.log /tmp/nemoclaw-issue-4434.*; do [ -f "$file" ] || continue - if [ -n "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - perl -0pi -e 's/\Q$ENV{NVIDIA_INFERENCE_API_KEY}\E/[REDACTED_NVIDIA_INFERENCE_API_KEY]/g' "$file" + if [ -n "${NVIDIA_API_KEY:-}" ]; then + perl -0pi -e 's/\Q$ENV{NVIDIA_API_KEY}\E/[REDACTED_NVIDIA_API_KEY]/g' "$file" fi if [ -n "${GITHUB_TOKEN:-}" ]; then perl -0pi -e 's/\Q$ENV{GITHUB_TOKEN}\E/[REDACTED_GITHUB_TOKEN]/g' "$file" fi - perl -0pi -e 's/nvapi-[A-Za-z0-9._-]+/[REDACTED_NVIDIA_INFERENCE_API_KEY]/g; s/gh[pousr]_[A-Za-z0-9_]+/[REDACTED_GITHUB_TOKEN]/g' "$file" + perl -0pi -e 's/nvapi-[A-Za-z0-9._-]+/[REDACTED_NVIDIA_API_KEY]/g; s/gh[pousr]_[A-Za-z0-9_]+/[REDACTED_GITHUB_TOKEN]/g' "$file" done - name: "Upload issue #4434 logs on failure" @@ -714,12 +700,12 @@ jobs: # chooses a `target_ref`. Both paths are "trusted-ref": the # code reached at runtime has already passed maintainer review # or is the default branch itself. - # * `NVIDIA_INFERENCE_API_KEY` is the repo-scoped E2E credential — purposefully + # * `NVIDIA_API_KEY` is the repo-scoped E2E credential — purposefully # not a production key. It is wired only to the inference quota # allocated to this repository's E2E lane, with no IAM / billing # authority outside that quota. Treat exposure as "rotate at the # quota boundary," not "rotate at the production boundary." Audit - # trail: `gh api repos/NVIDIA/NemoClaw/actions/secrets/NVIDIA_INFERENCE_API_KEY` + # trail: `gh api repos/NVIDIA/NemoClaw/actions/secrets/NVIDIA_API_KEY` # shows the secret scope. # * The top-level `github.repository == 'NVIDIA/NemoClaw'` check # additionally guards repo-forked schedules. @@ -969,14 +955,7 @@ jobs: - name: Run token rotation E2E test env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_POLICY_TIER: "open" @@ -1267,14 +1246,7 @@ jobs: - name: Run sandbox operations E2E test env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_POLICY_TIER: "open" @@ -1568,20 +1540,11 @@ jobs: - name: Run credential migration Vitest test # Trusted-code boundary: this job runs the checked-out target ref with - # NVIDIA_INFERENCE_API_KEY because it validates live credential - # migration into the OpenShell gateway. The hosted service behind this - # repo-scoped secret is inference-api.nvidia.com, not Build/NVIDIA - # Endpoints, so the test stages it as the custom provider's - # COMPATIBLE_API_KEY. Keep checkout credentials disabled, do not pass + # NVIDIA_API_KEY because it validates live credential migration into the + # OpenShell gateway. Keep checkout credentials disabled, do not pass # GITHUB_TOKEN, and rely on reviewed/maintainer-dispatched refs. env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/vitest/credential-migration NEMOCLAW_RUN_E2E_SCENARIOS: "1" NEMOCLAW_SANDBOX_NAME: "e2e-cred-migration" @@ -1752,23 +1715,15 @@ jobs: - *target-ref-checkout - *dockerhub-auth-step - - name: Set up Node - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.0.0 - with: - node-version: 22 - cache: npm - - - name: Install root dependencies - run: npm ci --ignore-scripts - - - name: Build CLI - run: npm run build:cli - - - name: Install OpenShell CLI - run: env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh - + - name: Install NemoClaw + env: + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NEMOCLAW_NON_INTERACTIVE: "1" + NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" + run: bash install.sh --non-interactive --yes-i-accept-third-party-software - name: Run double onboard E2E test env: + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" run: | @@ -1800,27 +1755,13 @@ jobs: - *dockerhub-auth-step - name: Install NemoClaw env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" run: bash install.sh --non-interactive --yes-i-accept-third-party-software - name: Run onboard repair E2E test env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" run: | @@ -1852,27 +1793,13 @@ jobs: - *dockerhub-auth-step - name: Install NemoClaw env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" run: bash install.sh --non-interactive --yes-i-accept-third-party-software - name: Run onboard resume E2E test env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" run: | @@ -1904,27 +1831,13 @@ jobs: - *dockerhub-auth-step - name: Install NemoClaw env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" run: bash install.sh --non-interactive --yes-i-accept-third-party-software - name: Run onboard negative-path E2E test env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" run: | @@ -1957,27 +1870,13 @@ jobs: - *dockerhub-auth-step - name: Install NemoClaw env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" run: bash install.sh --non-interactive --yes-i-accept-third-party-software - name: Run runtime overrides E2E test env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" run: | @@ -2010,28 +1909,14 @@ jobs: - *dockerhub-auth-step - name: Install NemoClaw and onboard sandbox env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_SANDBOX_NAME: "e2e-test" run: bash install.sh --non-interactive --yes-i-accept-third-party-software - name: Run credential sanitization E2E test env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_SANDBOX_NAME: "e2e-test" @@ -2066,28 +1951,14 @@ jobs: - *dockerhub-auth-step - name: Install NemoClaw and onboard sandbox env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_SANDBOX_NAME: "e2e-test" run: bash install.sh --non-interactive --yes-i-accept-third-party-software - name: Run telegram injection E2E test env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_SANDBOX_NAME: "e2e-test" @@ -2160,14 +2031,7 @@ jobs: - name: Run launchable install-flow smoke test env: - NVIDIA_INFERENCE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} - NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1" - NEMOCLAW_PROVIDER: custom - NEMOCLAW_ENDPOINT_URL: https://inference-api.nvidia.com/v1 - NEMOCLAW_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_COMPAT_MODEL: nvidia/nvidia/nemotron-3-super-v3 - NEMOCLAW_PREFERRED_API: openai-completions - COMPATIBLE_API_KEY: ${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.NVIDIA_INFERENCE_API_KEY || '' }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" NEMOCLAW_SANDBOX_NAME: "e2e-launchable" @@ -2391,22 +2255,15 @@ jobs: steps: - *target-ref-checkout - *dockerhub-auth-step - - name: Set up Node - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.0.0 - with: - node-version: 22 - cache: npm - - - name: Install root dependencies - run: npm ci --ignore-scripts - - - name: Build CLI - run: npm run build:cli - - - name: Install OpenShell CLI - run: env -u DOCKER_CONFIG -u DOCKERHUB_USERNAME -u DOCKERHUB_TOKEN -u NVIDIA_INFERENCE_API_KEY -u GITHUB_TOKEN bash scripts/install-openshell.sh - + - name: Install NemoClaw + env: + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} + NEMOCLAW_NON_INTERACTIVE: "1" + NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" + run: bash install.sh --non-interactive --yes-i-accept-third-party-software - name: Run concurrent gateway ports E2E test + env: + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} run: | [ -f "$HOME/.bashrc" ] && source "$HOME/.bashrc" 2>/dev/null || true export NVM_DIR="${NVM_DIR:-$HOME/.nvm}" diff --git a/.github/workflows/regression-e2e.yaml b/.github/workflows/regression-e2e.yaml index 7180ef65820..09a48a0cabc 100644 --- a/.github/workflows/regression-e2e.yaml +++ b/.github/workflows/regression-e2e.yaml @@ -248,7 +248,7 @@ jobs: - name: Run Model Router provider-routed inference E2E test env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} NEMOCLAW_NON_INTERACTIVE: "1" NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1" run: bash test/e2e/test-model-router-provider-routed-inference.sh @@ -322,7 +322,7 @@ jobs: # `openclaw channels login --channel whatsapp` onQr callback invokes) # at the version bundled in Dockerfile.base, and asserts the pairing QR # renders compact with the NemoClaw preload and oversized without it. - # Hermetic: only needs node + npm (no Docker, GPU, or NVIDIA_INFERENCE_API_KEY). + # Hermetic: only needs node + npm (no Docker, GPU, or NVIDIA_API_KEY). whatsapp-qr-compact-e2e: needs: select_regression_jobs if: >- diff --git a/.github/workflows/wsl-e2e.yaml b/.github/workflows/wsl-e2e.yaml index 9d6bae556eb..f3b633bd959 100644 --- a/.github/workflows/wsl-e2e.yaml +++ b/.github/workflows/wsl-e2e.yaml @@ -227,13 +227,13 @@ jobs: if: steps.docker.outputs.docker_ok == 'true' shell: powershell env: - NVIDIA_INFERENCE_API_KEY: ${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }} GITHUB_TOKEN: ${{ github.token }} run: | $script = @" set -euo pipefail cd '$env:WSL_WORKDIR' - export NVIDIA_INFERENCE_API_KEY='$env:NVIDIA_INFERENCE_API_KEY' + export NVIDIA_API_KEY='$env:NVIDIA_API_KEY' export GITHUB_TOKEN='$env:GITHUB_TOKEN' export NEMOCLAW_NON_INTERACTIVE='$env:NEMOCLAW_NON_INTERACTIVE' export NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE='$env:NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE' diff --git a/agents/hermes/policy-additions.yaml b/agents/hermes/policy-additions.yaml index 0386ddef63c..6151ebc8dcb 100644 --- a/agents/hermes/policy-additions.yaml +++ b/agents/hermes/policy-additions.yaml @@ -75,6 +75,16 @@ network_policies: - allow: { method: POST, path: "/v1/embeddings" } - allow: { method: GET, path: "/v1/models" } - allow: { method: GET, path: "/v1/models/**" } + - host: inference-api.nvidia.com + port: 443 + protocol: rest + enforcement: enforce + rules: + - allow: { method: POST, path: "/v1/chat/completions" } + - allow: { method: POST, path: "/v1/completions" } + - allow: { method: POST, path: "/v1/embeddings" } + - allow: { method: GET, path: "/v1/models" } + - allow: { method: GET, path: "/v1/models/**" } binaries: - { path: /usr/local/bin/hermes } - { path: /usr/bin/python3* } diff --git a/agents/hermes/policy-permissive.yaml b/agents/hermes/policy-permissive.yaml index 55029356335..5ed6a1b2ac7 100644 --- a/agents/hermes/policy-permissive.yaml +++ b/agents/hermes/policy-permissive.yaml @@ -48,6 +48,11 @@ network_policies: protocol: rest enforcement: enforce access: full + - host: inference-api.nvidia.com + port: 443 + protocol: rest + enforcement: enforce + access: full binaries: - { path: "/**" } diff --git a/agents/openclaw/policy-permissive.yaml b/agents/openclaw/policy-permissive.yaml index 18c4f7f1f5f..19e6b193749 100644 --- a/agents/openclaw/policy-permissive.yaml +++ b/agents/openclaw/policy-permissive.yaml @@ -48,6 +48,11 @@ network_policies: protocol: rest enforcement: enforce access: full + - host: inference-api.nvidia.com + port: 443 + protocol: rest + enforcement: enforce + access: full binaries: - { path: "/**" } diff --git a/docs/_components/StarterPromptButton.tsx b/docs/_components/StarterPromptButton.tsx index 168f6543fd9..d4f6411e63b 100644 --- a/docs/_components/StarterPromptButton.tsx +++ b/docs/_components/StarterPromptButton.tsx @@ -81,7 +81,7 @@ Use this provider mapping for non-interactive setup: | User choice | \`NEMOCLAW_PROVIDER\` | Other required values | |---|---|---| -| NVIDIA Endpoints | \`build\` | \`NVIDIA_INFERENCE_API_KEY\` | +| NVIDIA Endpoints | \`build\` | \`NVIDIA_API_KEY\` | | OpenAI | \`openai\` | \`OPENAI_API_KEY\` | | Other OpenAI-compatible endpoint | \`custom\` | \`NEMOCLAW_ENDPOINT_URL\`, \`NEMOCLAW_MODEL\`, \`COMPATIBLE_API_KEY\` | | Anthropic | \`anthropic\` | \`ANTHROPIC_API_KEY\` | @@ -89,7 +89,7 @@ Use this provider mapping for non-interactive setup: | Google Gemini | \`gemini\` | \`GEMINI_API_KEY\` | | Hermes Provider | \`hermes-provider\` | Hermes-only; ask for the provider credential as documented | | Local Ollama | \`ollama\` | Optional \`NEMOCLAW_MODEL\`; set \`NEMOCLAW_YES=1\` only if I approve model download | -| Model Router | \`routed\` | \`NVIDIA_INFERENCE_API_KEY\` | +| Model Router | \`routed\` | \`NVIDIA_API_KEY\` | When you have the approved values, run the installer with the environment variables on the \`bash\` side of the pipe, not before \`curl\`. diff --git a/docs/about/release-notes.mdx b/docs/about/release-notes.mdx index 71e7e769014..389ec1c24de 100644 --- a/docs/about/release-notes.mdx +++ b/docs/about/release-notes.mdx @@ -132,7 +132,7 @@ NemoClaw v0.0.54 updates messaging activation, Windows WSL onboarding, NemoHerme - The Windows bootstrap flow waits for Ubuntu account creation before touching Docker settings, enables Docker Desktop WSL integration for the target distro, avoids changing the global WSL default distro, and adds WSL-specific Docker reachability hints during onboarding. For more information, refer to [Prepare Windows for NemoClaw](../get-started/prerequisites/windows-preparation). - Windows-host Ollama setup inside WSL now requires the Docker Desktop WSL integration path. NemoClaw still shows Windows-host Ollama options when it detects them, but labels the Docker Desktop requirement and blocks unsupported native Docker-in-WSL selections before it tries to start or install Ollama. For more information, refer to [Use a Local Inference Server](../inference/use-local-inference). - NemoHermes can expose the optional native Hermes web dashboard separately from the OpenAI-compatible API. Set `NEMOCLAW_HERMES_DASHBOARD=1` before onboarding to start and forward the dashboard on port `9119`, with `NEMOCLAW_HERMES_DASHBOARD_PORT` and `NEMOCLAW_HERMES_DASHBOARD_TUI` available for port and TUI tab control. For more information, refer to [NemoClaw Quickstart with Hermes](../../hermes/get-started/quickstart). -- Onboarding diagnostics include more copy-paste-ready recovery hints. Invalid sandbox names now include a `Try: ` line when NemoClaw can derive a valid name, and non-interactive NVIDIA Endpoints setup prints the exact `export NVIDIA_INFERENCE_API_KEY=nvapi-...` shape when the key is missing. For more information, refer to [NemoClaw CLI Commands Reference](../reference/commands). +- Onboarding diagnostics include more copy-paste-ready recovery hints. Invalid sandbox names now include a `Try: ` line when NemoClaw can derive a valid name, and non-interactive NVIDIA Endpoints setup prints the exact `export NVIDIA_API_KEY=nvapi-...` shape when the key is missing. For more information, refer to [NemoClaw CLI Commands Reference](../reference/commands). - Homebrew stays on the Linuxbrew prefix while exposing installed formula commands in sandbox shell sessions, the `/nemoclaw` slash command activates at OpenClaw startup again, Hermes rebuilds tolerate older release tarballs that lack optional UI package lockfiles, and device scope-upgrade approvals recover without being pinned to the old gateway-scoped request. For more information, refer to [Common NemoClaw Integration Policy Examples](../network-policy/integration-policy-examples). - The host-gateway allowance for OpenClaw `web_fetch` is confined to the trusted proxy path, while strict and direct paths continue to block host-gateway names. Hermes Provider onboarding skips the host-side smoke probe only for OAuth-backed setup and keeps direct validation for Nous API key setup. For more information, refer to [NemoClaw Inference Options](../inference/inference-options). @@ -328,7 +328,7 @@ NemoClaw v0.0.39 improves several day-two workflows: - `$$nemoclaw destroy` preserves the shared gateway by default unless `--cleanup-gateway` is selected. - `$$nemoclaw connect` repairs stale `inference.local` DNS proxy routes before opening the session. - Windows-host Ollama onboarding relaunches the daemon with the reachable binding after install or restart. -- Local NVIDIA NIM onboarding passes `NGC_API_KEY` or `NVIDIA_INFERENCE_API_KEY` into the managed container without putting the secret in process arguments, detects early container exits during health checks, and prints a per-GPU preflight breakdown on mixed-model hosts. +- Local NVIDIA NIM onboarding passes `NGC_API_KEY` or `NVIDIA_API_KEY` into the managed container without putting the secret in process arguments, detects early container exits during health checks, and prints a per-GPU preflight breakdown on mixed-model hosts. - The sandbox startup path strips additional Linux capabilities before and during privilege step-down. - OpenClaw workspace template files are seeded when bootstrap is skipped and the workspace is still empty. - Kimi K2.6 and related NVIDIA-hosted chat-completions paths include model-specific compatibility handling for reasoning output. diff --git a/docs/get-started/quickstart-hermes.mdx b/docs/get-started/quickstart-hermes.mdx index a9d3098b957..c3a56ce55b6 100644 --- a/docs/get-started/quickstart-hermes.mdx +++ b/docs/get-started/quickstart-hermes.mdx @@ -93,7 +93,7 @@ export NEMOCLAW_AGENT=hermes export NEMOCLAW_NON_INTERACTIVE=1 export NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 export NEMOCLAW_SANDBOX_NAME=my-hermes -export NVIDIA_INFERENCE_API_KEY= +export NVIDIA_API_KEY= curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash ``` diff --git a/docs/get-started/quickstart.mdx b/docs/get-started/quickstart.mdx index f291d6b9e08..12a8d5a8bbf 100644 --- a/docs/get-started/quickstart.mdx +++ b/docs/get-started/quickstart.mdx @@ -119,7 +119,7 @@ A configured blueprint router profile makes the Model Router option appear. Export the API key before launching the installer so the wizard does not have to ask for it. -For example, run `export NVIDIA_INFERENCE_API_KEY=` before `curl ... | bash`. +For example, run `export NVIDIA_API_KEY=` before `curl ... | bash`. If you entered a key incorrectly, refer to [Reset a Stored Credential](../manage-sandboxes/lifecycle#reset-a-stored-credential) to clear and re-enter it. @@ -131,14 +131,14 @@ For Ollama, vLLM, NIM, and compatible local servers, refer to [Use a Local Infer | Option | Use when | Credential variable | |---|---|---| -| NVIDIA Endpoints | You want hosted models from `build.nvidia.com`, including hosted Nemotron models. | `NVIDIA_INFERENCE_API_KEY` | +| NVIDIA Endpoints | You want hosted models from `build.nvidia.com`, including hosted Nemotron models. | `NVIDIA_API_KEY` | | OpenAI | You want the OpenAI API at `https://api.openai.com/v1`. | `OPENAI_API_KEY` | | Other OpenAI-compatible endpoint | You have OpenRouter, LocalAI, llama.cpp, vLLM, NIM, SGLang, an enterprise gateway, or another `/v1/chat/completions` endpoint. | `COMPATIBLE_API_KEY` | | Anthropic | You want the Anthropic Messages API. | `ANTHROPIC_API_KEY` | | Other Anthropic-compatible endpoint | You have a Claude proxy, Bedrock-compatible gateway, or self-hosted `/v1/messages` endpoint. | `COMPATIBLE_ANTHROPIC_API_KEY` | | Google Gemini | You want Google's OpenAI-compatible Gemini endpoint. | `GEMINI_API_KEY` | | Local Ollama | You want a host-local Ollama model. | None | -| Model Router | You want NemoClaw to start the host-side model router. | `NVIDIA_INFERENCE_API_KEY` | +| Model Router | You want NemoClaw to start the host-side model router. | `NVIDIA_API_KEY` | Export the relevant key before launching the installer when possible. If your compatible endpoint does not require authentication, set its credential variable to any non-empty placeholder. diff --git a/docs/inference/inference-options.mdx b/docs/inference/inference-options.mdx index ec5c09cf6cd..fc21df96b76 100644 --- a/docs/inference/inference-options.mdx +++ b/docs/inference/inference-options.mdx @@ -64,7 +64,7 @@ The managed install/start vLLM entry appears by default on DGX Spark and DGX Sta | Option | Description | Curated models | |--------|-------------|----------------| -| NVIDIA Endpoints | Routes to models hosted on [build.nvidia.com](https://build.nvidia.com). You can also enter any model ID from the catalog. Set `NVIDIA_INFERENCE_API_KEY`. | Nemotron 3 Super 120B, Nemotron 3 Ultra 550B, GLM-5.1, MiniMax M2.7, GPT-OSS 120B, DeepSeek V4 Pro | +| NVIDIA Endpoints | Routes to models hosted on [build.nvidia.com](https://build.nvidia.com). You can also enter any model ID from the catalog. Set `NVIDIA_API_KEY`. | Nemotron 3 Super 120B, Nemotron 3 Ultra 550B, GLM-5.1, MiniMax M2.7, GPT-OSS 120B, DeepSeek V4 Pro | | OpenAI | Routes to the OpenAI API. Set `OPENAI_API_KEY`. | `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.4-nano`, `gpt-5.4-pro-2026-03-05` | | Other OpenAI-compatible endpoint | Routes to any server that implements `/v1/chat/completions`. NemoClaw uses `/v1/chat/completions` at runtime by default; set `NEMOCLAW_PREFERRED_API=openai-responses` to allow `/v1/responses` for proxies that implement it, such as some llama.cpp builds. The wizard prompts for a base URL and model name. Works with OpenRouter, LocalAI, llama.cpp, or any compatible proxy. When you enable Telegram messaging, onboarding also runs a bounded sandbox-side smoke check through `https://inference.local/v1/chat/completions`. Set `COMPATIBLE_API_KEY`. | You provide the model name. | | Anthropic | Routes to the Anthropic Messages API. Set `ANTHROPIC_API_KEY`. | `claude-sonnet-4-6`, `claude-haiku-4-5`, `claude-opus-4-6` | @@ -109,12 +109,12 @@ models: - name: nano litellm_model: "openai/nvidia/nvidia/Nemotron-3-Nano-30B-A3B" cost_per_m_input_tokens: 0.05 - api_base: "https://integrate.api.nvidia.com" + api_base: "https://inference-api.nvidia.com" - name: super litellm_model: "openai/nvidia/nvidia/nemotron-3-super-v3" cost_per_m_input_tokens: 0.10 - api_base: "https://integrate.api.nvidia.com" + api_base: "https://inference-api.nvidia.com" ``` The `tolerance` parameter controls the accuracy-cost tradeoff. @@ -138,7 +138,7 @@ The sandbox never sees raw API keys. To use the router in scripted setup, set: ```bash -NEMOCLAW_PROVIDER=routed NVIDIA_INFERENCE_API_KEY= $$nemoclaw onboard --non-interactive +NEMOCLAW_PROVIDER=routed NVIDIA_API_KEY= $$nemoclaw onboard --non-interactive ``` ### Host Python Requirement @@ -182,7 +182,7 @@ For setup instructions, refer to [Use a Local Inference Server](use-local-infere NemoClaw validates the selected provider and model before creating the sandbox. If credential validation fails, the wizard asks whether to re-enter the API key, choose a different provider, retry, or exit. The wizard retries transient upstream validation failures before it reports a provider failure. -The `nvapi-` prefix check applies only to `NVIDIA_INFERENCE_API_KEY`. +The `nvapi-` prefix check applies only to `NVIDIA_API_KEY`. Other provider credentials, such as `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, and compatible endpoint keys, use provider-aware validation during retry. | Provider type | Validation method | @@ -415,7 +415,7 @@ NVIDIA hosts NIM container images on `nvcr.io`, and `docker pull` requires NGC r If Docker is not already logged in to `nvcr.io`, onboard prompts for an [NGC API key](https://org.ngc.nvidia.com/setup/api-key) and runs `docker login nvcr.io` over `--password-stdin` so the key is never written to disk or shell history. The prompt masks the key during input and retries one time on a bad key before failing. In non-interactive mode, onboard exits with login instructions if Docker is not already authenticated; run `docker login nvcr.io` yourself, then re-run `$$nemoclaw onboard --non-interactive`. -If `NGC_API_KEY` or `NVIDIA_INFERENCE_API_KEY` is already exported, NemoClaw passes it into the managed NIM container through the process environment instead of command-line arguments. +If `NGC_API_KEY` or `NVIDIA_API_KEY` is already exported, NemoClaw passes it into the managed NIM container through the process environment instead of command-line arguments. If the NIM container exits before the health endpoint becomes ready, onboarding stops early and prints the last container log lines. After NIM becomes healthy, NemoClaw reads `/v1/models` and uses the served model id for validation when it differs from the catalog name. Unsafe served ids are rejected instead of being written into the sandbox config. diff --git a/docs/network-policy/approve-network-requests.mdx b/docs/network-policy/approve-network-requests.mdx index f311709b9e8..4766a54db9f 100644 --- a/docs/network-policy/approve-network-requests.mdx +++ b/docs/network-policy/approve-network-requests.mdx @@ -64,8 +64,7 @@ From the NemoClaw repository root, run the walkthrough script after you have onb ``` This script opens a split tmux session with the TUI on the left and the agent on the right. -The walkthrough requires tmux and the `NVIDIA_INFERENCE_API_KEY` environment variable. -It assumes an existing sandbox to attach to. +The walkthrough requires tmux and the `NVIDIA_API_KEY` environment variable, and it assumes an existing sandbox to attach to. ## Related Topics diff --git a/docs/reference/network-policies.mdx b/docs/reference/network-policies.mdx index 4fb8c04be42..d92916384d6 100644 --- a/docs/reference/network-policies.mdx +++ b/docs/reference/network-policies.mdx @@ -41,7 +41,7 @@ The following endpoint groups are allowed by default: | Policy | Endpoints | Binaries | Rules | | --- | --- | --- | --- | -| `nvidia` | `integrate.api.nvidia.com:443` | `/usr/local/bin/openclaw` | POST to inference and embedding paths, GET to model listings | +| `nvidia` | `integrate.api.nvidia.com:443`, `inference-api.nvidia.com:443` | `/usr/local/bin/openclaw` | POST to inference and embedding paths, GET to model listings | | `clawhub` | `clawhub.ai:443` | `/usr/local/bin/openclaw`, `/usr/local/bin/node` | GET, POST | | `openclaw_api` | `openclaw.ai:443` | `/usr/local/bin/openclaw`, `/usr/local/bin/node` | GET, POST | | `openclaw_docs` | `docs.openclaw.ai:443` | `/usr/local/bin/openclaw` | GET only | diff --git a/docs/security/credential-storage.mdx b/docs/security/credential-storage.mdx index 036a1507ba8..79297512142 100644 --- a/docs/security/credential-storage.mdx +++ b/docs/security/credential-storage.mdx @@ -53,7 +53,7 @@ That directory is created with mode `0700` and contains no credential material. When a NemoClaw command needs a credential value during a single run (for example to forward it to an `openshell provider` registration), it reads from `process.env` first. This means you can: -- Prefix any command with the credential to override the gateway-stored value: `NVIDIA_INFERENCE_API_KEY=nvapi-... $$nemoclaw onboard` +- Prefix any command with the credential to override the gateway-stored value: `NVIDIA_API_KEY=nvapi-... $$nemoclaw onboard` - Use short-lived or rotated credentials in CI by exporting them once per pipeline run - Avoid registering credentials in the gateway entirely if your environment supplies them @@ -66,7 +66,7 @@ Export the credential only when you want to create, replace, or rotate the store A typical deploy invocation looks like: ```bash -NVIDIA_INFERENCE_API_KEY=nvapi-... \ +NVIDIA_API_KEY=nvapi-... \ HF_TOKEN=hf_... \ TELEGRAM_BOT_TOKEN=... \ $$nemoclaw deploy my-instance @@ -107,7 +107,7 @@ If `~/.nemoclaw/credentials.json` remains after a rebuild or other credential lo The simplest way to replace a stored value is to rerun onboarding with the new value in your environment: ```bash -NVIDIA_INFERENCE_API_KEY=nvapi-new-value $$nemoclaw onboard +NVIDIA_API_KEY=nvapi-new-value $$nemoclaw onboard ``` To remove a credential from the gateway entirely: diff --git a/nemoclaw-blueprint/blueprint.yaml b/nemoclaw-blueprint/blueprint.yaml index 7d2437bee72..c34323bf516 100644 --- a/nemoclaw-blueprint/blueprint.yaml +++ b/nemoclaw-blueprint/blueprint.yaml @@ -62,7 +62,7 @@ components: provider_name: "nvidia-ncp" endpoint: "" model: "nvidia/nemotron-3-super-120b-a12b" - credential_env: "NVIDIA_INFERENCE_API_KEY" + credential_env: "NVIDIA_API_KEY" dynamic_endpoint: true nim-local: @@ -89,7 +89,7 @@ components: provider_name: "nvidia-router" endpoint: "http://localhost:4000/v1" model: "nvidia-routed" - credential_env: "NVIDIA_INFERENCE_API_KEY" + credential_env: "NVIDIA_API_KEY" timeout_secs: 180 router: diff --git a/nemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml b/nemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml index b0915b2b70c..a85ab6d8c6f 100644 --- a/nemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml +++ b/nemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml @@ -54,6 +54,11 @@ network_policies: protocol: rest enforcement: enforce access: full + - host: inference-api.nvidia.com + port: 443 + protocol: rest + enforcement: enforce + access: full binaries: - { path: "/**" } diff --git a/nemoclaw-blueprint/policies/openclaw-sandbox.yaml b/nemoclaw-blueprint/policies/openclaw-sandbox.yaml index 06e725e3c7d..bde10f96706 100644 --- a/nemoclaw-blueprint/policies/openclaw-sandbox.yaml +++ b/nemoclaw-blueprint/policies/openclaw-sandbox.yaml @@ -83,6 +83,16 @@ network_policies: - allow: { method: POST, path: "/v1/embeddings" } - allow: { method: GET, path: "/v1/models" } - allow: { method: GET, path: "/v1/models/**" } + - host: inference-api.nvidia.com + port: 443 + protocol: rest + enforcement: enforce + rules: + - allow: { method: POST, path: "/v1/chat/completions" } + - allow: { method: POST, path: "/v1/completions" } + - allow: { method: POST, path: "/v1/embeddings" } + - allow: { method: GET, path: "/v1/models" } + - allow: { method: GET, path: "/v1/models/**" } binaries: - { path: /usr/local/bin/openclaw } diff --git a/nemoclaw/src/blueprint/runner.test.ts b/nemoclaw/src/blueprint/runner.test.ts index 40e433cb304..54cd1367c81 100644 --- a/nemoclaw/src/blueprint/runner.test.ts +++ b/nemoclaw/src/blueprint/runner.test.ts @@ -141,7 +141,7 @@ function routedBlueprint(): Record { provider_name: "nvidia-router", endpoint: "http://localhost:4000/v1", model: "routed", - credential_env: "NVIDIA_INFERENCE_API_KEY", + credential_env: "NVIDIA_API_KEY", credential_default: "router-local", timeout_secs: 180, }, @@ -1005,13 +1005,13 @@ describe("runner", () => { const prevMyApiKey = process.env.MY_API_KEY; const prevGithubToken = process.env.GITHUB_TOKEN; const prevAwsKey = process.env.AWS_ACCESS_KEY_ID; - const prevNvidiaKey = process.env.NVIDIA_INFERENCE_API_KEY; + const prevNvidiaKey = process.env.NVIDIA_API_KEY; const prevProxy = process.env.HTTPS_PROXY; const prevOsDebug = process.env.OPENSHELL_DEBUG; process.env.MY_API_KEY = "secret-key-123"; process.env.GITHUB_TOKEN = "ghp_leaked"; process.env.AWS_ACCESS_KEY_ID = "AKIA_leaked"; - process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-leaked"; + process.env.NVIDIA_API_KEY = "nvapi-leaked"; process.env.HTTPS_PROXY = "http://proxy.corp:8080"; process.env.OPENSHELL_DEBUG = "1"; try { @@ -1029,7 +1029,7 @@ describe("runner", () => { // Secrets from the parent process must NOT be present expect(subEnv).not.toHaveProperty("GITHUB_TOKEN"); expect(subEnv).not.toHaveProperty("AWS_ACCESS_KEY_ID"); - expect(subEnv).not.toHaveProperty("NVIDIA_INFERENCE_API_KEY"); + expect(subEnv).not.toHaveProperty("NVIDIA_API_KEY"); expect(subEnv).not.toHaveProperty("MY_API_KEY"); // Allowed system vars should still be present @@ -1046,8 +1046,8 @@ describe("runner", () => { else process.env.GITHUB_TOKEN = prevGithubToken; if (prevAwsKey === undefined) delete process.env.AWS_ACCESS_KEY_ID; else process.env.AWS_ACCESS_KEY_ID = prevAwsKey; - if (prevNvidiaKey === undefined) delete process.env.NVIDIA_INFERENCE_API_KEY; - else process.env.NVIDIA_INFERENCE_API_KEY = prevNvidiaKey; + if (prevNvidiaKey === undefined) delete process.env.NVIDIA_API_KEY; + else process.env.NVIDIA_API_KEY = prevNvidiaKey; if (prevProxy === undefined) delete process.env.HTTPS_PROXY; else process.env.HTTPS_PROXY = prevProxy; if (prevOsDebug === undefined) delete process.env.OPENSHELL_DEBUG; @@ -1131,7 +1131,7 @@ describe("runner", () => { }); it("passes endpoint as-is from blueprint (no rewriting)", async () => { - process.env.NVIDIA_INFERENCE_API_KEY = "test-key"; + process.env.NVIDIA_API_KEY = "test-key"; try { await actionApply("routed", routedBlueprint()); @@ -1144,7 +1144,7 @@ describe("runner", () => { ); expect(configArg).toBe("OPENAI_BASE_URL=http://localhost:4000/v1"); } finally { - delete process.env.NVIDIA_INFERENCE_API_KEY; + delete process.env.NVIDIA_API_KEY; } }); }); diff --git a/nemoclaw/src/commands/config-show.test.ts b/nemoclaw/src/commands/config-show.test.ts index c54043b7b34..12cf4884342 100644 --- a/nemoclaw/src/commands/config-show.test.ts +++ b/nemoclaw/src/commands/config-show.test.ts @@ -40,7 +40,7 @@ describe("commands/config-show", () => { ncpPartner: null, model: "nvidia/nemotron-3-super-120b-a12b", profile: "default", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", onboardedAt: "2026-04-10T14:22:00Z", }; mockedLoadOnboardConfig.mockReturnValue(config); @@ -50,7 +50,7 @@ describe("commands/config-show", () => { const result = slashConfigShow(); expect(result.text).toContain("NemoClaw Config"); expect(result.text).toContain("build (https://integrate.api.nvidia.com/v1)"); - expect(result.text).toContain("$NVIDIA_INFERENCE_API_KEY"); + expect(result.text).toContain("$NVIDIA_API_KEY"); expect(result.text).toContain("NVIDIA Endpoint API"); expect(result.text).toContain("nvidia/nemotron-3-super-120b-a12b"); expect(result.text).toContain("2026-04-10T14:22:00Z"); @@ -63,7 +63,7 @@ describe("commands/config-show", () => { ncpPartner: null, model: "nvidia/nemotron-3-super-120b-a12b", profile: "default", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", onboardedAt: "2026-04-10T14:22:00Z", }; mockedLoadOnboardConfig.mockReturnValue(config); @@ -72,7 +72,7 @@ describe("commands/config-show", () => { const result = slashConfigShow(); // Should show env var name, not the actual key value - expect(result.text).toContain("$NVIDIA_INFERENCE_API_KEY"); + expect(result.text).toContain("$NVIDIA_API_KEY"); expect(result.text).not.toContain("nvapi-"); }); @@ -83,7 +83,7 @@ describe("commands/config-show", () => { ncpPartner: "PartnerCo", model: "nvidia/nemotron-3-super-120b-a12b", profile: "default", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", onboardedAt: "2026-04-10T14:22:00Z", }; mockedLoadOnboardConfig.mockReturnValue(config); @@ -119,7 +119,7 @@ describe("commands/config-show", () => { ncpPartner: null, model: "nvidia/nemotron-3-super-120b-a12b", profile: "default", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", onboardedAt: "2026-04-10T14:22:00Z", }; mockedLoadOnboardConfig.mockReturnValue(config); diff --git a/nemoclaw/src/commands/slash.test.ts b/nemoclaw/src/commands/slash.test.ts index 2b9928886b3..fe7d402c111 100644 --- a/nemoclaw/src/commands/slash.test.ts +++ b/nemoclaw/src/commands/slash.test.ts @@ -173,7 +173,7 @@ describe("commands/slash", () => { ncpPartner: null, model: "nvidia/nemotron-3-super-120b-a12b", profile: "default", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", onboardedAt: "2026-03-01T00:00:00.000Z", }; @@ -309,7 +309,7 @@ describe("commands/slash", () => { ncpPartner: null, model: "nvidia/nemotron-3-super-120b-a12b", profile: "default", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", onboardedAt: "2026-03-01T00:00:00.000Z", }; mockedLoadOnboardConfig.mockReturnValue(config); @@ -319,7 +319,7 @@ describe("commands/slash", () => { expect(result.text).toContain("NemoClaw Onboard Status"); expect(result.text).toContain("NVIDIA Endpoint API"); expect(result.text).toContain("nvidia/nemotron-3-super-120b-a12b"); - expect(result.text).toContain("NVIDIA_INFERENCE_API_KEY"); + expect(result.text).toContain("NVIDIA_API_KEY"); }); it("includes NCP partner when set", () => { @@ -329,7 +329,7 @@ describe("commands/slash", () => { ncpPartner: "PartnerCo", model: "nvidia/nemotron-3-super-120b-a12b", profile: "default", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", onboardedAt: "2026-03-01T00:00:00.000Z", }; mockedLoadOnboardConfig.mockReturnValue(config); diff --git a/nemoclaw/src/index.ts b/nemoclaw/src/index.ts index 188259f0611..dc9f25f6222 100644 --- a/nemoclaw/src/index.ts +++ b/nemoclaw/src/index.ts @@ -282,12 +282,10 @@ function registeredProviderForConfig( activeModel: string, providerCredentialEnv: string, ): ProviderPlugin { - const isNvidiaCredential = - providerCredentialEnv === "NVIDIA_INFERENCE_API_KEY" || - providerCredentialEnv === "NVIDIA_API_KEY"; - const authLabel = isNvidiaCredential - ? `NVIDIA API Key (${providerCredentialEnv})` - : `OpenAI API Key (${providerCredentialEnv})`; + const authLabel = + providerCredentialEnv === "NVIDIA_API_KEY" + ? `NVIDIA API Key (${providerCredentialEnv})` + : `OpenAI API Key (${providerCredentialEnv})`; return { id: "inference", @@ -371,7 +369,7 @@ export default function register(api: OpenClawPluginApi): void { const bannerProvider = onboardCfg ? describeOnboardProvider(onboardCfg) : "NVIDIA Endpoints"; const bannerModel = activeModel || DEFAULT_INFERENCE_MODEL; - const providerCredentialEnv = onboardCfg?.credentialEnv ?? "NVIDIA_INFERENCE_API_KEY"; + const providerCredentialEnv = onboardCfg?.credentialEnv ?? "NVIDIA_API_KEY"; api.registerProvider(registeredProviderForConfig(activeModel, providerCredentialEnv)); // 3. Register before_tool_call hook to block secrets in memory writes (#1233) diff --git a/nemoclaw/src/lib/subprocess-env.ts b/nemoclaw/src/lib/subprocess-env.ts index 90927a186c7..de497710b5c 100644 --- a/nemoclaw/src/lib/subprocess-env.ts +++ b/nemoclaw/src/lib/subprocess-env.ts @@ -5,7 +5,7 @@ * Subprocess environment allowlist. * * Subprocesses spawned by the CLI or plugin must NOT inherit the full - * parent process.env — that leaks secrets (NVIDIA_INFERENCE_API_KEY, GITHUB_TOKEN, + * parent process.env — that leaks secrets (NVIDIA_API_KEY, GITHUB_TOKEN, * AWS_ACCESS_KEY_ID, etc.) to child processes where they can be read and * exfiltrated. Instead, only forward the categories below. * diff --git a/nemoclaw/src/onboard/config.test.ts b/nemoclaw/src/onboard/config.test.ts index c539b3b455a..9eed8ca7f2b 100644 --- a/nemoclaw/src/onboard/config.test.ts +++ b/nemoclaw/src/onboard/config.test.ts @@ -45,7 +45,7 @@ function makeConfig(overrides: Partial = {}): NemoClawOnb ncpPartner: null, model: "nvidia/nemotron-3-super-120b-a12b", profile: "default", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", onboardedAt: "2026-03-01T00:00:00.000Z", ...overrides, }; diff --git a/nemoclaw/src/register.test.ts b/nemoclaw/src/register.test.ts index ed66e916df1..acaaa733983 100644 --- a/nemoclaw/src/register.test.ts +++ b/nemoclaw/src/register.test.ts @@ -117,7 +117,7 @@ describe("plugin registration", () => { ncpPartner: null, model: "nvidia/stale-model", profile: "default", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", onboardedAt: "2026-03-01T00:00:00.000Z", }); mockedReadFileSync.mockReset(); @@ -151,7 +151,7 @@ describe("plugin registration", () => { ncpPartner: null, model: "nvidia/custom-model", profile: "default", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", onboardedAt: "2026-03-01T00:00:00.000Z", }); mockedReadFileSync.mockReset(); diff --git a/nemoclaw/src/security/secret-scanner.test.ts b/nemoclaw/src/security/secret-scanner.test.ts index f87eef71333..0c088c2038e 100644 --- a/nemoclaw/src/security/secret-scanner.test.ts +++ b/nemoclaw/src/security/secret-scanner.test.ts @@ -168,7 +168,7 @@ describe("scanForSecrets", () => { describe("multiple secrets in one content", () => { it("detects multiple different secrets", () => { - const content = `NVIDIA_INFERENCE_API_KEY=${FAKE.nvidia}\nOPENAI_KEY=${FAKE.openai}`; + const content = `NVIDIA_API_KEY=${FAKE.nvidia}\nOPENAI_KEY=${FAKE.openai}`; const matches = scanForSecrets(content); expect(matches.length).toBeGreaterThanOrEqual(2); }); diff --git a/scripts/checks/direct-credential-env.ts b/scripts/checks/direct-credential-env.ts index 2045a08164f..0d8b317f0ac 100644 --- a/scripts/checks/direct-credential-env.ts +++ b/scripts/checks/direct-credential-env.ts @@ -4,7 +4,7 @@ /** * Guards src/lib/onboard.ts against direct reads of provider credential env vars. * - * Direct `process.env.NVIDIA_INFERENCE_API_KEY`-style reads bypass credentials.json. Use + * Direct `process.env.NVIDIA_API_KEY`-style reads bypass credentials.json. Use * resolveProviderCredential() or getCredential() for credential resolution unless * a narrowly-scoped raw env check is intentional and explicitly suppressed. */ @@ -15,7 +15,6 @@ import { fileURLToPath } from "node:url"; import * as ts from "typescript"; const CREDENTIAL_ENV_KEYS = new Set([ - "NVIDIA_INFERENCE_API_KEY", "NVIDIA_API_KEY", "OPENAI_API_KEY", "ANTHROPIC_API_KEY", diff --git a/scripts/install.sh b/scripts/install.sh index f008768d27d..bbb0791a9c1 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -573,7 +573,7 @@ usage() { printf " --version, -v Print installer version and exit\n" printf " --help, -h Show this help message and exit\n\n" printf " ${C_DIM}Environment:${C_RESET}\n" - printf " NVIDIA_INFERENCE_API_KEY API key (skips credential prompt)\n" + printf " NVIDIA_API_KEY API key (skips credential prompt)\n" printf " NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 Same as --yes-i-accept-third-party-software\n" printf " NEMOCLAW_NON_INTERACTIVE=1 Same as --non-interactive\n" printf " NEMOCLAW_NON_INTERACTIVE_SUDO_MODE=prompt Allow sudo prompts during non-interactive onboarding\n" diff --git a/scripts/nemoclaw-start.sh b/scripts/nemoclaw-start.sh index 17ac1fb05b1..64abd4af84f 100755 --- a/scripts/nemoclaw-start.sh +++ b/scripts/nemoclaw-start.sh @@ -10,7 +10,7 @@ # The config hash is verified at startup to detect tampering. # # Optional env: -# NVIDIA_INFERENCE_API_KEY API key for NVIDIA-hosted inference +# NVIDIA_API_KEY API key for NVIDIA-hosted inference # CHAT_UI_URL Browser origin that will access the forwarded dashboard # NEMOCLAW_DISABLE_DEVICE_AUTH Build-time only. Set to "1" to skip device-pairing auth. # Also auto-disabled when CHAT_UI_URL is non-loopback. @@ -1741,11 +1741,7 @@ prepare_gateway_token_for_current_command() { # Write an auth profile JSON for the NVIDIA API key so the gateway can authenticate. write_auth_profile() { - if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ] && [ -n "${NVIDIA_API_KEY:-}" ]; then - export NVIDIA_INFERENCE_API_KEY="$NVIDIA_API_KEY" - fi - - if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then + if [ -z "${NVIDIA_API_KEY:-}" ]; then return fi @@ -1768,7 +1764,7 @@ json.dump({ f'{provider_key}:manual': { 'type': 'api_key', 'provider': provider_key, - 'keyRef': {'source': 'env', 'id': 'NVIDIA_INFERENCE_API_KEY'}, + 'keyRef': {'source': 'env', 'id': 'NVIDIA_API_KEY'}, 'profileId': f'{provider_key}:manual', } }, open(path, 'w')) diff --git a/scripts/smoke-macos-install.sh b/scripts/smoke-macos-install.sh index 7dcbf4c8e3e..414fb828723 100755 --- a/scripts/smoke-macos-install.sh +++ b/scripts/smoke-macos-install.sh @@ -63,7 +63,7 @@ Options: -h, --help Show this help Environment: - NVIDIA_INFERENCE_API_KEY Required for the cloud install path + NVIDIA_API_KEY Required for the cloud install path EOF } @@ -110,7 +110,7 @@ while [ $# -gt 0 ]; do esac done -[ -n "${NVIDIA_INFERENCE_API_KEY:-}" ] || fail "NVIDIA_INFERENCE_API_KEY must be set for the smoke install flow." +[ -n "${NVIDIA_API_KEY:-}" ] || fail "NVIDIA_API_KEY must be set for the smoke install flow." [ -x "$REPO_DIR/install.sh" ] || fail "install.sh not found at repo root." [ -x "$REPO_DIR/uninstall.sh" ] || fail "uninstall.sh not found at repo root." diff --git a/scripts/walkthrough.sh b/scripts/walkthrough.sh index 02c1b2c5167..3a02ec6381b 100755 --- a/scripts/walkthrough.sh +++ b/scripts/walkthrough.sh @@ -14,7 +14,7 @@ # # Prerequisites: # - NemoClaw setup complete (nemoclaw onboard) -# - NVIDIA_INFERENCE_API_KEY in environment +# - NVIDIA_API_KEY in environment # # Suggested prompts that trigger the approval flow: # @@ -37,14 +37,14 @@ # # Terminal 2 (Agent): # openshell sandbox connect nemoclaw -# export NVIDIA_INFERENCE_API_KEY=nvapi-... +# export NVIDIA_API_KEY=nvapi-... # nemoclaw-start # openclaw agent --agent main --local --session-id live set -euo pipefail -[ -n "${NVIDIA_INFERENCE_API_KEY:-}" ] || { - echo "NVIDIA_INFERENCE_API_KEY required" +[ -n "${NVIDIA_API_KEY:-}" ] || { + echo "NVIDIA_API_KEY required" exit 1 } @@ -85,7 +85,7 @@ tmux kill-session -t "$SESSION" 2>/dev/null || true tmux new-session -d -s "$SESSION" -x 200 -y 50 "openshell term" # Split right pane for the agent -# NVIDIA_INFERENCE_API_KEY is not needed inside the sandbox — inference is proxied +# NVIDIA_API_KEY is not needed inside the sandbox — inference is proxied # through the OpenShell gateway which injects credentials server-side. tmux split-window -h -t "$SESSION" \ "openshell sandbox connect nemoclaw -- bash -c 'nemoclaw-start openclaw agent --agent main --local --session-id live'" diff --git a/src/commands/sandbox/config/rotate-token.ts b/src/commands/sandbox/config/rotate-token.ts index 3162aece6a1..544857b967d 100644 --- a/src/commands/sandbox/config/rotate-token.ts +++ b/src/commands/sandbox/config/rotate-token.ts @@ -22,7 +22,7 @@ export default class SandboxConfigRotateTokenCommand extends NemoClawCommand { static usage = [" [--from-env ] [--stdin]"]; static examples = [ "<%= config.bin %> sandbox config rotate-token alpha", - "<%= config.bin %> sandbox config rotate-token alpha --from-env NVIDIA_INFERENCE_API_KEY", + "<%= config.bin %> sandbox config rotate-token alpha --from-env NVIDIA_API_KEY", ]; static args = { sandboxName: sandboxNameArg, diff --git a/src/lib/actions/dev/npm-link-or-shim.test.ts b/src/lib/actions/dev/npm-link-or-shim.test.ts index 94948191083..78329802ac0 100644 --- a/src/lib/actions/dev/npm-link-or-shim.test.ts +++ b/src/lib/actions/dev/npm-link-or-shim.test.ts @@ -87,7 +87,7 @@ describe("runNpmLinkOrShim", () => { commandPath: () => process.execPath, logError: (message) => errors.push(message), run: failingNpm( - `npm failed in ${repoDir} under ${homeDir}\nNVIDIA_INFERENCE_API_KEY=${token}\nAuthorization: Bearer ${token}\n`, + `npm failed in ${repoDir} under ${homeDir}\nNVIDIA_API_KEY=${token}\nAuthorization: Bearer ${token}\n`, ), }, ); @@ -97,7 +97,7 @@ describe("runNpmLinkOrShim", () => { expect(logOutput).toContain("npm link failed"); expect(logOutput).toContain(""); expect(logOutput).toContain("~"); - expect(logOutput).toContain("NVIDIA_INFERENCE_API_KEY=[REDACTED]"); + expect(logOutput).toContain("NVIDIA_API_KEY=[REDACTED]"); expect(logOutput).toContain("Bearer [REDACTED]"); expect(logOutput).not.toContain(homeDir); expect(logOutput).not.toContain(repoDir); diff --git a/src/lib/credentials/store.ts b/src/lib/credentials/store.ts index 6758ff23102..8464633e7cc 100644 --- a/src/lib/credentials/store.ts +++ b/src/lib/credentials/store.ts @@ -31,7 +31,6 @@ export type CredentialPromptIntent = // Exported so tests can import the same source-of-truth list and stay in // sync without a second hand-maintained copy. export const KNOWN_CREDENTIAL_ENV_KEYS: readonly string[] = [ - "NVIDIA_INFERENCE_API_KEY", "NVIDIA_API_KEY", "OPENAI_API_KEY", "ANTHROPIC_API_KEY", @@ -50,10 +49,6 @@ export const KNOWN_CREDENTIAL_ENV_KEYS: readonly string[] = [ "WECHAT_BOT_TOKEN", ]; -const LEGACY_CREDENTIAL_ENV_ALIASES: Partial> = { - NVIDIA_INFERENCE_API_KEY: ["NVIDIA_API_KEY"], -}; - // Hard upper bound on the legacy credentials.json size we are willing to // read into memory. The largest realistic credential set NemoClaw has ever // shipped is well under 1 KiB; the cap exists purely so an attacker who @@ -187,14 +182,6 @@ export function getCredential(key: string): string | null { return normalized || null; } -function getLegacyCredentialAlias(envName: string): string | null { - for (const alias of LEGACY_CREDENTIAL_ENV_ALIASES[envName] ?? []) { - const value = getCredential(alias); - if (value) return value; - } - return null; -} - /** * Canonical entry point for provider credential resolution (PR #2306). * Resolves the credential for `envName` from `process.env`, falling back @@ -215,10 +202,10 @@ function getLegacyCredentialAlias(envName: string): string | null { * guard inside the staging helper itself. */ export function resolveProviderCredential(envName: string): string | null { - let value = getCredential(envName) || getLegacyCredentialAlias(envName); + let value = getCredential(envName); if (!value) { stageLegacyCredentialsToEnv(); - value = getCredential(envName) || getLegacyCredentialAlias(envName); + value = getCredential(envName); } if (value) { process.env[envName] = value; @@ -697,17 +684,15 @@ export async function readCredentialPrompt( } /** - * Ensure `NVIDIA_INFERENCE_API_KEY` is staged for this process. Returns immediately + * Ensure `NVIDIA_API_KEY` is staged for this process. Returns immediately * if it is already in env, otherwise prompts interactively (validating * the `nvapi-` prefix) and stages the result. Onboarding registers the * value with the OpenShell gateway later in the flow. */ export async function ensureApiKey(): Promise { - let key = - getCredential("NVIDIA_INFERENCE_API_KEY") || - getLegacyCredentialAlias("NVIDIA_INFERENCE_API_KEY"); + let key = getCredential("NVIDIA_API_KEY"); if (key) { - process.env.NVIDIA_INFERENCE_API_KEY = key; + process.env.NVIDIA_API_KEY = key; return { kind: "credential", value: key }; } @@ -744,8 +729,8 @@ export async function ensureApiKey(): Promise { break; } - saveCredential("NVIDIA_INFERENCE_API_KEY", key); - process.env.NVIDIA_INFERENCE_API_KEY = key; + saveCredential("NVIDIA_API_KEY", key); + process.env.NVIDIA_API_KEY = key; console.log(""); console.log(" Key staged for the OpenShell gateway. It is held in process memory only;"); console.log(" onboarding registers it with the gateway and nothing is written to disk."); diff --git a/src/lib/deploy/index.test.ts b/src/lib/deploy/index.test.ts index 1fa44189677..c4226b7a365 100644 --- a/src/lib/deploy/index.test.ts +++ b/src/lib/deploy/index.test.ts @@ -15,7 +15,7 @@ import { validateName } from "../../../dist/lib/runner"; describe("inferDeployProvider", () => { it("prefers an explicit provider override", () => { const provider = inferDeployProvider("openai", { - NVIDIA_INFERENCE_API_KEY: "nvapi-test", + NVIDIA_API_KEY: "nvapi-test", }); expect(provider).toBe("openai"); @@ -31,7 +31,7 @@ describe("inferDeployProvider", () => { it("returns null when multiple provider credentials are present without an override", () => { const provider = inferDeployProvider("", { - NVIDIA_INFERENCE_API_KEY: "nvapi-test", + NVIDIA_API_KEY: "nvapi-test", OPENAI_API_KEY: "sk-openai-test", }); @@ -49,7 +49,7 @@ describe("buildDeployEnvLines", () => { sandboxName: "my-assistant", provider: "build", credentials: { - NVIDIA_INFERENCE_API_KEY: "nvapi-test", + NVIDIA_API_KEY: "nvapi-test", }, shellQuote: (value: string) => `'${value}'`, }); @@ -60,7 +60,7 @@ describe("buildDeployEnvLines", () => { expect(envLines).toContain("NEMOCLAW_PROVIDER='build'"); expect(envLines).toContain("CHAT_UI_URL='https://chat.example.com'"); expect(envLines).toContain("NEMOCLAW_POLICY_MODE='suggested'"); - expect(envLines).toContain("NVIDIA_INFERENCE_API_KEY='nvapi-test'"); + expect(envLines).toContain("NVIDIA_API_KEY='nvapi-test'"); }); it("passes ALLOWED_CHAT_IDS through when Telegram is configured", () => { @@ -85,7 +85,7 @@ describe("buildDeployEnvLines", () => { sandboxName: "my-assistant", provider: "build", credentials: { - NVIDIA_INFERENCE_API_KEY: "nvapi-test", + NVIDIA_API_KEY: "nvapi-test", HF_TOKEN: "hf_abc123", HUGGING_FACE_HUB_TOKEN: "hf_def456", }, @@ -126,7 +126,7 @@ describe("executeDeploy", () => { NEMOCLAW_SANDBOX_NAME: "my-box", }, rootDir: "/repo/root", - getCredential: (key: string) => (key === "NVIDIA_INFERENCE_API_KEY" ? "nvapi-test" : null), + getCredential: (key: string) => (key === "NVIDIA_API_KEY" ? "nvapi-test" : null), validateName: (value: string) => value, shellQuote: (value: string) => `'${value}'`, run: (command: readonly string[]) => { diff --git a/src/lib/deploy/index.ts b/src/lib/deploy/index.ts index 65733f1a657..8133f86b2f7 100644 --- a/src/lib/deploy/index.ts +++ b/src/lib/deploy/index.ts @@ -28,7 +28,7 @@ function readCommandOutput(error: object | null, key: "stdout" | "stderr"): stri } export interface DeployCredentials { - NVIDIA_INFERENCE_API_KEY?: string | null; + NVIDIA_API_KEY?: string | null; OPENAI_API_KEY?: string | null; ANTHROPIC_API_KEY?: string | null; GEMINI_API_KEY?: string | null; @@ -117,7 +117,7 @@ export function inferDeployProvider( if (explicit) return explicit; const providerByCredential: Array<[keyof DeployCredentials, string]> = [ - ["NVIDIA_INFERENCE_API_KEY", "build"], + ["NVIDIA_API_KEY", "build"], ["OPENAI_API_KEY", "openai"], ["ANTHROPIC_API_KEY", "anthropic"], ["GEMINI_API_KEY", "gemini"], @@ -308,7 +308,7 @@ export async function executeDeploy(opts: DeployExecutionOptions): Promise exit, }); const credentials: DeployCredentials = { - NVIDIA_INFERENCE_API_KEY: getCredential("NVIDIA_INFERENCE_API_KEY"), + NVIDIA_API_KEY: getCredential("NVIDIA_API_KEY"), OPENAI_API_KEY: getCredential("OPENAI_API_KEY"), ANTHROPIC_API_KEY: getCredential("ANTHROPIC_API_KEY"), GEMINI_API_KEY: getCredential("GEMINI_API_KEY"), @@ -328,7 +328,7 @@ export async function executeDeploy(opts: DeployExecutionOptions): Promise [ " Could not determine which inference provider to configure for remote onboarding.", " Set `NEMOCLAW_PROVIDER` explicitly or provide exactly one matching provider credential.", - " Supported provider credentials: NVIDIA_INFERENCE_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, COMPATIBLE_API_KEY, COMPATIBLE_ANTHROPIC_API_KEY.", + " Supported provider credentials: NVIDIA_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, COMPATIBLE_API_KEY, COMPATIBLE_ANTHROPIC_API_KEY.", ], error, exit, diff --git a/src/lib/diagnostics/debug.test.ts b/src/lib/diagnostics/debug.test.ts index 201583f139f..054b4f64923 100644 --- a/src/lib/diagnostics/debug.test.ts +++ b/src/lib/diagnostics/debug.test.ts @@ -17,8 +17,8 @@ import { } from "../../../dist/lib/diagnostics/debug"; describe("redact", () => { - it("redacts NVIDIA_INFERENCE_API_KEY=value patterns", () => { - const key = ["NVIDIA", "INFERENCE", "API", "KEY"].join("_"); + it("redacts NVIDIA_API_KEY=value patterns", () => { + const key = ["NVIDIA", "API", "KEY"].join("_"); expect(redact(`${key}=some-value`)).toBe(`${key}=`); }); diff --git a/src/lib/inference/health.test.ts b/src/lib/inference/health.test.ts index 6e3c6f8569a..65c337aede0 100644 --- a/src/lib/inference/health.test.ts +++ b/src/lib/inference/health.test.ts @@ -206,8 +206,7 @@ describe("inference health", () => { let authConfigContent = ""; const result = probeRemoteProviderHealth("nvidia-prod", { model: "moonshotai/kimi-k2.6", - getCredentialImpl: (envName) => - envName === "NVIDIA_INFERENCE_API_KEY" ? "nvapi-test" : null, + getCredentialImpl: (envName) => (envName === "NVIDIA_API_KEY" ? "nvapi-test" : null), runCurlProbeImpl: (argv) => { capturedArgv = argv; const configIndex = argv.indexOf("--config"); @@ -269,7 +268,7 @@ describe("inference health", () => { expect(result?.ok).toBe(true); expect(result?.probed).toBe(false); expect(result?.endpoint).toBe(`${BUILD_ENDPOINT_URL}/chat/completions`); - expect(result?.detail).toContain("NVIDIA_INFERENCE_API_KEY"); + expect(result?.detail).toContain("NVIDIA_API_KEY"); expect(result?.detail).toContain("provider-level /models"); }); diff --git a/src/lib/inference/health.ts b/src/lib/inference/health.ts index 8ca7518cc12..2cdb7b70ff8 100644 --- a/src/lib/inference/health.ts +++ b/src/lib/inference/health.ts @@ -50,7 +50,7 @@ export interface ProviderHealthProbeOptions { const COMPATIBLE_PROVIDERS = new Set(["compatible-endpoint", "compatible-anthropic-endpoint"]); const NVIDIA_MANAGED_PROVIDERS = new Set(["nvidia-prod", "nvidia-nim"]); -const NVIDIA_HEALTH_CREDENTIAL_ENV = "NVIDIA_INFERENCE_API_KEY"; +const NVIDIA_HEALTH_CREDENTIAL_ENV = "NVIDIA_API_KEY"; const KIMI_K26_MODEL = "moonshotai/kimi-k2.6"; const KIMI_STATUS_CONNECT_TIMEOUT_SECONDS = "3"; const KIMI_STATUS_MAX_TIME_SECONDS = "5"; diff --git a/src/lib/inference/model-prompts.test.ts b/src/lib/inference/model-prompts.test.ts index 0d574b4ae71..05e6a5e7259 100644 --- a/src/lib/inference/model-prompts.test.ts +++ b/src/lib/inference/model-prompts.test.ts @@ -76,7 +76,7 @@ describe("model prompt helpers", () => { expect(result).toBe(BACK_TO_SELECTION); expect(errorLine).toHaveBeenCalledWith( - " NVIDIA_INFERENCE_API_KEY is required before validating a custom NVIDIA Endpoints model.", + " NVIDIA_API_KEY is required before validating a custom NVIDIA Endpoints model.", ); }); diff --git a/src/lib/inference/model-prompts.ts b/src/lib/inference/model-prompts.ts index ad173656c62..0784e626300 100644 --- a/src/lib/inference/model-prompts.ts +++ b/src/lib/inference/model-prompts.ts @@ -162,10 +162,10 @@ export async function promptCloudModel( return deps.cloudModelOptions[index].id; } - const nvidiaApiKey = deps.getCredentialFn("NVIDIA_INFERENCE_API_KEY"); + const nvidiaApiKey = deps.getCredentialFn("NVIDIA_API_KEY"); if (!nvidiaApiKey) { deps.errorLine( - " NVIDIA_INFERENCE_API_KEY is required before validating a custom NVIDIA Endpoints model.", + " NVIDIA_API_KEY is required before validating a custom NVIDIA Endpoints model.", ); return deps.backToSelection; } diff --git a/src/lib/inference/nim.test.ts b/src/lib/inference/nim.test.ts index 34591592a05..2ce0f9bb535 100644 --- a/src/lib/inference/nim.test.ts +++ b/src/lib/inference/nim.test.ts @@ -1705,9 +1705,9 @@ describe("nim", () => { }); it("falls back to process.env.NGC_API_KEY when no opts key is supplied", () => { - const prev = { ngc: process.env.NGC_API_KEY, nv: process.env.NVIDIA_INFERENCE_API_KEY }; + const prev = { ngc: process.env.NGC_API_KEY, nv: process.env.NVIDIA_API_KEY }; process.env.NGC_API_KEY = "nvapi-env-ngc"; - delete process.env.NVIDIA_INFERENCE_API_KEY; + delete process.env.NVIDIA_API_KEY; const run = vi.fn(); const { nimModule, restore } = loadNimWithMockedRunner( vi.fn(() => ""), @@ -1728,14 +1728,14 @@ describe("nim", () => { restore(); if (prev.ngc === undefined) delete process.env.NGC_API_KEY; else process.env.NGC_API_KEY = prev.ngc; - if (prev.nv !== undefined) process.env.NVIDIA_INFERENCE_API_KEY = prev.nv; + if (prev.nv !== undefined) process.env.NVIDIA_API_KEY = prev.nv; } }); - it("falls back to process.env.NVIDIA_INFERENCE_API_KEY when NGC_API_KEY is unset", () => { - const prev = { ngc: process.env.NGC_API_KEY, nv: process.env.NVIDIA_INFERENCE_API_KEY }; + it("falls back to process.env.NVIDIA_API_KEY when NGC_API_KEY is unset", () => { + const prev = { ngc: process.env.NGC_API_KEY, nv: process.env.NVIDIA_API_KEY }; delete process.env.NGC_API_KEY; - process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-env-nvidia"; + process.env.NVIDIA_API_KEY = "nvapi-env-nvidia"; const run = vi.fn(); const { nimModule, restore } = loadNimWithMockedRunner( vi.fn(() => ""), @@ -1752,15 +1752,15 @@ describe("nim", () => { } finally { restore(); if (prev.ngc !== undefined) process.env.NGC_API_KEY = prev.ngc; - if (prev.nv === undefined) delete process.env.NVIDIA_INFERENCE_API_KEY; - else process.env.NVIDIA_INFERENCE_API_KEY = prev.nv; + if (prev.nv === undefined) delete process.env.NVIDIA_API_KEY; + else process.env.NVIDIA_API_KEY = prev.nv; } }); it("omits env flags when no key is available", () => { - const prev = { ngc: process.env.NGC_API_KEY, nv: process.env.NVIDIA_INFERENCE_API_KEY }; + const prev = { ngc: process.env.NGC_API_KEY, nv: process.env.NVIDIA_API_KEY }; delete process.env.NGC_API_KEY; - delete process.env.NVIDIA_INFERENCE_API_KEY; + delete process.env.NVIDIA_API_KEY; const run = vi.fn(); const { nimModule, restore } = loadNimWithMockedRunner( vi.fn(() => ""), @@ -1779,7 +1779,7 @@ describe("nim", () => { } finally { restore(); if (prev.ngc !== undefined) process.env.NGC_API_KEY = prev.ngc; - if (prev.nv !== undefined) process.env.NVIDIA_INFERENCE_API_KEY = prev.nv; + if (prev.nv !== undefined) process.env.NVIDIA_API_KEY = prev.nv; } }); }); diff --git a/src/lib/inference/nim.ts b/src/lib/inference/nim.ts index 0767c3ebc5e..5c35fd9b4c4 100644 --- a/src/lib/inference/nim.ts +++ b/src/lib/inference/nim.ts @@ -821,18 +821,12 @@ export function startNimContainerByName( process.exit(1); } - // Resolve the NGC key: explicit arg wins, then NGC_API_KEY, then NVIDIA_INFERENCE_API_KEY, - // then the legacy NVIDIA_API_KEY alias. + // Resolve the NGC key: explicit arg wins, then NGC_API_KEY, then NVIDIA_API_KEY // (covers users who only set the NVIDIA key for cloud inference but reuse it // against NGC). Without this, NIM's in-container model-manifest download // returns "Authentication Error" and the container exits 0 a few seconds in. // Regression of #210 — see #3333. - const ngcApiKey = - opts.ngcApiKey ?? - process.env.NGC_API_KEY ?? - process.env.NVIDIA_INFERENCE_API_KEY ?? - process.env.NVIDIA_API_KEY ?? - ""; + const ngcApiKey = opts.ngcApiKey ?? process.env.NGC_API_KEY ?? process.env.NVIDIA_API_KEY ?? ""; // Use `-e KEY` (no value) so the secret never appears in argv; pass the // value through the spawn env instead. Docker reads each named var from // its own process env and forwards it to the container. diff --git a/src/lib/messaging-channel-config.test.ts b/src/lib/messaging-channel-config.test.ts index b02268d270b..50a98af1fca 100644 --- a/src/lib/messaging-channel-config.test.ts +++ b/src/lib/messaging-channel-config.test.ts @@ -33,7 +33,7 @@ describe("messaging channel config", () => { DISCORD_REQUIRE_MENTION: "0", SLACK_ALLOWED_USERS: " U01ABC2DEF3, U04GHI5JKL6 ", SLACK_ALLOWED_CHANNELS: " C012AB3CD, C987ZY6XW ", - NVIDIA_INFERENCE_API_KEY: "not-channel-config", + NVIDIA_API_KEY: "not-channel-config", }), ).toEqual({ TELEGRAM_ALLOWED_IDS: "123,456", diff --git a/src/lib/onboard.ts b/src/lib/onboard.ts index 3ad2da4e3a1..eafab2f890f 100644 --- a/src/lib/onboard.ts +++ b/src/lib/onboard.ts @@ -3636,16 +3636,17 @@ async function setupNim( hydrateCredentialEnv(credentialEnv); if (selected.key === "build") { - // Let NEMOCLAW_PROVIDER_KEY fill the NVIDIA key without overriding explicit env. + // Allow NEMOCLAW_PROVIDER_KEY as a fallback for NVIDIA_API_KEY. + // Check raw process.env first — NEMOCLAW_PROVIDER_KEY is a user-facing + // override that should take precedence before resolving from credentials.json. const _nvProviderKey = (process.env.NEMOCLAW_PROVIDER_KEY || "").trim(); - const existingNvidiaKey = ["NVIDIA_INFERENCE_API_KEY", "NVIDIA_API_KEY"] - .map((envName) => normalizeCredentialValue(process.env[envName] ?? "")) - .find(Boolean); + // check-direct-credential-env-ignore -- intentional: checking if env is already set before applying NEMOCLAW_PROVIDER_KEY override + const existingNvidiaKey = normalizeCredentialValue(process.env.NVIDIA_API_KEY ?? ""); if (_nvProviderKey && !existingNvidiaKey) { - process.env.NVIDIA_INFERENCE_API_KEY = _nvProviderKey; + process.env.NVIDIA_API_KEY = _nvProviderKey; } if (isNonInteractive()) { - const resolvedNvidiaKey = resolveProviderCredential("NVIDIA_INFERENCE_API_KEY"); + const resolvedNvidiaKey = resolveProviderCredential("NVIDIA_API_KEY"); if (resolvedNvidiaKey) { const keyError = validateNvidiaApiKeyValue(resolvedNvidiaKey); if (keyError) { @@ -4004,8 +4005,7 @@ async function setupNim( // answer falls through to startNimContainerByName's warning so // we don't double-fail in non-interactive callers. ngcApiKey = - hydrateCredentialEnv("NGC_API_KEY") || - hydrateCredentialEnv("NVIDIA_INFERENCE_API_KEY"); + hydrateCredentialEnv("NGC_API_KEY") || hydrateCredentialEnv("NVIDIA_API_KEY"); if (!ngcApiKey && !isNonInteractive()) { console.log(""); console.log(" NGC API Key required to download NIM model weights at runtime."); diff --git a/src/lib/onboard/docker-gpu-patch.test.ts b/src/lib/onboard/docker-gpu-patch.test.ts index 5e7146e31e1..b52ade24a9e 100644 --- a/src/lib/onboard/docker-gpu-patch.test.ts +++ b/src/lib/onboard/docker-gpu-patch.test.ts @@ -239,7 +239,7 @@ describe("docker-gpu-patch", () => { it("formats sanitized network diagnostics without dumping provider secrets", () => { const inspect = inspectFixture(); - inspect.Config?.Env?.push("NVIDIA_INFERENCE_API_KEY=secret"); + inspect.Config?.Env?.push("NVIDIA_API_KEY=secret"); const summary = formatDockerInspectNetworkSummary("old-container-id", inspect); @@ -248,7 +248,7 @@ describe("docker-gpu-patch", () => { expect(summary).toContain("host.openshell.internal:172.17.0.1"); expect(summary).toContain("env.OPENSHELL_ENDPOINT=http://host.openshell.internal:8080/"); expect(summary).toContain("openshell-docker: ip=172.18.0.2 gateway=172.18.0.1"); - expect(summary).not.toContain("NVIDIA_INFERENCE_API_KEY"); + expect(summary).not.toContain("NVIDIA_API_KEY"); expect(summary).not.toContain("secret"); }); diff --git a/src/lib/onboard/machine/core-flow-phases.test.ts b/src/lib/onboard/machine/core-flow-phases.test.ts index c7b262c6ece..712c92ad84d 100644 --- a/src/lib/onboard/machine/core-flow-phases.test.ts +++ b/src/lib/onboard/machine/core-flow-phases.test.ts @@ -87,7 +87,7 @@ function createPhases( model: "nvidia/test", provider: "nim", endpointUrl: "https://example.test/v1", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", hermesAuthMethod: null, hermesToolGateways: ["local"], preferredInferenceApi: "chat", @@ -196,7 +196,7 @@ describe("core onboard flow phases", () => { model: "nvidia/test", provider: "nim", endpointUrl: "https://example.test/v1", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", hermesToolGateways: ["local"], preferredInferenceApi: "chat", nimContainer: "nim-test", diff --git a/src/lib/onboard/machine/flow-phases/provider-sandbox.test.ts b/src/lib/onboard/machine/flow-phases/provider-sandbox.test.ts index 1431a4bebf8..e01dbdf54fa 100644 --- a/src/lib/onboard/machine/flow-phases/provider-sandbox.test.ts +++ b/src/lib/onboard/machine/flow-phases/provider-sandbox.test.ts @@ -43,7 +43,7 @@ describe("provider/sandbox flow phases", () => { provider: "nvidia-prod", model: "model", endpointUrl: "https://example.com/v1", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", preferredInferenceApi: "openai-responses", }, result: [advanceTo("inference"), advanceTo("sandbox")], diff --git a/src/lib/onboard/machine/handlers/finalization.test.ts b/src/lib/onboard/machine/handlers/finalization.test.ts index 254bfd4a9b8..4b42278a284 100644 --- a/src/lib/onboard/machine/handlers/finalization.test.ts +++ b/src/lib/onboard/machine/handlers/finalization.test.ts @@ -144,8 +144,8 @@ describe("handleFinalizationState", () => { await handleFinalizationState({ ...baseOptions(deps), - stagedLegacyKeys: ["NVIDIA_INFERENCE_API_KEY", "SLACK_BOT_TOKEN"], - migratedLegacyKeys: new Set(["NVIDIA_INFERENCE_API_KEY", "SLACK_BOT_TOKEN"]), + stagedLegacyKeys: ["NVIDIA_API_KEY", "SLACK_BOT_TOKEN"], + migratedLegacyKeys: new Set(["NVIDIA_API_KEY", "SLACK_BOT_TOKEN"]), }); expect(calls.removeLegacy).toHaveBeenCalledOnce(); @@ -157,8 +157,8 @@ describe("handleFinalizationState", () => { const result = await handleFinalizationState({ ...baseOptions(deps), - stagedLegacyKeys: ["NVIDIA_INFERENCE_API_KEY", "SLACK_BOT_TOKEN"], - migratedLegacyKeys: new Set(["NVIDIA_INFERENCE_API_KEY"]), + stagedLegacyKeys: ["NVIDIA_API_KEY", "SLACK_BOT_TOKEN"], + migratedLegacyKeys: new Set(["NVIDIA_API_KEY"]), }); expect(calls.removeLegacy).not.toHaveBeenCalled(); diff --git a/src/lib/onboard/machine/handlers/policies.test.ts b/src/lib/onboard/machine/handlers/policies.test.ts index 3b1889119d4..a5882446a14 100644 --- a/src/lib/onboard/machine/handlers/policies.test.ts +++ b/src/lib/onboard/machine/handlers/policies.test.ts @@ -118,7 +118,7 @@ function baseOptions( provider: "provider", model: "model", endpointUrl: "https://example.com/v1", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", selectedMessagingChannels: [], webSearchConfig: null, webSearchSupported: true, @@ -139,7 +139,7 @@ describe("handlePoliciesState", () => { provider: "provider", model: "model", endpointUrl: "https://example.com/v1", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", messagingChannels: ["telegram"], agent: null, }); diff --git a/src/lib/onboard/machine/handlers/provider-inference.test.ts b/src/lib/onboard/machine/handlers/provider-inference.test.ts index e6af5f2018e..d6d24014647 100644 --- a/src/lib/onboard/machine/handlers/provider-inference.test.ts +++ b/src/lib/onboard/machine/handlers/provider-inference.test.ts @@ -18,7 +18,7 @@ const baseSelection: ProviderSelectionResult = { model: "nvidia/test", provider: "nvidia-prod", endpointUrl: "https://integrate.api.nvidia.com/v1", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", hermesAuthMethod: null, hermesToolGateways: [], preferredInferenceApi: "openai-responses", @@ -159,12 +159,12 @@ describe("handleProviderInferenceState", () => { "nvidia/test", "nvidia-prod", "https://integrate.api.nvidia.com/v1", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", null, [], { allowToolsIncompatible: false }, ); - expect(calls.deleteEnv).toHaveBeenCalledWith("NVIDIA_INFERENCE_API_KEY"); + expect(calls.deleteEnv).toHaveBeenCalledWith("NVIDIA_API_KEY"); expect(result).toMatchObject({ sandboxName: "my-assistant", model: "nvidia/test", @@ -374,7 +374,7 @@ describe("handleProviderInferenceState", () => { provider: "nvidia-router", model: "router/model", endpointUrl: "http://localhost:4000/v1", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", }); session.steps.provider_selection.status = "complete"; const { deps, calls } = createDeps({ isInferenceRouteReady: vi.fn(() => true) }); @@ -389,7 +389,7 @@ describe("handleProviderInferenceState", () => { expect(calls.reupsertRoutedProvider).toHaveBeenCalledWith( "nvidia-router", "http://localhost:4000/v1", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); expect(calls.setupInference).not.toHaveBeenCalled(); expect(result.endpointUrl).toBe("http://host.openshell.internal:4000/v1"); diff --git a/src/lib/onboard/machine/runtime.test.ts b/src/lib/onboard/machine/runtime.test.ts index fc9d4a81ad6..cbff3a6f2ac 100644 --- a/src/lib/onboard/machine/runtime.test.ts +++ b/src/lib/onboard/machine/runtime.test.ts @@ -193,14 +193,14 @@ describe("OnboardRuntime", () => { await runtime.updateContext({ provider: "nvidia-prod", endpointUrl: "https://alice:secret@example.com/v1?token=super-secret&keep=yes#token=frag", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", apiKey: "super-secret", } as Parameters[0] & { apiKey: string }); expect(getSession()).toMatchObject({ provider: "nvidia-prod", endpointUrl: "https://example.com/v1?token=%3CREDACTED%3E&keep=yes", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", }); expect("apiKey" in getSession()).toBe(false); expect(events).toHaveLength(1); @@ -295,11 +295,11 @@ describe("OnboardRuntime", () => { it("fails non-terminal sessions with redacted failure events", async () => { const { runtime, events, getSession } = createHarness(sessionInState("gateway")); - await runtime.fail("NVIDIA_INFERENCE_API_KEY=super-secret", { step: "gateway" }); + await runtime.fail("NVIDIA_API_KEY=super-secret", { step: "gateway" }); expect(getSession()).toMatchObject({ status: "failed", - failure: { step: "gateway", message: "NVIDIA_INFERENCE_API_KEY=" }, + failure: { step: "gateway", message: "NVIDIA_API_KEY=" }, machine: { state: "failed", revision: 8 }, }); expect(events.map((event) => event.type)).toEqual(["state.failed", "onboard.failed"]); diff --git a/src/lib/onboard/missing-credential-hints.ts b/src/lib/onboard/missing-credential-hints.ts index dbe9ca1c88d..bd154491ad3 100644 --- a/src/lib/onboard/missing-credential-hints.ts +++ b/src/lib/onboard/missing-credential-hints.ts @@ -3,10 +3,10 @@ export function logMissingNvidiaApiKeyHelp(helpUrl: string | null | undefined): void { console.error( - " NVIDIA_INFERENCE_API_KEY (or NEMOCLAW_PROVIDER_KEY) is required for NVIDIA Endpoints in non-interactive mode.", + " NVIDIA_API_KEY (or NEMOCLAW_PROVIDER_KEY) is required for NVIDIA Endpoints in non-interactive mode.", ); console.error(" Set with:"); - console.error(" export NVIDIA_INFERENCE_API_KEY=nvapi-..."); + console.error(" export NVIDIA_API_KEY=nvapi-..."); if (helpUrl) { console.error(` Get a key from ${helpUrl}`); } diff --git a/src/lib/onboard/model-router.ts b/src/lib/onboard/model-router.ts index 5ff7fccf29c..e8c5faf0456 100644 --- a/src/lib/onboard/model-router.ts +++ b/src/lib/onboard/model-router.ts @@ -49,7 +49,7 @@ const MODEL_ROUTER_FINGERPRINT_IGNORED_NAMES = new Set([ "node_modules", "venv", ]); -export const DEFAULT_MODEL_ROUTER_CREDENTIAL_ENV = "NVIDIA_INFERENCE_API_KEY"; +export const DEFAULT_MODEL_ROUTER_CREDENTIAL_ENV = "NVIDIA_API_KEY"; export type BlueprintRouterConfig = { enabled?: boolean; diff --git a/src/lib/onboard/providers.test.ts b/src/lib/onboard/providers.test.ts index c7411825f8e..21849ea6c41 100644 --- a/src/lib/onboard/providers.test.ts +++ b/src/lib/onboard/providers.test.ts @@ -112,20 +112,8 @@ describe("onboard provider helpers", () => { }); it("builds update arguments", () => { - const args = buildProviderArgs( - "update", - "inference", - "openai", - "NVIDIA_INFERENCE_API_KEY", - null, - ); - expect(args).toEqual([ - "provider", - "update", - "inference", - "--credential", - "NVIDIA_INFERENCE_API_KEY", - ]); + const args = buildProviderArgs("update", "inference", "openai", "NVIDIA_API_KEY", null); + expect(args).toEqual(["provider", "update", "inference", "--credential", "NVIDIA_API_KEY"]); }); it("appends OPENAI_BASE_URL config for openai providers with a base URL", () => { @@ -133,7 +121,7 @@ describe("onboard provider helpers", () => { "create", "inference", "openai", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", "https://api.example.com/v1", ); expect(args).toContain("--config"); @@ -215,7 +203,7 @@ describe("onboard provider helpers", () => { const result = upsertProvider( "inference", "openai", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", "https://integrate.api.nvidia.com/v1", {}, (command) => { @@ -238,7 +226,7 @@ describe("onboard provider helpers", () => { const result = upsertProvider( "nvidia-prod", "openai", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", "https://integrate.api.nvidia.com/v1", {}, (command) => { @@ -277,9 +265,9 @@ describe("onboard provider helpers", () => { upsertProvider( "nvidia-prod", "openai", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", null, - { NVIDIA_INFERENCE_API_KEY: "nvapi-staged" }, + { NVIDIA_API_KEY: "nvapi-staged" }, (command) => { commands.push(command.join(" ")); return { status: 0, stdout: "", stderr: "" }; @@ -288,7 +276,7 @@ describe("onboard provider helpers", () => { expect(commands).toHaveLength(2); expect(commands[1]).toMatch(/^provider update nvidia-prod /); - expect(commands[1]).toMatch(/--credential NVIDIA_INFERENCE_API_KEY/); + expect(commands[1]).toMatch(/--credential NVIDIA_API_KEY/); }); it("stages non-nvapi NVIDIA_INFERENCE_API_KEY as hosted custom inference", () => { diff --git a/src/lib/onboard/providers.ts b/src/lib/onboard/providers.ts index 18f835cb1ba..fb96f02f27f 100644 --- a/src/lib/onboard/providers.ts +++ b/src/lib/onboard/providers.ts @@ -33,7 +33,7 @@ const REMOTE_PROVIDER_CONFIG = { label: "NVIDIA Endpoints", providerName: "nvidia-prod", providerType: "nvidia", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", endpointUrl: BUILD_ENDPOINT_URL, helpUrl: "https://build.nvidia.com/settings/api-keys", modelMode: "catalog", diff --git a/src/lib/onboard/routed-inference.test.ts b/src/lib/onboard/routed-inference.test.ts index 63353540b4d..f23509c56ce 100644 --- a/src/lib/onboard/routed-inference.test.ts +++ b/src/lib/onboard/routed-inference.test.ts @@ -12,7 +12,7 @@ vi.mock("../inference/local", () => ({ HOST_GATEWAY_URL: "http://host.openshell.internal", })); vi.mock("./model-router", () => ({ - DEFAULT_MODEL_ROUTER_CREDENTIAL_ENV: "NVIDIA_INFERENCE_API_KEY", + DEFAULT_MODEL_ROUTER_CREDENTIAL_ENV: "NVIDIA_API_KEY", loadBlueprintProfile: vi.fn(() => ({ endpoint: "http://localhost:4000/v1" })), })); @@ -76,7 +76,7 @@ describe("resolveRoutedCredentialEnv (#4564)", () => { it("uses the NVIDIA default when no profile credential env is set", () => { const loadProfile = vi.fn(() => ({ endpoint: "http://localhost:4000/v1" })) as never; - expect(resolveRoutedCredentialEnv(null, loadProfile)).toBe("NVIDIA_INFERENCE_API_KEY"); + expect(resolveRoutedCredentialEnv(null, loadProfile)).toBe("NVIDIA_API_KEY"); }); }); @@ -88,7 +88,7 @@ describe("upsertRoutedProvider (#4564)", () => { const result = upsertRoutedProvider( "nvidia-router", "http://localhost:4000/v1", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", { upsertProvider, hydrateCredentialEnv, @@ -97,13 +97,13 @@ describe("upsertRoutedProvider (#4564)", () => { expect(result.ok).toBe(true); expect(result.endpointUrl).toBe("http://host.openshell.internal:4000/v1"); - expect(result.resolvedCredentialEnv).toBe("NVIDIA_INFERENCE_API_KEY"); + expect(result.resolvedCredentialEnv).toBe("NVIDIA_API_KEY"); expect(upsertProvider).toHaveBeenCalledWith( "nvidia-router", "openai", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", "http://host.openshell.internal:4000/v1", - { NVIDIA_INFERENCE_API_KEY: "nvapi-secret" }, + { NVIDIA_API_KEY: "nvapi-secret" }, ); }); @@ -116,11 +116,11 @@ describe("upsertRoutedProvider (#4564)", () => { hydrateCredentialEnv, }); - expect(result.resolvedCredentialEnv).toBe("NVIDIA_INFERENCE_API_KEY"); + expect(result.resolvedCredentialEnv).toBe("NVIDIA_API_KEY"); expect(upsertProvider).toHaveBeenCalledWith( "nvidia-router", "openai", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", "http://host.openshell.internal:4000/v1", {}, ); @@ -133,7 +133,7 @@ describe("upsertRoutedProvider (#4564)", () => { const result = upsertRoutedProvider( "nvidia-router", "http://localhost:4000/v1", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", { upsertProvider, hydrateCredentialEnv, diff --git a/src/lib/onboard/routed-inference.ts b/src/lib/onboard/routed-inference.ts index c9e866234ad..ebdc56f9c66 100644 --- a/src/lib/onboard/routed-inference.ts +++ b/src/lib/onboard/routed-inference.ts @@ -77,8 +77,8 @@ export function normalizeRoutedEndpointUrl( * Mirrors `reconcileModelRouter()`'s resolution order so the gateway provider * is bound to the same key the router process reads: an explicit recorded env * first, then the routed blueprint profile's credential env, and only then the - * `NVIDIA_INFERENCE_API_KEY` default. Without the profile step a resume with no recorded - * credential env would re-upsert the provider against `NVIDIA_INFERENCE_API_KEY` even + * `NVIDIA_API_KEY` default. Without the profile step a resume with no recorded + * credential env would re-upsert the provider against `NVIDIA_API_KEY` even * when the routed profile defines a custom `credential_env`, breaking * inference.local (#4564). */ diff --git a/src/lib/onboard/summary.test.ts b/src/lib/onboard/summary.test.ts index 03721ab790d..35dd3845931 100644 --- a/src/lib/onboard/summary.test.ts +++ b/src/lib/onboard/summary.test.ts @@ -40,7 +40,7 @@ describe("onboard summary helpers", () => { const bareSummary = formatOnboardConfigSummary({ provider: "nvidia-prod", model: "nvidia/nemotron-3-super-120b-a12b", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", webSearchConfig: null, enabledChannels: [], sandboxName: "test", diff --git a/src/lib/onboard/validation-recovery-prompt.ts b/src/lib/onboard/validation-recovery-prompt.ts index bb39aca867e..bdf73e8d20d 100644 --- a/src/lib/onboard/validation-recovery-prompt.ts +++ b/src/lib/onboard/validation-recovery-prompt.ts @@ -97,7 +97,7 @@ export function createValidationRecoveryPromptHelpers( // Regex fallback: base64-safe token pattern (20+ chars, no spaces, mixed alphanum) /^[A-Za-z0-9_\-.]{20,}$/.test(choice); // validateNvidiaApiKeyValue is provider-aware: it only enforces the - // nvapi- prefix when credentialEnv === "NVIDIA_INFERENCE_API_KEY", so passing it + // nvapi- prefix when credentialEnv === "NVIDIA_API_KEY", so passing it // unconditionally here is safe for Anthropic/OpenAI/Gemini too. const validator = (key: string) => deps.validateNvidiaApiKeyValue(key, credentialEnv); if (looksLikeToken) { diff --git a/src/lib/security/redact.test.ts b/src/lib/security/redact.test.ts index 471b8d8d17a..f183f802b68 100644 --- a/src/lib/security/redact.test.ts +++ b/src/lib/security/redact.test.ts @@ -14,7 +14,7 @@ describe("redactForLog", () => { model: "gpt-4o", refreshToken: "refresh-token-value", }, - items: [{ name: "safe" }, { credentialEnv: "NVIDIA_INFERENCE_API_KEY" }], + items: [{ name: "safe" }, { credentialEnv: "NVIDIA_API_KEY" }], }); expect(result).toEqual({ diff --git a/src/lib/security/redact.ts b/src/lib/security/redact.ts index a1787b6c041..8503e6b8341 100644 --- a/src/lib/security/redact.ts +++ b/src/lib/security/redact.ts @@ -84,10 +84,7 @@ export function writeRedactedResult( // ── Full redaction (debug.ts style) ───────────────────────────── const FULL_REDACT_PATTERNS: [RegExp, string][] = [ - [ - /(NVIDIA_INFERENCE_API_KEY|NVIDIA_API_KEY|API_KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL|_KEY)=\S+/gi, - "$1=", - ], + [/(NVIDIA_API_KEY|API_KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL|_KEY)=\S+/gi, "$1="], ...TOKEN_PREFIX_PATTERNS.map((p): [RegExp, string] => [ new RegExp(p.source, p.flags), "", @@ -111,7 +108,7 @@ export function redactSensitiveText(value: unknown): string | null { if (typeof value !== "string") return null; let result = value .replace( - /(NVIDIA_INFERENCE_API_KEY|NVIDIA_API_KEY|NOUS_API_KEY|OPENAI_API_KEY|ANTHROPIC_API_KEY|GEMINI_API_KEY|COMPATIBLE_API_KEY|COMPATIBLE_ANTHROPIC_API_KEY|BRAVE_API_KEY|SLACK_BOT_TOKEN|SLACK_APP_TOKEN|DISCORD_BOT_TOKEN|TELEGRAM_BOT_TOKEN)=\S+/gi, + /(NVIDIA_API_KEY|NOUS_API_KEY|OPENAI_API_KEY|ANTHROPIC_API_KEY|GEMINI_API_KEY|COMPATIBLE_API_KEY|COMPATIBLE_ANTHROPIC_API_KEY|BRAVE_API_KEY|SLACK_BOT_TOKEN|SLACK_APP_TOKEN|DISCORD_BOT_TOKEN|TELEGRAM_BOT_TOKEN)=\S+/gi, "$1=", ) .replace(/Bearer\s+\S+/gi, "Bearer "); diff --git a/src/lib/state/onboard-session.test.ts b/src/lib/state/onboard-session.test.ts index c17b41ef695..935a8560893 100644 --- a/src/lib/state/onboard-session.test.ts +++ b/src/lib/state/onboard-session.test.ts @@ -320,10 +320,10 @@ describe("onboard session", () => { sandboxName: "my-assistant", endpointUrl: "https://alice:super-secret-token@example.com/v1?token=super-secret-token&keep=yes#token=super-secret-token", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", }); session.markStepSkipped("openclaw"); - session.markStepFailed("sandbox", "NVIDIA_INFERENCE_API_KEY=super-secret-token"); + session.markStepFailed("sandbox", "NVIDIA_API_KEY=super-secret-token"); session.completeSession({ provider: "ollama-local", credentialEnv: null }); expect(emitted.map((event) => event.type)).toEqual([ @@ -345,7 +345,7 @@ describe("onboard session", () => { }); expect(emitted[1].context).toMatchObject({ sandboxName: "my-assistant", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", }); expect(emitted[1].context.endpointOrigin).toBe("https://example.com"); expect(emitted[1].metadata.fields).toEqual(["sandboxName", "endpointUrl", "credentialEnv"]); @@ -353,7 +353,7 @@ describe("onboard session", () => { type: "state.failed", state: "sandbox", step: "sandbox", - error: "NVIDIA_INFERENCE_API_KEY=", + error: "NVIDIA_API_KEY=", }); expect(emitted[5]).toMatchObject({ type: "onboard.failed", state: "failed" }); expect(emitted.at(-1)).toMatchObject({ type: "onboard.completed", state: "complete" }); @@ -409,7 +409,7 @@ describe("onboard session", () => { model: "nvidia/test-model", sandboxName: "my-assistant", endpointUrl: "https://example.com/v1", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", preferredInferenceApi: "openai-completions", nimContainer: "nim-123", policyPresets: ["pypi", "npm"], @@ -426,7 +426,7 @@ describe("onboard session", () => { expect(loaded.model).toBe("nvidia/test-model"); expect(loaded.sandboxName).toBe("my-assistant"); expect(loaded.endpointUrl).toBe("https://example.com/v1"); - expect(loaded.credentialEnv).toBe("NVIDIA_INFERENCE_API_KEY"); + expect(loaded.credentialEnv).toBe("NVIDIA_API_KEY"); expect(loaded.preferredInferenceApi).toBe("openai-completions"); expect(loaded.nimContainer).toBe("nim-123"); expect(loaded.policyPresets).toEqual(["pypi", "npm"]); @@ -1043,11 +1043,11 @@ describe("onboard session", () => { session.saveSession(session.createSession()); session.markStepFailed( "inference", - "provider auth failed with NVIDIA_INFERENCE_API_KEY=nvapi-secret Bearer topsecret sk-secret-value-that-is-long-enough ghp_1234567890123456789012345", + "provider auth failed with NVIDIA_API_KEY=nvapi-secret Bearer topsecret sk-secret-value-that-is-long-enough ghp_1234567890123456789012345", ); const loaded = requireLoadedSession(session.loadSession()); - expect(loaded.steps.inference.error).toContain("NVIDIA_INFERENCE_API_KEY="); + expect(loaded.steps.inference.error).toContain("NVIDIA_API_KEY="); expect(loaded.steps.inference.error).toContain("Bearer "); expect(loaded.steps.inference.error).not.toContain("nvapi-secret"); expect(loaded.steps.inference.error).not.toContain("topsecret"); diff --git a/src/lib/state/onboard-step-mutation.test.ts b/src/lib/state/onboard-step-mutation.test.ts index 71cbb4c628d..859f7f61051 100644 --- a/src/lib/state/onboard-step-mutation.test.ts +++ b/src/lib/state/onboard-step-mutation.test.ts @@ -59,13 +59,10 @@ describe("record-only onboard step mutation", () => { expect(loaded.sandboxName).toBe("my-assistant"); expect(loaded.machine).toMatchObject({ state: "init", revision: 0 }); - session.markStepFailedRecordOnly( - "gateway", - "Gateway failed: NVIDIA_INFERENCE_API_KEY=nvapi-secret", - ); + session.markStepFailedRecordOnly("gateway", "Gateway failed: NVIDIA_API_KEY=nvapi-secret"); loaded = requireLoadedSession(session.loadSession()); expect(loaded.steps.gateway.status).toBe("failed"); - expect(loaded.steps.gateway.error).toBe("Gateway failed: NVIDIA_INFERENCE_API_KEY="); + expect(loaded.steps.gateway.error).toBe("Gateway failed: NVIDIA_API_KEY="); expect(loaded.steps.gateway.error).not.toContain("nvapi-secret"); expect(loaded.status).toBe("in_progress"); expect(loaded.failure).toBeNull(); diff --git a/src/lib/subprocess-env.ts b/src/lib/subprocess-env.ts index 9387aa5e616..0ff8b59bdc5 100644 --- a/src/lib/subprocess-env.ts +++ b/src/lib/subprocess-env.ts @@ -5,7 +5,7 @@ * Subprocess environment allowlist. * * Subprocesses spawned by the CLI or plugin must NOT inherit the full - * parent process.env — that leaks secrets (NVIDIA_INFERENCE_API_KEY, GITHUB_TOKEN, + * parent process.env — that leaks secrets (NVIDIA_API_KEY, GITHUB_TOKEN, * AWS_ACCESS_KEY_ID, etc.) to child processes where they can be read and * exfiltrated. Instead, only forward the categories below. * diff --git a/src/lib/trace.test.ts b/src/lib/trace.test.ts index 761f516037d..b020728e52a 100644 --- a/src/lib/trace.test.ts +++ b/src/lib/trace.test.ts @@ -174,11 +174,11 @@ describe("onboard trace artifacts", () => { expect( sanitizeTraceAttributes({ nested: { token: "xoxb-secret", ok: true }, - credential_env: "NVIDIA_INFERENCE_API_KEY", + credential_env: "NVIDIA_API_KEY", }), ).toMatchObject({ nested: '{"token":"","ok":true}', - credential_env: "NVIDIA_INFERENCE_API_KEY", + credential_env: "NVIDIA_API_KEY", }); }); diff --git a/src/lib/validation.test.ts b/src/lib/validation.test.ts index f4c671c84cd..6b0620ea9b5 100644 --- a/src/lib/validation.test.ts +++ b/src/lib/validation.test.ts @@ -340,7 +340,7 @@ describe("validateNvidiaApiKeyValue", () => { expect(validateNvidiaApiKeyValue("sk-abc123")).toBeTruthy(); }); - it("accepts non-nvapi keys when credentialEnv is not NVIDIA_INFERENCE_API_KEY", () => { + it("accepts non-nvapi keys when credentialEnv is not NVIDIA_API_KEY", () => { expect(validateNvidiaApiKeyValue("sk-ant-abc123", "ANTHROPIC_API_KEY")).toBeNull(); expect(validateNvidiaApiKeyValue("sk-openai-xyz", "OPENAI_API_KEY")).toBeNull(); expect(validateNvidiaApiKeyValue("AIza-gemini", "GEMINI_API_KEY")).toBeNull(); diff --git a/src/lib/validation.ts b/src/lib/validation.ts index 03ab1b3b90a..bd181f3261d 100644 --- a/src/lib/validation.ts +++ b/src/lib/validation.ts @@ -193,13 +193,12 @@ export function classifyGatewayStartFailure(output = ""): GatewayStartFailure { export function validateNvidiaApiKeyValue( key: string, - credentialEnv: string = "NVIDIA_INFERENCE_API_KEY", + credentialEnv: string = "NVIDIA_API_KEY", ): string | null { // The nvapi- prefix check is specific to NVIDIA keys; skip it for keys // from other providers (e.g. ANTHROPIC_API_KEY, OPENAI_API_KEY) so that // a valid Anthropic key is not rejected with an NVIDIA-specific error. - const isNvidia = - credentialEnv === "NVIDIA_INFERENCE_API_KEY" || credentialEnv === "NVIDIA_API_KEY"; + const isNvidia = credentialEnv === "NVIDIA_API_KEY"; if (!key) { return isNvidia ? " NVIDIA API Key is required." : " API Key is required."; } diff --git a/test/canonical-credential-resolution.test.ts b/test/canonical-credential-resolution.test.ts index 137dcefd585..9b417b5b14a 100644 --- a/test/canonical-credential-resolution.test.ts +++ b/test/canonical-credential-resolution.test.ts @@ -22,20 +22,6 @@ afterEach(() => { vi.restoreAllMocks(); vi.resetModules(); vi.unstubAllEnvs(); - for (const key of [ - "NVIDIA_INFERENCE_API_KEY", - "NVIDIA_API_KEY", - "OPENAI_API_KEY", - "ANTHROPIC_API_KEY", - "GEMINI_API_KEY", - "COMPATIBLE_API_KEY", - "COMPATIBLE_ANTHROPIC_API_KEY", - "TEST_RESOLVE_KEY", - "TEST_BOTH_KEY", - "NONEXISTENT_KEY", - ]) { - delete process.env[key]; - } for (const dir of tmpFixtures.splice(0)) { try { fs.rmSync(dir, { recursive: true, force: true }); @@ -79,11 +65,7 @@ describe("resolveProviderCredential — canonical credential resolution (#2306)" // Parametric: all 6 remote providers const providers = [ - { - name: "NVIDIA Endpoints", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", - value: "nvapi-test-resolve", - }, + { name: "NVIDIA Endpoints", credentialEnv: "NVIDIA_API_KEY", value: "nvapi-test-resolve" }, { name: "OpenAI", credentialEnv: "OPENAI_API_KEY", value: "sk-test-resolve" }, { name: "Anthropic", credentialEnv: "ANTHROPIC_API_KEY", value: "sk-ant-test-resolve" }, { name: "Google Gemini", credentialEnv: "GEMINI_API_KEY", value: "gemini-test-resolve" }, @@ -136,48 +118,20 @@ describe("resolveProviderCredential — canonical credential resolution (#2306)" }); it("stages legacy credentials through the resolver without deleting the legacy file", async () => { - const tmpDir = createFixtureHome("NVIDIA_INFERENCE_API_KEY", "nvapi-staged-only"); + const tmpDir = createFixtureHome("NVIDIA_API_KEY", "nvapi-staged-only"); const legacyFile = path.join(tmpDir, ".nemoclaw", "credentials.json"); - delete process.env["NVIDIA_INFERENCE_API_KEY"]; + delete process.env["NVIDIA_API_KEY"]; const credentials = await importCredentialsModule(tmpDir); - const result = credentials.resolveProviderCredential("NVIDIA_INFERENCE_API_KEY"); + const result = credentials.resolveProviderCredential("NVIDIA_API_KEY"); expect(result).toBe("nvapi-staged-only"); - expect(process.env["NVIDIA_INFERENCE_API_KEY"]).toBe("nvapi-staged-only"); + expect(process.env["NVIDIA_API_KEY"]).toBe("nvapi-staged-only"); // Generic lookup cannot prove every legacy value reached the gateway. // Only onboard's verified migration gate may remove this plaintext file. expect(fs.existsSync(legacyFile)).toBe(true); }); - it("maps legacy NVIDIA_API_KEY env to NVIDIA_INFERENCE_API_KEY", async () => { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-2306-env-alias-")); - tmpFixtures.push(tmpDir); - delete process.env["NVIDIA_INFERENCE_API_KEY"]; - vi.stubEnv("NVIDIA_API_KEY", "nvapi-legacy-env"); - - const credentials = await importCredentialsModule(tmpDir); - const result = credentials.resolveProviderCredential("NVIDIA_INFERENCE_API_KEY"); - - expect(result).toBe("nvapi-legacy-env"); - expect(process.env["NVIDIA_INFERENCE_API_KEY"]).toBe("nvapi-legacy-env"); - }); - - it("maps legacy NVIDIA_API_KEY credentials.json entries to NVIDIA_INFERENCE_API_KEY", async () => { - const tmpDir = createFixtureHome("NVIDIA_API_KEY", "nvapi-legacy-file"); - const legacyFile = path.join(tmpDir, ".nemoclaw", "credentials.json"); - delete process.env["NVIDIA_INFERENCE_API_KEY"]; - delete process.env["NVIDIA_API_KEY"]; - - const credentials = await importCredentialsModule(tmpDir); - const result = credentials.resolveProviderCredential("NVIDIA_INFERENCE_API_KEY"); - - expect(result).toBe("nvapi-legacy-file"); - expect(process.env["NVIDIA_INFERENCE_API_KEY"]).toBe("nvapi-legacy-file"); - expect(process.env["NVIDIA_API_KEY"]).toBe("nvapi-legacy-file"); - expect(fs.existsSync(legacyFile)).toBe(true); - }); - it("returns null when credential exists nowhere", async () => { const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-2306-missing-")); tmpFixtures.push(tmpDir); @@ -191,21 +145,21 @@ describe("resolveProviderCredential — canonical credential resolution (#2306)" }); it("normalizes whitespace and carriage returns", async () => { - // Uses an allowlisted env-key (`NVIDIA_INFERENCE_API_KEY`) so the value can + // Uses an allowlisted env-key (`NVIDIA_API_KEY`) so the value can // actually be staged from the legacy file. The post-#2554 staging // helper rejects entries that aren't in `KNOWN_CREDENTIAL_ENV_KEYS`, // which is the security guard that prevents a tampered // credentials.json from injecting unrelated env vars (e.g. `PATH`, // `NODE_OPTIONS`); the original test fixture used a fake // `TEST_WHITESPACE_KEY` that is correctly filtered out. - const tmpDir = createFixtureHome("NVIDIA_INFERENCE_API_KEY", " nvapi-whitespace-test \r\n"); + const tmpDir = createFixtureHome("NVIDIA_API_KEY", " nvapi-whitespace-test \r\n"); const credentials = await importCredentialsModule(tmpDir); - delete process.env["NVIDIA_INFERENCE_API_KEY"]; - const result = credentials.resolveProviderCredential("NVIDIA_INFERENCE_API_KEY"); + delete process.env["NVIDIA_API_KEY"]; + const result = credentials.resolveProviderCredential("NVIDIA_API_KEY"); expect(result).toBe("nvapi-whitespace-test"); - expect(process.env["NVIDIA_INFERENCE_API_KEY"]).toBe("nvapi-whitespace-test"); + expect(process.env["NVIDIA_API_KEY"]).toBe("nvapi-whitespace-test"); }); it("does not pollute process.env on null resolve", async () => { diff --git a/test/check-env-var-docs.test.ts b/test/check-env-var-docs.test.ts index 6e41bcef92d..ff587abab6b 100644 --- a/test/check-env-var-docs.test.ts +++ b/test/check-env-var-docs.test.ts @@ -49,7 +49,7 @@ describe("findEnvVarReads", () => { it.each([ "const x = process.env.PATH;", "const x = process.env.HOME;", - "const x = process.env.NVIDIA_INFERENCE_API_KEY;", + "const x = process.env.NVIDIA_API_KEY;", "const x = process.env.BRAVE_API_KEY;", "const x = process.env.TELEGRAM_BOT_TOKEN;", ])("ignores non-NEMOCLAW var %s", (code) => { diff --git a/test/cli/dispatch-basics.test.ts b/test/cli/dispatch-basics.test.ts index 301666df8f8..2447efc770f 100644 --- a/test/cli/dispatch-basics.test.ts +++ b/test/cli/dispatch-basics.test.ts @@ -66,7 +66,7 @@ describe("CLI dispatch", () => { }); it( - "start does not prompt for NVIDIA_INFERENCE_API_KEY before launching local services", + "start does not prompt for NVIDIA_API_KEY before launching local services", testTimeoutOptions(35_000), () => { const home = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-cli-start-no-key-")); @@ -107,7 +107,7 @@ describe("CLI dispatch", () => { { HOME: home, PATH: `${localBin}:${process.env.PATH || ""}`, - NVIDIA_INFERENCE_API_KEY: "", + NVIDIA_API_KEY: "", TELEGRAM_BOT_TOKEN: "", }, 30000, diff --git a/test/config-set-nested-ssrf.test.ts b/test/config-set-nested-ssrf.test.ts index dcbd581e6e3..ab809ebe0d5 100644 --- a/test/config-set-nested-ssrf.test.ts +++ b/test/config-set-nested-ssrf.test.ts @@ -577,7 +577,7 @@ describe("config set nested URL SSRF enforcement", () => { exports: { loadSession: () => ({ sandboxName: "rotate-test", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", provider: "nvidia-prod", providerType: "openai", }), @@ -611,10 +611,7 @@ describe("config set nested URL SSRF enforcement", () => { ).resolves.toBeUndefined(); expect(errorSpy).not.toHaveBeenCalled(); - expect(saveCredential).toHaveBeenCalledWith( - "NVIDIA_INFERENCE_API_KEY", - "nvapi-rotated-value", - ); + expect(saveCredential).toHaveBeenCalledWith("NVIDIA_API_KEY", "nvapi-rotated-value"); // Credential rotation is not a shields operation; its audit entry must // use the rotate_token action so it does not inflate shields_down counts // in the forensics log. @@ -622,7 +619,7 @@ describe("config set nested URL SSRF enforcement", () => { expect.objectContaining({ action: "rotate_token", sandbox: "rotate-test", - reason: "rotate-token openclaw:NVIDIA_INFERENCE_API_KEY", + reason: "rotate-token openclaw:NVIDIA_API_KEY", }), ); expect(appendAuditEntry).not.toHaveBeenCalledWith( diff --git a/test/credential-exposure.test.ts b/test/credential-exposure.test.ts index 6f05c71eeb9..d260e785571 100644 --- a/test/credential-exposure.test.ts +++ b/test/credential-exposure.test.ts @@ -3,7 +3,7 @@ // // Security regression test: credential values must never appear in --credential // CLI arguments. OpenShell reads credential values from the environment when -// only the env-var name is passed (e.g. --credential "NVIDIA_INFERENCE_API_KEY"), so +// only the env-var name is passed (e.g. --credential "NVIDIA_API_KEY"), so // there is no reason to pass the secret itself on the command line where it // would be visible in `ps aux` output. @@ -34,13 +34,13 @@ describe("credential exposure in process arguments", () => { "create", "inference", "openai", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", "https://api.example.test/v1", ); expect(args).toContain("--credential"); - expect(args).toContain("NVIDIA_INFERENCE_API_KEY"); - expect(args.join(" ")).not.toContain("NVIDIA_INFERENCE_API_KEY="); + expect(args).toContain("NVIDIA_API_KEY"); + expect(args.join(" ")).not.toContain("NVIDIA_API_KEY="); expect(args.join(" ")).not.toContain("nvapi-"); }); @@ -123,20 +123,20 @@ describe("credential exposure in process arguments", () => { it("subprocess env builder does not spread full process.env into subprocesses", () => { const previous = { - NVIDIA_INFERENCE_API_KEY: process.env.NVIDIA_INFERENCE_API_KEY, + NVIDIA_API_KEY: process.env.NVIDIA_API_KEY, PATH: process.env.PATH, }; try { - process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-secret-should-not-leak"; + process.env.NVIDIA_API_KEY = "nvapi-secret-should-not-leak"; process.env.PATH = `/tmp/nemoclaw-fake-bin:${process.env.PATH || ""}`; const env = buildCliSubprocessEnv(); - expect(env.NVIDIA_INFERENCE_API_KEY).toBeUndefined(); + expect(env.NVIDIA_API_KEY).toBeUndefined(); expect(env.PATH).toContain("/tmp/nemoclaw-fake-bin"); } finally { - if (previous.NVIDIA_INFERENCE_API_KEY === undefined) { - delete process.env.NVIDIA_INFERENCE_API_KEY; + if (previous.NVIDIA_API_KEY === undefined) { + delete process.env.NVIDIA_API_KEY; } else { - process.env.NVIDIA_INFERENCE_API_KEY = previous.NVIDIA_INFERENCE_API_KEY; + process.env.NVIDIA_API_KEY = previous.NVIDIA_API_KEY; } if (previous.PATH === undefined) { delete process.env.PATH; diff --git a/test/credentials-cli-command.test.ts b/test/credentials-cli-command.test.ts index 50e40f7e192..ad38844fd8d 100644 --- a/test/credentials-cli-command.test.ts +++ b/test/credentials-cli-command.test.ts @@ -254,10 +254,10 @@ describe("credentials oclif commands", () => { const { CredentialsResetCommand } = loadCommands(); const output = await captureOutput(() => - expectExitCode(() => CredentialsResetCommand.run(["NVIDIA_INFERENCE_API_KEY", "--yes"]), 1), + expectExitCode(() => CredentialsResetCommand.run(["NVIDIA_API_KEY", "--yes"]), 1), ); - expect(output.stderr).toContain("Could not remove provider 'NVIDIA_INFERENCE_API_KEY'."); + expect(output.stderr).toContain("Could not remove provider 'NVIDIA_API_KEY'."); expect(output.stderr).toContain("looks like a credential env variable name"); expect(output.stderr).toContain("provider not found"); }); diff --git a/test/credentials-shim.test.ts b/test/credentials-shim.test.ts index 131c622971e..17096995284 100644 --- a/test/credentials-shim.test.ts +++ b/test/credentials-shim.test.ts @@ -50,13 +50,13 @@ describe("credentials shim", () => { }); it("stages and lists allowlisted credentials from process.env only", () => { - credentials.saveCredential("NVIDIA_INFERENCE_API_KEY", " nvapi-js-shim \r\n"); + credentials.saveCredential("NVIDIA_API_KEY", " nvapi-js-shim \r\n"); credentials.saveCredential("TEST_KEY", "fixture-only"); - expect(credentials.getCredential("NVIDIA_INFERENCE_API_KEY")).toBe("nvapi-js-shim"); + expect(credentials.getCredential("NVIDIA_API_KEY")).toBe("nvapi-js-shim"); expect(credentials.getCredential("TEST_KEY")).toBe("fixture-only"); - expect(credentials.loadCredentials()).toEqual({ NVIDIA_INFERENCE_API_KEY: "nvapi-js-shim" }); - expect(credentials.listCredentialKeys()).toEqual(["NVIDIA_INFERENCE_API_KEY"]); + expect(credentials.loadCredentials()).toEqual({ NVIDIA_API_KEY: "nvapi-js-shim" }); + expect(credentials.listCredentialKeys()).toEqual(["NVIDIA_API_KEY"]); }); it("clears blank values instead of persisting them", () => { @@ -72,17 +72,15 @@ describe("credentials shim", () => { const dir = path.join(tmpDir, ".nemoclaw"); const file = path.join(dir, "credentials.json"); fs.mkdirSync(dir, { recursive: true }); - fs.writeFileSync(file, JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "nvapi-from-disk" }), { - mode: 0o600, - }); + fs.writeFileSync(file, JSON.stringify({ NVIDIA_API_KEY: "nvapi-from-disk" }), { mode: 0o600 }); - expect(credentials.getCredential("NVIDIA_INFERENCE_API_KEY")).toBe(null); + expect(credentials.getCredential("NVIDIA_API_KEY")).toBe(null); expect(credentials.loadCredentials()).toEqual({}); - credentials.saveCredential("NVIDIA_INFERENCE_API_KEY", "nvapi-from-env"); + credentials.saveCredential("NVIDIA_API_KEY", "nvapi-from-env"); expect(fs.readFileSync(file, "utf8")).toBe( - JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "nvapi-from-disk" }), + JSON.stringify({ NVIDIA_API_KEY: "nvapi-from-disk" }), ); - expect(credentials.getCredential("NVIDIA_INFERENCE_API_KEY")).toBe("nvapi-from-env"); + expect(credentials.getCredential("NVIDIA_API_KEY")).toBe("nvapi-from-env"); }); }); diff --git a/test/credentials.test.ts b/test/credentials.test.ts index 3ab41cb1bda..d9a5b28510f 100644 --- a/test/credentials.test.ts +++ b/test/credentials.test.ts @@ -54,7 +54,7 @@ async function importCredentialsModule(home: string): Promise } beforeEach(() => { - // The user's shell may export NVIDIA_INFERENCE_API_KEY etc.; the credentials module + // The user's shell may export NVIDIA_API_KEY etc.; the credentials module // now reads exclusively from process.env, so any inherited value would // contaminate every test. Start each case from a clean process env. clearTrackedEnv(); @@ -94,16 +94,16 @@ describe("host-side credential staging", () => { expect(credentials.loadCredentials()).toEqual({}); - credentials.saveCredential("NVIDIA_INFERENCE_API_KEY", " nvapi-saved-key \r\n"); + credentials.saveCredential("NVIDIA_API_KEY", " nvapi-saved-key \r\n"); // No plaintext credentials.json — the gateway is the system of record. const legacyFile = path.join(home, ".nemoclaw", "credentials.json"); expect(fs.existsSync(legacyFile)).toBe(false); - expect(process.env.NVIDIA_INFERENCE_API_KEY).toBe("nvapi-saved-key"); - expect(credentials.getCredential("NVIDIA_INFERENCE_API_KEY")).toBe("nvapi-saved-key"); - expect(credentials.loadCredentials()).toEqual({ NVIDIA_INFERENCE_API_KEY: "nvapi-saved-key" }); - expect(credentials.listCredentialKeys()).toEqual(["NVIDIA_INFERENCE_API_KEY"]); + expect(process.env.NVIDIA_API_KEY).toBe("nvapi-saved-key"); + expect(credentials.getCredential("NVIDIA_API_KEY")).toBe("nvapi-saved-key"); + expect(credentials.loadCredentials()).toEqual({ NVIDIA_API_KEY: "nvapi-saved-key" }); + expect(credentials.listCredentialKeys()).toEqual(["NVIDIA_API_KEY"]); }); it("getCredential reads only from process.env", async () => { @@ -114,15 +114,15 @@ describe("host-side credential staging", () => { fs.mkdirSync(path.join(home, ".nemoclaw"), { recursive: true }); fs.writeFileSync( path.join(home, ".nemoclaw", "credentials.json"), - JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "nvapi-from-disk" }), + JSON.stringify({ NVIDIA_API_KEY: "nvapi-from-disk" }), { mode: 0o600 }, ); const credentials = await importCredentialsModule(home); - expect(credentials.getCredential("NVIDIA_INFERENCE_API_KEY")).toBe(null); + expect(credentials.getCredential("NVIDIA_API_KEY")).toBe(null); - vi.stubEnv("NVIDIA_INFERENCE_API_KEY", " nvapi-from-env \n"); - expect(credentials.getCredential("NVIDIA_INFERENCE_API_KEY")).toBe("nvapi-from-env"); + vi.stubEnv("NVIDIA_API_KEY", " nvapi-from-env \n"); + expect(credentials.getCredential("NVIDIA_API_KEY")).toBe("nvapi-from-env"); }); it("returns null for missing or blank credential values", async () => { @@ -131,29 +131,26 @@ describe("host-side credential staging", () => { credentials.saveCredential("EMPTY_VALUE", " \r\n "); expect(credentials.getCredential("EMPTY_VALUE")).toBe(null); - expect(credentials.getCredential("NVIDIA_INFERENCE_API_KEY")).toBe(null); + expect(credentials.getCredential("NVIDIA_API_KEY")).toBe(null); }); it("deleteCredential clears the staged value without touching disk", async () => { const home = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-creds-")); const credentials = await importCredentialsModule(home); - credentials.saveCredential("NVIDIA_INFERENCE_API_KEY", "nvapi-bad-key"); + credentials.saveCredential("NVIDIA_API_KEY", "nvapi-bad-key"); credentials.saveCredential("OPENAI_API_KEY", "sk-other"); - expect(credentials.listCredentialKeys()).toEqual([ - "NVIDIA_INFERENCE_API_KEY", - "OPENAI_API_KEY", - ]); + expect(credentials.listCredentialKeys()).toEqual(["NVIDIA_API_KEY", "OPENAI_API_KEY"]); expect(fs.existsSync(path.join(home, ".nemoclaw", "credentials.json"))).toBe(false); - expect(credentials.deleteCredential("NVIDIA_INFERENCE_API_KEY")).toBe(true); - expect(credentials.getCredential("NVIDIA_INFERENCE_API_KEY")).toBe(null); + expect(credentials.deleteCredential("NVIDIA_API_KEY")).toBe(true); + expect(credentials.getCredential("NVIDIA_API_KEY")).toBe(null); expect(credentials.listCredentialKeys()).toEqual(["OPENAI_API_KEY"]); expect(credentials.getCredential("OPENAI_API_KEY")).toBe("sk-other"); // Idempotent. - expect(credentials.deleteCredential("NVIDIA_INFERENCE_API_KEY")).toBe(false); + expect(credentials.deleteCredential("NVIDIA_API_KEY")).toBe(false); }); it("deleteCredential returns false when nothing is staged", async () => { @@ -182,7 +179,7 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () fs.writeFileSync( legacyFile, JSON.stringify({ - NVIDIA_INFERENCE_API_KEY: "nvapi-legacy", + NVIDIA_API_KEY: "nvapi-legacy", TELEGRAM_BOT_TOKEN: "tg-legacy", IGNORED_NON_STRING: 42 as unknown as string, }), @@ -192,8 +189,8 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () const credentials = await importCredentialsModule(home); const staged = credentials.stageLegacyCredentialsToEnv(); - expect(staged).toEqual(["NVIDIA_INFERENCE_API_KEY", "TELEGRAM_BOT_TOKEN"]); - expect(process.env.NVIDIA_INFERENCE_API_KEY).toBe("nvapi-legacy"); + expect(staged).toEqual(["NVIDIA_API_KEY", "TELEGRAM_BOT_TOKEN"]); + expect(process.env.NVIDIA_API_KEY).toBe("nvapi-legacy"); expect(process.env.TELEGRAM_BOT_TOKEN).toBe("tg-legacy"); // The file MUST still exist after staging — it is removed only after a @@ -218,7 +215,7 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () PATH: "/attacker/bin:/usr/bin", NODE_OPTIONS: "--require=/tmp/evil.js", OPENSHELL_GATEWAY: "evil-gw", - NVIDIA_INFERENCE_API_KEY: "nvapi-legitimate", + NVIDIA_API_KEY: "nvapi-legitimate", }), { mode: 0o600 }, ); @@ -226,8 +223,8 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () const credentials = await importCredentialsModule(home); const staged = credentials.stageLegacyCredentialsToEnv(); - expect(staged).toEqual(["NVIDIA_INFERENCE_API_KEY"]); - expect(process.env.NVIDIA_INFERENCE_API_KEY).toBe("nvapi-legitimate"); + expect(staged).toEqual(["NVIDIA_API_KEY"]); + expect(process.env.NVIDIA_API_KEY).toBe("nvapi-legitimate"); expect(process.env.PATH).toBe(originalPath); expect(process.env.NODE_OPTIONS).toBe(originalNodeOptions); expect(process.env.OPENSHELL_GATEWAY).toBe(originalOpenshellGateway); @@ -245,15 +242,15 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () fs.mkdirSync(credsDir, { recursive: true }); fs.writeFileSync( path.join(credsDir, "credentials.json"), - JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "nvapi-from-disk" }), + JSON.stringify({ NVIDIA_API_KEY: "nvapi-from-disk" }), { mode: 0o600 }, ); - vi.stubEnv("NVIDIA_INFERENCE_API_KEY", "nvapi-from-env"); + vi.stubEnv("NVIDIA_API_KEY", "nvapi-from-env"); const credentials = await importCredentialsModule(home); const staged = credentials.stageLegacyCredentialsToEnv(); - expect(process.env.NVIDIA_INFERENCE_API_KEY).toBe("nvapi-from-env"); + expect(process.env.NVIDIA_API_KEY).toBe("nvapi-from-env"); // The legacy value was skipped, so it must NOT be reported as staged. // Onboard uses the staged length to decide whether to delete the file; // a false-positive entry here would unlink credentials we never @@ -268,7 +265,7 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () const home = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-creds-")); const credentials = await importCredentialsModule(home); expect(credentials.stageLegacyCredentialsToEnv()).toEqual([]); - expect(process.env.NVIDIA_INFERENCE_API_KEY).toBeUndefined(); + expect(process.env.NVIDIA_API_KEY).toBeUndefined(); }); it("treats a blank/whitespace env entry as unset and stages the legacy value", async () => { @@ -277,7 +274,7 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () fs.mkdirSync(credsDir, { recursive: true }); fs.writeFileSync( path.join(credsDir, "credentials.json"), - JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "nvapi-from-disk" }), + JSON.stringify({ NVIDIA_API_KEY: "nvapi-from-disk" }), { mode: 0o600 }, ); @@ -285,12 +282,12 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () // an empty value — must not block staging the legacy file value, or // rebuild/onboard preflight will fail with a credential the user // demonstrably has on disk. - vi.stubEnv("NVIDIA_INFERENCE_API_KEY", " "); + vi.stubEnv("NVIDIA_API_KEY", " "); const credentials = await importCredentialsModule(home); const staged = credentials.stageLegacyCredentialsToEnv(); - expect(staged).toEqual(["NVIDIA_INFERENCE_API_KEY"]); - expect(process.env.NVIDIA_INFERENCE_API_KEY).toBe("nvapi-from-disk"); + expect(staged).toEqual(["NVIDIA_API_KEY"]); + expect(process.env.NVIDIA_API_KEY).toBe("nvapi-from-disk"); }); it("stages nothing from a corrupt legacy file and leaves it untouched", async () => { @@ -304,7 +301,7 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () expect(credentials.stageLegacyCredentialsToEnv()).toEqual([]); // Corrupt input must not silently disappear — leave it for inspection. expect(fs.existsSync(legacyFile)).toBe(true); - expect(process.env.NVIDIA_INFERENCE_API_KEY).toBeUndefined(); + expect(process.env.NVIDIA_API_KEY).toBeUndefined(); }); it("refuses to migrate an oversized legacy file (DoS guard)", async () => { @@ -314,7 +311,7 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () fs.mkdirSync(credsDir, { recursive: true }); // Two megabytes of valid JSON, well above the 1 MiB sanity cap. const filler = "x".repeat(2 * 1024 * 1024); - fs.writeFileSync(legacyFile, JSON.stringify({ NVIDIA_INFERENCE_API_KEY: `nvapi-${filler}` }), { + fs.writeFileSync(legacyFile, JSON.stringify({ NVIDIA_API_KEY: `nvapi-${filler}` }), { mode: 0o600, }); @@ -323,7 +320,7 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () try { expect(credentials.stageLegacyCredentialsToEnv()).toEqual([]); - expect(process.env.NVIDIA_INFERENCE_API_KEY).toBeUndefined(); + expect(process.env.NVIDIA_API_KEY).toBeUndefined(); // File is left in place so the user can inspect or delete it. expect(fs.existsSync(legacyFile)).toBe(true); // The user gets a diagnostic on stderr explaining the refusal. @@ -343,15 +340,12 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () // A real credentials file at an unrelated path; the attacker plants a // symlink at credentials.json that points at it. const realFile = path.join(home, "real-creds.json"); - fs.writeFileSync( - realFile, - JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "nvapi-attacker-controlled" }), - ); + fs.writeFileSync(realFile, JSON.stringify({ NVIDIA_API_KEY: "nvapi-attacker-controlled" })); fs.symlinkSync(realFile, legacyFile); const credentials = await importCredentialsModule(home); expect(credentials.stageLegacyCredentialsToEnv()).toEqual([]); - expect(process.env.NVIDIA_INFERENCE_API_KEY).toBeUndefined(); + expect(process.env.NVIDIA_API_KEY).toBeUndefined(); // The pointee is intact; we never read or modified it. expect(fs.existsSync(realFile)).toBe(true); }); @@ -365,33 +359,29 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () const credsDir = path.join(home, ".nemoclaw"); const legacyFile = path.join(credsDir, "credentials.json"); fs.mkdirSync(credsDir, { recursive: true }); - fs.writeFileSync( - legacyFile, - JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "nvapi-survives-crash" }), - { - mode: 0o600, - }, - ); + fs.writeFileSync(legacyFile, JSON.stringify({ NVIDIA_API_KEY: "nvapi-survives-crash" }), { + mode: 0o600, + }); // --- Process A: stage, then "crash" (we just abandon the env). --- { const credentials = await importCredentialsModule(home); const stagedA = credentials.stageLegacyCredentialsToEnv(); - expect(stagedA).toEqual(["NVIDIA_INFERENCE_API_KEY"]); - expect(process.env.NVIDIA_INFERENCE_API_KEY).toBe("nvapi-survives-crash"); + expect(stagedA).toEqual(["NVIDIA_API_KEY"]); + expect(process.env.NVIDIA_API_KEY).toBe("nvapi-survives-crash"); // Mid-onboard crash — file MUST still exist. expect(fs.existsSync(legacyFile)).toBe(true); } // Wipe env so nothing carries over from "process A" into "process B". - delete process.env.NVIDIA_INFERENCE_API_KEY; + delete process.env.NVIDIA_API_KEY; // --- Process B: fresh start, re-stage idempotently, then succeed. --- { const credentials = await importCredentialsModule(home); const stagedB = credentials.stageLegacyCredentialsToEnv(); - expect(stagedB).toEqual(["NVIDIA_INFERENCE_API_KEY"]); - expect(process.env.NVIDIA_INFERENCE_API_KEY).toBe("nvapi-survives-crash"); + expect(stagedB).toEqual(["NVIDIA_API_KEY"]); + expect(process.env.NVIDIA_API_KEY).toBe("nvapi-survives-crash"); credentials.removeLegacyCredentialsFile(); expect(fs.existsSync(legacyFile)).toBe(false); } @@ -402,7 +392,7 @@ describe("legacy credentials.json migration (two-phase: stage then remove)", () const credsDir = path.join(home, ".nemoclaw"); const legacyFile = path.join(credsDir, "credentials.json"); fs.mkdirSync(credsDir, { recursive: true }); - const cleartext = JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "nvapi-secret-payload" }); + const cleartext = JSON.stringify({ NVIDIA_API_KEY: "nvapi-secret-payload" }); fs.writeFileSync(legacyFile, cleartext, { mode: 0o600 }); // Capture the pre-unlink content via a wrapper that intercepts the unlink @@ -497,7 +487,7 @@ describe("removeLegacyCredentialsFileIfEmpty (post-upgrade cleanup, #3105)", () fs.mkdirSync(credsDir, { recursive: true }); fs.writeFileSync( legacyFile, - JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "", OPENAI_API_KEY: " \r\n\t " }), + JSON.stringify({ NVIDIA_API_KEY: "", OPENAI_API_KEY: " \r\n\t " }), { mode: 0o600 }, ); @@ -511,7 +501,7 @@ describe("removeLegacyCredentialsFileIfEmpty (post-upgrade cleanup, #3105)", () const credsDir = path.join(home, ".nemoclaw"); const legacyFile = path.join(credsDir, "credentials.json"); fs.mkdirSync(credsDir, { recursive: true }); - const payload = JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "nvapi-real-secret", FOO: "bar" }); + const payload = JSON.stringify({ NVIDIA_API_KEY: "nvapi-real-secret", FOO: "bar" }); fs.writeFileSync(legacyFile, payload, { mode: 0o600 }); const credentials = await importCredentialsModule(home); @@ -776,9 +766,9 @@ createCredentialPromptHelpers(() => { throw new Error("unexpected exit"); }).rea const script = ` const { ensureApiKey } = require(${JSON.stringify(path.join(import.meta.dirname, "..", "dist", "lib", "credentials", "store.js"))}); -delete process.env.NVIDIA_INFERENCE_API_KEY; +delete process.env.NVIDIA_API_KEY; ensureApiKey() - .then(() => console.log('STAGED=' + process.env.NVIDIA_INFERENCE_API_KEY)) + .then(() => console.log('STAGED=' + process.env.NVIDIA_API_KEY)) .catch((err) => { console.error(err && err.stack ? err.stack : String(err)); process.exit(1); }); `; const scriptFile = path.join(os.tmpdir(), `nemoclaw-ensure-api-key-${process.pid}.js`); @@ -795,7 +785,7 @@ ${JSON.stringify(process.execPath)} ${JSON.stringify(scriptFile)} < "$pipe" try { result = spawnSync("bash", ["--noprofile", "--norc"], { encoding: "utf-8", - env: { ...process.env, NVIDIA_INFERENCE_API_KEY: "" }, + env: { ...process.env, NVIDIA_API_KEY: "" }, input: bash, timeout: 5000, }); @@ -816,15 +806,15 @@ ${JSON.stringify(process.execPath)} ${JSON.stringify(scriptFile)} < "$pipe" it("returns navigation from the NVIDIA API key prompt without staging it", () => { const script = ` const { ensureApiKey } = require(${JSON.stringify(path.join(import.meta.dirname, "..", "dist", "lib", "credentials", "store.js"))}); -delete process.env.NVIDIA_INFERENCE_API_KEY; +delete process.env.NVIDIA_API_KEY; ensureApiKey() - .then((result) => console.log(JSON.stringify({ result, key: process.env.NVIDIA_INFERENCE_API_KEY || null }))) + .then((result) => console.log(JSON.stringify({ result, key: process.env.NVIDIA_API_KEY || null }))) .catch((err) => { console.error(err && err.stack ? err.stack : String(err)); process.exit(1); }); `; const result = spawnSync(process.execPath, ["-e", script], { encoding: "utf-8", input: "back\n", - env: { ...process.env, NVIDIA_INFERENCE_API_KEY: "" }, + env: { ...process.env, NVIDIA_API_KEY: "" }, timeout: 5000, }); @@ -836,15 +826,15 @@ ensureApiKey() it("returns exit from the NVIDIA API key prompt without staging it", () => { const script = ` const { ensureApiKey } = require(${JSON.stringify(path.join(import.meta.dirname, "..", "dist", "lib", "credentials", "store.js"))}); -delete process.env.NVIDIA_INFERENCE_API_KEY; +delete process.env.NVIDIA_API_KEY; ensureApiKey() - .then((result) => console.log(JSON.stringify({ result, key: process.env.NVIDIA_INFERENCE_API_KEY || null }))) + .then((result) => console.log(JSON.stringify({ result, key: process.env.NVIDIA_API_KEY || null }))) .catch((err) => { console.error(err && err.stack ? err.stack : String(err)); process.exit(1); }); `; const result = spawnSync(process.execPath, ["-e", script], { encoding: "utf-8", input: "exit\n", - env: { ...process.env, NVIDIA_INFERENCE_API_KEY: "" }, + env: { ...process.env, NVIDIA_API_KEY: "" }, timeout: 5000, }); diff --git a/test/e2e-runtime/4851-ultra-toolless-validation.md b/test/e2e-runtime/4851-ultra-toolless-validation.md index 42cb97fa82d..c6444f04b6d 100644 --- a/test/e2e-runtime/4851-ultra-toolless-validation.md +++ b/test/e2e-runtime/4851-ultra-toolless-validation.md @@ -9,7 +9,7 @@ Repository-verifiable acceptance evidence for [PR #5085](https://github.com/NVID The unit tests in `test/nemotron-inference-fix.test.ts` prove request mutation, Content-Length refresh, and the 12 inject/skip branches via stubbed http + real fetch/undici. They do not prove the upstream model-output behavior the issue's expected result asks for. That requires a live call to NVIDIA Endpoints, which can't run in unit CI without API-key secret infrastructure. -This runbook is the maintained runtime-validation path. Anyone reviewing #4851 acceptance can run it directly against `inference-api.nvidia.com` and confirm the model returns `content` with both file-creation code and the run command after the preload's system message is injected. +This runbook is the maintained runtime-validation path. Anyone reviewing #4851 acceptance can run it directly against `integrate.api.nvidia.com` and confirm the model returns `content` with both file-creation code and the run command after the preload's system message is injected. ## When to run @@ -25,7 +25,7 @@ This runbook is the maintained runtime-validation path. Anyone reviewing #4851 a Export the key once for the session: ```bash -export NVIDIA_INFERENCE_API_KEY="nvapi-..." +export NVIDIA_API_KEY="nvapi-..." ``` ## Scenario A — baseline (no preload, no system message, no tools) @@ -33,8 +33,8 @@ export NVIDIA_INFERENCE_API_KEY="nvapi-..." Demonstrates the bug as filed in the issue body. ```bash -curl -sS -X POST https://inference-api.nvidia.com/v1/chat/completions \ - -H "Authorization: Bearer ${NVIDIA_INFERENCE_API_KEY}" \ +curl -sS -X POST https://integrate.api.nvidia.com/v1/chat/completions \ + -H "Authorization: Bearer ${NVIDIA_API_KEY}" \ -H "Content-Type: application/json" \ -d '{ "model": "nvidia/nemotron-3-ultra-550b-a55b", @@ -61,8 +61,8 @@ Expected result with `nemotron-3-ultra-550b-a55b` (matches issue body): Demonstrates that the existing Nemotron-family kwarg doesn't fix #4851 by itself. ```bash -curl -sS -X POST https://inference-api.nvidia.com/v1/chat/completions \ - -H "Authorization: Bearer ${NVIDIA_INFERENCE_API_KEY}" \ +curl -sS -X POST https://integrate.api.nvidia.com/v1/chat/completions \ + -H "Authorization: Bearer ${NVIDIA_API_KEY}" \ -H "Content-Type: application/json" \ -d '{ "model": "nvidia/nemotron-3-ultra-550b-a55b", @@ -80,8 +80,8 @@ Expected: still ≈ 0–60 chars. The kwarg doesn't change the failure mode. Demonstrates the fix shipped in this PR. ```bash -curl -sS -X POST https://inference-api.nvidia.com/v1/chat/completions \ - -H "Authorization: Bearer ${NVIDIA_INFERENCE_API_KEY}" \ +curl -sS -X POST https://integrate.api.nvidia.com/v1/chat/completions \ + -H "Authorization: Bearer ${NVIDIA_API_KEY}" \ -H "Content-Type: application/json" \ -d '{ "model": "nvidia/nemotron-3-ultra-550b-a55b", @@ -109,7 +109,7 @@ This satisfies the issue's "Expected Result, Option A" (`Model explains it lacks ## Sanitized acceptance transcript -The transcript below was captured by @cjagwani on 2026-06-09 against `inference-api.nvidia.com` from a GCP Brev box. Reproduces the bug behavior in Scenarios A/B and the fix behavior in Scenario C. Use this as the durable acceptance baseline; new runs that differ structurally should update this section (and the dated entry below) rather than the unit tests. +The transcript below was captured by @cjagwani on 2026-06-09 against `integrate.api.nvidia.com` from a GCP Brev box. Reproduces the bug behavior in Scenarios A/B and the fix behavior in Scenario C. Use this as the durable acceptance baseline; new runs that differ structurally should update this section (and the dated entry below) rather than the unit tests. ### Scenario A (baseline) — 2026-06-09 @@ -200,6 +200,6 @@ This satisfies the issue's Option A acceptance condition: model explains it lack ## Live verification log -- 2026-06-09 — verified by @cjagwani on a GCP Brev box against `inference-api.nvidia.com`. Numbers and content above match this run. +- 2026-06-09 — verified by @cjagwani on a GCP Brev box against `integrate.api.nvidia.com`. Numbers and content above match this run. When you re-run this runbook, add a dated entry here so the next reviewer can see how recently the upstream behavior was last confirmed. If the response shape differs materially from the sanitized transcript above, update both this log and the transcript. diff --git a/test/e2e-scenario/fixtures/hosted-inference.ts b/test/e2e-scenario/fixtures/hosted-inference.ts deleted file mode 100644 index f46b446bf71..00000000000 --- a/test/e2e-scenario/fixtures/hosted-inference.ts +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -const HOSTED_INFERENCE_SECRET = "NVIDIA_INFERENCE_API_KEY"; -const HOSTED_INFERENCE_CREDENTIAL_ENV = "COMPATIBLE_API_KEY"; -const HOSTED_INFERENCE_PROVIDER = "custom"; -const HOSTED_INFERENCE_PROVIDER_NAME = "compatible-endpoint"; -const DEFAULT_HOSTED_INFERENCE_BASE_URL = "https://inference-api.nvidia.com/v1"; -const DEFAULT_HOSTED_INFERENCE_MODEL = "nvidia/nvidia/nemotron-3-super-v3"; - -export interface HostedInferenceSecrets { - required(name: string): string; -} - -export interface HostedInferenceOptions { - model?: string; -} - -export interface HostedInferenceConfig { - apiKey: string; - sourceSecretName: typeof HOSTED_INFERENCE_SECRET; - credentialEnv: typeof HOSTED_INFERENCE_CREDENTIAL_ENV; - provider: typeof HOSTED_INFERENCE_PROVIDER; - providerName: typeof HOSTED_INFERENCE_PROVIDER_NAME; - env: NodeJS.ProcessEnv; - model: string; - endpointUrl: string; - contractLabel: string; -} - -export function requireHostedInferenceConfig( - secrets: HostedInferenceSecrets, - env: NodeJS.ProcessEnv = process.env, - options: HostedInferenceOptions = {}, -): HostedInferenceConfig { - const apiKey = secrets.required(HOSTED_INFERENCE_SECRET); - const endpointUrl = env.NEMOCLAW_ENDPOINT_URL || DEFAULT_HOSTED_INFERENCE_BASE_URL; - const model = - env.NEMOCLAW_MODEL || - env.NEMOCLAW_COMPAT_MODEL || - options.model || - DEFAULT_HOSTED_INFERENCE_MODEL; - return { - apiKey, - sourceSecretName: HOSTED_INFERENCE_SECRET, - credentialEnv: HOSTED_INFERENCE_CREDENTIAL_ENV, - provider: HOSTED_INFERENCE_PROVIDER, - providerName: HOSTED_INFERENCE_PROVIDER_NAME, - endpointUrl, - model, - env: { - NEMOCLAW_PROVIDER: HOSTED_INFERENCE_PROVIDER, - NEMOCLAW_ENDPOINT_URL: endpointUrl, - NEMOCLAW_MODEL: model, - NEMOCLAW_COMPAT_MODEL: model, - [HOSTED_INFERENCE_CREDENTIAL_ENV]: apiKey, - }, - contractLabel: "NVIDIA_INFERENCE_API_KEY is staged as the compatible endpoint credential", - }; -} diff --git a/test/e2e-scenario/fixtures/phases/onboarding.ts b/test/e2e-scenario/fixtures/phases/onboarding.ts index 23000d53908..aa6b533ccc6 100644 --- a/test/e2e-scenario/fixtures/phases/onboarding.ts +++ b/test/e2e-scenario/fixtures/phases/onboarding.ts @@ -176,11 +176,11 @@ export class OnboardingPhaseFixture { throw new Error("cloud-openclaw onboarding requires an available Docker runtime."); } const sandboxName = sandboxNameFromOptions(environment.onboarding, options); - const apiKey = this.secrets.required("NVIDIA_INFERENCE_API_KEY"); + const apiKey = this.secrets.required("NVIDIA_API_KEY"); this.registerSandboxCleanup(sandboxName); const result = await this.host.nemoclaw(ONBOARD_ARGS, { artifactName: "onboard-cloud-openclaw", - env: commandEnv(sandboxName, { NVIDIA_INFERENCE_API_KEY: apiKey }), + env: commandEnv(sandboxName, { NVIDIA_API_KEY: apiKey }), redactionValues: [apiKey], timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS, }); @@ -206,14 +206,14 @@ export class OnboardingPhaseFixture { ); } const sandboxName = sandboxNameFromOptions(environment.onboarding, options); - const apiKey = this.secrets.required("NVIDIA_INFERENCE_API_KEY"); + const apiKey = this.secrets.required("NVIDIA_API_KEY"); this.registerSandboxCleanup(sandboxName); const shimDir = await mkdtemp(join(tmpdir(), "e2e-no-docker-")); const shimPath = join(shimDir, "docker"); try { await writeFile(shimPath, noDockerShim(), "utf8"); await chmod(shimPath, 0o700); - const env = commandEnv(sandboxName, { NVIDIA_INFERENCE_API_KEY: apiKey }); + const env = commandEnv(sandboxName, { NVIDIA_API_KEY: apiKey }); env.PATH = prependPath(shimDir, env.PATH); const result = await this.host.nemoclaw(ONBOARD_ARGS, { artifactName: "onboard-cloud-openclaw-no-docker", diff --git a/test/e2e-scenario/live/credential-migration.test.ts b/test/e2e-scenario/live/credential-migration.test.ts index 4068840372a..a020a5a1133 100644 --- a/test/e2e-scenario/live/credential-migration.test.ts +++ b/test/e2e-scenario/live/credential-migration.test.ts @@ -9,7 +9,6 @@ import { buildAvailabilityProbeEnv } from "../fixtures/availability-env.ts"; import type { HostCliClient } from "../fixtures/clients/host.ts"; import { validateSandboxName } from "../fixtures/clients/sandbox.ts"; import { expect, test } from "../fixtures/e2e-test.ts"; -import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; // Migrated from test/e2e/test-credential-migration.sh. This is a focused live @@ -18,10 +17,10 @@ import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; // a successful real onboard registers the migrated value with the OpenShell // gateway, the plaintext file is removed after success, credentials list reads // from the gateway, and secure unlink removes a planted symlink without touching -// its target. The repository secret is named NVIDIA_INFERENCE_API_KEY, but the -// hosted E2E service is the OpenAI-compatible inference-api.nvidia.com endpoint, -// so the migration contract stages that value as COMPATIBLE_API_KEY and expects -// the compatible-endpoint gateway provider. +// its target. The live onboard intentionally follows the legacy default NVIDIA +// Endpoints path: NVIDIA_API_KEY is present only in the legacy file, absent from +// the onboard child env, and must migrate into the nvidia-prod gateway provider. +// No registry, migration ledger, or shared helper is introduced. const REPO_ROOT = path.resolve(import.meta.dirname, "../../.."); const CLI_ENTRYPOINT = path.join(REPO_ROOT, "bin", "nemoclaw.js"); @@ -108,10 +107,7 @@ async function cleanupCredentialMigrationState(host: HostCliClient, home: string host.command("node", [CLI_ENTRYPOINT, SANDBOX_NAME, "destroy", "--yes"], { artifactName: "cleanup-nemoclaw-destroy", env, - redactionValues: [ - process.env.NVIDIA_INFERENCE_API_KEY ?? "", - process.env.COMPATIBLE_API_KEY ?? "", - ], + redactionValues: [process.env.NVIDIA_API_KEY ?? ""], timeoutMs: 120_000, }), ); @@ -142,18 +138,15 @@ runCredentialMigrationTest( "credential migration stages legacy file into gateway and removes plaintext safely", { timeout: ONBOARD_TIMEOUT_MS + INSTALL_TIMEOUT_MS + 5 * 60_000 }, async ({ artifacts, cleanup, host, secrets, skip }) => { - // Use the existing nightly secret as the legacy provider credential. The - // onboard child env below deliberately does not receive that credential, so + // Use the existing nightly secret as the legacy NVIDIA credential. The + // onboard child env below deliberately does not receive NVIDIA_API_KEY, so // the only source is ~/.nemoclaw/credentials.json — matching the retired // shell lane's migration contract. - const hostedInference = requireHostedInferenceConfig(secrets, process.env, { - model: CREDENTIAL_MIGRATION_MODEL, - }); - const migratedCredentialValue = hostedInference.apiKey; - const { - [hostedInference.credentialEnv]: _omittedCredential, - ...hostedInferenceEnvWithoutCredential - } = hostedInference.env; + const migratedCredentialValue = secrets.required("NVIDIA_API_KEY"); + expect( + migratedCredentialValue.startsWith("nvapi-"), + "NVIDIA_API_KEY must start with nvapi-", + ).toBe(true); expect(fs.existsSync(CLI_ENTRYPOINT), "bin/nemoclaw.js missing").toBe(true); expect( fs.existsSync(DIST_CREDENTIAL_STORE), @@ -190,9 +183,8 @@ runCredentialMigrationTest( sandboxName: SANDBOX_NAME, contracts: [ "legacy credentials.json stages allowlisted provider keys into onboard env", - `successful onboard registers the migrated value with the ${hostedInference.providerName} OpenShell gateway provider`, - `${hostedInference.sourceSecretName} is migrated into the ${hostedInference.credentialEnv} provider credential`, - `onboard uses the ${hostedInference.provider} provider and ${hostedInference.endpointUrl} endpoint path`, + "successful default NVIDIA Endpoints onboard registers the migrated value with OpenShell gateway", + "onboard keeps the default NVIDIA provider/key/endpoint/policy path while pinning a low-quota catalog model", "successful onboard removes plaintext credentials.json", "tampered non-credential keys do not become gateway providers", "credentials list reads providers from the gateway, not disk", @@ -209,7 +201,7 @@ runCredentialMigrationTest( legacyFile, JSON.stringify( { - [hostedInference.credentialEnv]: migratedCredentialValue, + NVIDIA_API_KEY: migratedCredentialValue, OPENSHELL_GATEWAY: "evil-gw-from-tampered-file", NODE_OPTIONS: "--require=/tmp/evil.js", }, @@ -222,9 +214,11 @@ runCredentialMigrationTest( const onboard = await host.command("node", [CLI_ENTRYPOINT, "onboard", "--non-interactive"], { artifactName: "onboard-from-legacy-credentials", env: testEnv(home, { - ...hostedInferenceEnvWithoutCredential, NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, NEMOCLAW_RECREATE_SANDBOX: "1", + // Keep the default NVIDIA provider/key/endpoint/policy path while + // avoiding the high-quota default Nemotron validation model. + NEMOCLAW_MODEL: CREDENTIAL_MIGRATION_MODEL, }), redactionValues: [migratedCredentialValue], timeoutMs: ONBOARD_TIMEOUT_MS, @@ -253,10 +247,9 @@ runCredentialMigrationTest( .split(/\r?\n/) .map((line) => line.trim()) .filter((line) => /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(line)); - expect( - providerNames, - `expected migrated ${hostedInference.providerName} provider\n${providersText}`, - ).toContain(hostedInference.providerName); + expect(providerNames, `expected migrated NVIDIA provider\n${providersText}`).toContain( + "nvidia-prod", + ); expect(providerNames).not.toContain("OPENSHELL_GATEWAY"); expect(providerNames).not.toContain("NODE_OPTIONS"); @@ -299,9 +292,7 @@ runCredentialMigrationTest( await artifacts.writeJson("scenario-result.json", { id: "credential-migration", sandboxName: SANDBOX_NAME, - model: hostedInference.model || CREDENTIAL_MIGRATION_MODEL, - provider: hostedInference.providerName, - credentialEnv: hostedInference.credentialEnv, + model: CREDENTIAL_MIGRATION_MODEL, providerNames, assertions: { onboardSucceeded: onboard.exitCode === 0, @@ -309,7 +300,7 @@ runCredentialMigrationTest( "Staged 1 legacy credential(s) for migration to the OpenShell gateway.", ), legacyFileRemovedAfterOnboard: !fs.existsSync(legacyFile), - migratedProviderRegistered: providerNames.includes(hostedInference.providerName), + migratedNvidiaProviderRegistered: providerNames.includes("nvidia-prod"), tamperedKeysExcluded: !providerNames.includes("OPENSHELL_GATEWAY") && !providerNames.includes("NODE_OPTIONS"), credentialsListReadsGateway: credentialsText.includes( diff --git a/test/e2e-scenario/live/credential-sanitization.test.ts b/test/e2e-scenario/live/credential-sanitization.test.ts index e12e57b2a17..0c9bd56f75a 100644 --- a/test/e2e-scenario/live/credential-sanitization.test.ts +++ b/test/e2e-scenario/live/credential-sanitization.test.ts @@ -199,7 +199,7 @@ function assertCredentialFieldDetectionContract(): void { displayName: "should-be-preserved", sortKey: "should-also-be-preserved", modelName: "nvidia/nemotron-3-super-120b-a12b", - keyRef: { source: "env", id: "NVIDIA_INFERENCE_API_KEY" }, + keyRef: { source: "env", id: "NVIDIA_API_KEY" }, description: "A secret garden (but not a real secret)", tokenizer: "sentencepiece", endpoint: "https://api.nvidia.com/v1", @@ -318,10 +318,8 @@ runCredentialSanitizationTest( assertCredentialFieldDetectionContract(); assertBlueprintDigestContract(); - const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); + const apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); const docker = await host.command("docker", ["info"], { artifactName: "prereq-docker-info-credential-sanitization", @@ -352,7 +350,7 @@ runCredentialSanitizationTest( artifactName: "install-and-onboard-credential-sanitization", cwd: REPO_ROOT, env: testEnv(home, { - NVIDIA_INFERENCE_API_KEY: apiKey, + NVIDIA_API_KEY: apiKey, NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, NEMOCLAW_RECREATE_SANDBOX: "1", }), diff --git a/test/e2e-scenario/live/gateway-guard-recovery.test.ts b/test/e2e-scenario/live/gateway-guard-recovery.test.ts index 4cb08907d1b..3a26756765d 100644 --- a/test/e2e-scenario/live/gateway-guard-recovery.test.ts +++ b/test/e2e-scenario/live/gateway-guard-recovery.test.ts @@ -72,7 +72,7 @@ test("gateway recovery restores /tmp guard chain after pod-recreate wipe (#2701) secrets, cleanup, }) => { - secrets.required("NVIDIA_INFERENCE_API_KEY"); + secrets.required("NVIDIA_API_KEY"); await artifacts.writeJson("scenario.json", { id: "gateway-guard-recovery", diff --git a/test/e2e-scenario/live/hermes-e2e.test.ts b/test/e2e-scenario/live/hermes-e2e.test.ts index bd7fed651cd..e086f52fc41 100644 --- a/test/e2e-scenario/live/hermes-e2e.test.ts +++ b/test/e2e-scenario/live/hermes-e2e.test.ts @@ -75,7 +75,7 @@ function commandEnv(apiKey?: string): NodeJS.ProcessEnv { NEMOCLAW_ONBOARD_VALIDATION_TIMEOUT_SECONDS: ONBOARD_VALIDATION_TIMEOUT_SECONDS, NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, }; - if (apiKey) env.NVIDIA_INFERENCE_API_KEY = apiKey; + if (apiKey) env.NVIDIA_API_KEY = apiKey; if (process.env.NEMOCLAW_E2E_HERMES_DASHBOARD) { env.NEMOCLAW_E2E_HERMES_DASHBOARD = process.env.NEMOCLAW_E2E_HERMES_DASHBOARD; } @@ -219,10 +219,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 apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); await artifacts.writeJson("scenario.json", { id: "hermes-e2e", @@ -279,11 +277,11 @@ test.skipIf(!shouldRunLiveE2EScenarios())( expect(fs.existsSync(path.join(REPO_ROOT, "agents", "hermes", "manifest.yaml"))).toBe(true); const providerModels = await provider.requestJson( - trustedProviderEndpoint("https://inference-api.nvidia.com/v1/models", { - allowedHosts: ["inference-api.nvidia.com"], + trustedProviderEndpoint("https://integrate.api.nvidia.com/v1/models", { + allowedHosts: ["integrate.api.nvidia.com"], }), { - artifactName: "phase-1-inference-models", + artifactName: "phase-1-integrate-models", curlMaxTimeSeconds: 15, headers: [`Authorization: Bearer ${apiKey}`], env: buildAvailabilityProbeEnv(), @@ -486,8 +484,8 @@ test.skipIf(!shouldRunLiveE2EScenarios())( "direct NVIDIA Endpoints chat", async (attempt) => { const response = await provider.requestJson( - trustedProviderEndpoint("https://inference-api.nvidia.com/v1/chat/completions", { - allowedHosts: ["inference-api.nvidia.com"], + trustedProviderEndpoint("https://integrate.api.nvidia.com/v1/chat/completions", { + allowedHosts: ["integrate.api.nvidia.com"], }), { artifactName: `phase-5-direct-nvidia-chat-attempt-${attempt}`, diff --git a/test/e2e-scenario/live/inference-routing.test.ts b/test/e2e-scenario/live/inference-routing.test.ts index 83007af27a3..ff958867fa4 100644 --- a/test/e2e-scenario/live/inference-routing.test.ts +++ b/test/e2e-scenario/live/inference-routing.test.ts @@ -563,7 +563,7 @@ liveTest( const result = await onboardSandbox( artifacts, sandboxName, - { NVIDIA_INFERENCE_API_KEY: invalidKey }, + { NVIDIA_API_KEY: invalidKey }, [invalidKey], "tc-inf-06-onboard-invalid-api-key", 120_000, @@ -612,7 +612,7 @@ liveTest( NEMOCLAW_ENDPOINT_URL: "https://nemoclaw-e2e.invalid/v1", NEMOCLAW_MODEL: "test-model", NEMOCLAW_PROVIDER: "custom", - NVIDIA_INFERENCE_API_KEY: nvidiaKey, + NVIDIA_API_KEY: nvidiaKey, }, [nvidiaKey, compatibleKey], "tc-inf-07-onboard-unreachable-endpoint", @@ -633,8 +633,8 @@ liveTest( { timeout: 15 * 60_000 }, async ({ artifacts, cleanup, host, sandbox, secrets, skip }) => { const apiKey = - secrets.optional("NVIDIA_INFERENCE_API_KEY") ?? - skipLive(skip, "NVIDIA_INFERENCE_API_KEY not set — cannot test credential isolation"); + secrets.optional("NVIDIA_API_KEY") ?? + skipLive(skip, "NVIDIA_API_KEY not set — cannot test credential isolation"); await requireLivePrerequisites(host, skip); const sandboxName = inferenceSandboxName("e2e-inf-cred"); cleanup.add( @@ -648,17 +648,17 @@ liveTest( runner: "vitest", migratedFrom: "test/e2e/test-inference-routing.sh", contract: [ - "real NVIDIA_INFERENCE_API_KEY does not appear in sandbox environment", - "real NVIDIA_INFERENCE_API_KEY does not appear in sandbox process list when ps is available", - "real NVIDIA_INFERENCE_API_KEY does not appear in sampled sandbox filesystem", - "sandbox NVIDIA_INFERENCE_API_KEY, when present, is a placeholder rather than the real key", + "real NVIDIA_API_KEY does not appear in sandbox environment", + "real NVIDIA_API_KEY does not appear in sandbox process list when ps is available", + "real NVIDIA_API_KEY does not appear in sampled sandbox filesystem", + "sandbox NVIDIA_API_KEY, when present, is a placeholder rather than the real key", ], }); const onboard = await onboardSandbox( artifacts, sandboxName, - { NVIDIA_INFERENCE_API_KEY: apiKey }, + { NVIDIA_API_KEY: apiKey }, [apiKey], "tc-inf-05-onboard-credential-isolation", ); @@ -787,7 +787,7 @@ liveTest( const placeholder = await sandbox.execShell( sandboxName, - trustedSandboxShellScript("printenv NVIDIA_INFERENCE_API_KEY 2>/dev/null || true"), + trustedSandboxShellScript("printenv NVIDIA_API_KEY 2>/dev/null || true"), { artifactName: "tc-inf-05-sandbox-placeholder", env: buildAvailabilityProbeEnv(), @@ -798,8 +798,7 @@ liveTest( const placeholderValue = placeholder.stdout.trim(); if (!placeholderValue) { await artifacts.writeJson("tc-inf-05-placeholder-skipped.json", { - reason: - "NVIDIA_INFERENCE_API_KEY not set in sandbox; placeholder injection may not be active", + reason: "NVIDIA_API_KEY not set in sandbox; placeholder injection may not be active", }); } else { expect(placeholderValue, "sandbox has the real key, not a placeholder").not.toBe(apiKey); 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..dc1d50b9ace 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 @@ -25,7 +25,7 @@ const ENVIRONMENT = ubuntuRepoDocker("cloud-openclaw"); const SANDBOX_NAME = process.env.NEMOCLAW_SANDBOX_NAME ?? "e2e-issue-4434-tui-unreachable"; validateSandboxName(SANDBOX_NAME); -const INFERENCE_MODELS_URL = "https://inference-api.nvidia.com/v1/models"; +const INTEGRATE_MODELS_URL = "https://integrate.api.nvidia.com/v1/models"; const BLOCKED_IPS = ["75.2.113.119", "99.83.136.103"]; const DEFAULT_TUI_TIMEOUT_SEC = 180; const MAX_TUI_TIMEOUT_SEC = 3600; @@ -138,10 +138,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 apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); await artifacts.writeJson("scenario.json", { id: "issue-4434-tui-unreachable-inference", @@ -245,7 +243,7 @@ runIssue4434LiveTest( const blockedEndpointProbe = await sandbox.execShell( instance.sandboxName, trustedSandboxShellScript( - `command -v curl >/dev/null && curl -sk --connect-timeout 5 --max-time 12 ${shellSingleQuote(INFERENCE_MODELS_URL)} >/tmp/issue4434-models.blocked.out 2>&1`, + `command -v curl >/dev/null && curl -sk --connect-timeout 5 --max-time 12 ${shellSingleQuote(INTEGRATE_MODELS_URL)} >/tmp/issue4434-models.blocked.out 2>&1`, ), { artifactName: "issue4434-endpoint-probe-after-block", @@ -255,7 +253,7 @@ runIssue4434LiveTest( ); expect( blockedEndpointProbe.exitCode, - `inference-api.nvidia.com remained reachable from inside the sandbox after firewall block\n${resultText(blockedEndpointProbe)}`, + `integrate.api.nvidia.com remained reachable from inside the sandbox after firewall block\n${resultText(blockedEndpointProbe)}`, ).not.toBe(0); const captureFile = artifacts.pathFor("openclaw-tui-capture.log"); diff --git a/test/e2e-scenario/live/launchable-smoke.test.ts b/test/e2e-scenario/live/launchable-smoke.test.ts index b9660950941..466ac355a6c 100644 --- a/test/e2e-scenario/live/launchable-smoke.test.ts +++ b/test/e2e-scenario/live/launchable-smoke.test.ts @@ -234,10 +234,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 apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); expect(fs.existsSync(LAUNCHABLE_SCRIPT), `${LAUNCHABLE_SCRIPT} missing`).toBe(true); @@ -257,10 +255,10 @@ runLaunchableSmokeTest( const network = await host.command( "curl", - ["-sf", "--max-time", "10", "https://inference-api.nvidia.com/v1/models"], - { artifactName: "prereq-inference-api-models", env: runEnv(), timeoutMs: 30_000 }, + ["-sf", "--max-time", "10", "https://integrate.api.nvidia.com/v1/models"], + { artifactName: "prereq-integrate-api-models", env: runEnv(), timeoutMs: 30_000 }, ); - expectExitZero(network, "inference-api.nvidia.com reachable"); + expectExitZero(network, "integrate.api.nvidia.com reachable"); const cloneDir = path.join(os.tmpdir(), `NemoClaw-launchable-vitest-${randomUUID()}`); cleanup.add(`remove launchable clone ${cloneDir}`, async () => @@ -335,7 +333,7 @@ runLaunchableSmokeTest( cwd: cloneDir, env: runEnv({ PATH: `/usr/local/bin:${process.env.PATH ?? ""}`, - NVIDIA_INFERENCE_API_KEY: apiKey, + NVIDIA_API_KEY: apiKey, NEMOCLAW_MODEL: MODEL, NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, NEMOCLAW_RECREATE_SANDBOX: "1", @@ -414,7 +412,7 @@ runLaunchableSmokeTest( "30", "-X", "POST", - "https://inference-api.nvidia.com/v1/chat/completions", + "https://integrate.api.nvidia.com/v1/chat/completions", "-H", "Content-Type: application/json", "-H", diff --git a/test/e2e-scenario/live/model-router-provider-routed-inference.test.ts b/test/e2e-scenario/live/model-router-provider-routed-inference.test.ts index 79aec674626..3cbd7d187ef 100644 --- a/test/e2e-scenario/live/model-router-provider-routed-inference.test.ts +++ b/test/e2e-scenario/live/model-router-provider-routed-inference.test.ts @@ -75,7 +75,7 @@ function routedPongReason(raw: string): "ok" | string { function withProviderRoutedEnv(apiKey: string): NodeJS.ProcessEnv { return { ...buildAvailabilityProbeEnv(), - NVIDIA_INFERENCE_API_KEY: apiKey, + NVIDIA_API_KEY: apiKey, NEMOCLAW_PROVIDER_KEY: apiKey, NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, NEMOCLAW_NON_INTERACTIVE: "1", @@ -107,10 +107,8 @@ test.skipIf(!shouldRunLiveE2EScenarios())( skip("Docker is required for provider-routed Model Router onboarding"); } - const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); + const apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); await artifacts.writeJson("scenario.json", { id: "model-router-provider-routed-inference", @@ -119,7 +117,7 @@ test.skipIf(!shouldRunLiveE2EScenarios())( legacySource: "test/e2e/test-model-router-provider-routed-inference.sh", contract: [ "Docker is available before onboarding", - "NVIDIA_INFERENCE_API_KEY is present and nvapi-prefixed", + "NVIDIA_API_KEY is present and nvapi-prefixed", "nemoclaw onboard --fresh completes with NEMOCLAW_PROVIDER=routed", "host model-router health reports at least one healthy endpoint", "sandbox inference.local returns model nvidia-routed with PONG content", diff --git a/test/e2e-scenario/live/network-policy.test.ts b/test/e2e-scenario/live/network-policy.test.ts index d45c9f8be58..6ba4b57f611 100644 --- a/test/e2e-scenario/live/network-policy.test.ts +++ b/test/e2e-scenario/live/network-policy.test.ts @@ -401,10 +401,8 @@ 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, - ); + const apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); cleanup.add(`destroy network-policy sandbox ${SANDBOX_NAME}`, async () => { await runNemoclaw(host, [SANDBOX_NAME, "destroy", "--yes"], { @@ -444,7 +442,7 @@ RUN_NETWORK_POLICY_TEST( ? "onboard-restricted-network-policy" : `onboard-restricted-network-policy-attempt-${attempt}`, env: baseEnv({ - NVIDIA_INFERENCE_API_KEY: apiKey, + NVIDIA_API_KEY: apiKey, NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, NEMOCLAW_RECREATE_SANDBOX: "1", NEMOCLAW_POLICY_TIER: "restricted", @@ -689,7 +687,7 @@ printf '\n' expect(inferenceContent.trim().length).toBeGreaterThan(0); const directProvider = await fetchStatus( sandbox, - "https://inference-api.nvidia.com/v1/models", + "https://integrate.api.nvidia.com/v1/models", "tc-net-07-direct-provider-blocked", ); expect(directProvider).toMatch(/STATUS_403|ERROR_/); diff --git a/test/e2e-scenario/live/onboard-negative-paths.test.ts b/test/e2e-scenario/live/onboard-negative-paths.test.ts index 074c798c96a..dc957e2ff56 100644 --- a/test/e2e-scenario/live/onboard-negative-paths.test.ts +++ b/test/e2e-scenario/live/onboard-negative-paths.test.ts @@ -16,7 +16,7 @@ import type { HostCliClient } from "../fixtures/clients/host.ts"; const REPO_ROOT = path.resolve(import.meta.dirname, "../../.."); const CLI_DIST_ENTRYPOINT = path.join(REPO_ROOT, "dist", "nemoclaw.js"); const SESSION_FILE = path.join(process.env.HOME ?? "/tmp", ".nemoclaw", "onboard-session.json"); -const INVALID_NVIDIA_INFERENCE_API_KEY = "not-a-nvidia-key"; +const INVALID_NVIDIA_API_KEY = "not-a-nvidia-key"; const STACK_TRACE_PATTERNS = [/(^|\s)(TypeError|ReferenceError|SyntaxError):/m, /^\s+at /m]; process.env.NEMOCLAW_CLI_BIN ??= path.join(REPO_ROOT, "bin", "nemoclaw.js"); @@ -123,9 +123,9 @@ liveTest( NEMOCLAW_RECREATE_SANDBOX: "1", NEMOCLAW_PROVIDER: "cloud", NEMOCLAW_POLICY_MODE: "skip", - NVIDIA_INFERENCE_API_KEY: INVALID_NVIDIA_INFERENCE_API_KEY, + NVIDIA_API_KEY: INVALID_NVIDIA_API_KEY, }), - redactionValues: [INVALID_NVIDIA_INFERENCE_API_KEY], + redactionValues: [INVALID_NVIDIA_API_KEY], timeoutMs: 5 * 60_000, }, ); diff --git a/test/e2e-scenario/live/onboard-resume.test.ts b/test/e2e-scenario/live/onboard-resume.test.ts index f5b9c5847ec..e411f759624 100644 --- a/test/e2e-scenario/live/onboard-resume.test.ts +++ b/test/e2e-scenario/live/onboard-resume.test.ts @@ -16,7 +16,7 @@ import { shouldRunLiveE2EScenarios } from "../fixtures/live-project-gate.ts"; // Shape: drive the real `nemoclaw onboard` CLI through the deterministic E2E // failure-injection hook (NEMOCLAW_E2E_FAILURE_INJECTION + // NEMOCLAW_E2E_FORCE_FAIL_AT_STEP), then invoke -// `nemoclaw onboard --resume --non-interactive` with NVIDIA_INFERENCE_API_KEY stripped +// `nemoclaw onboard --resume --non-interactive` with NVIDIA_API_KEY stripped // from the environment to prove the credential is hydrated from the onboard // session file. // @@ -93,7 +93,7 @@ function containsExactJsonToken(value: unknown, token: string): boolean { } // Gate the test on NEMOCLAW_RUN_E2E_SCENARIOS=1 so accidental cli-test-shard -// discovery does not run it without real `openshell`, Docker, or NVIDIA_INFERENCE_API_KEY. +// discovery does not run it without real `openshell`, Docker, or NVIDIA_API_KEY. // Live-only tests opt in to the same gate used by the `e2e-scenarios-live` // project include glob in vitest.config.ts. test.skipIf(!shouldRunLiveE2EScenarios())( @@ -113,7 +113,7 @@ test.skipIf(!shouldRunLiveE2EScenarios())( // env (includes PATH, HOME, etc.) so spawn can locate `docker`. // The shell-probe boundary defaults to no env inheritance; fixture spawns // must opt in via buildAvailabilityProbeEnv() to keep secret-passthrough - // explicit (NVIDIA_INFERENCE_API_KEY is NOT in the allowlist; we layer it explicitly + // explicit (NVIDIA_API_KEY is NOT in the allowlist; we layer it explicitly // in Phase 2 below). const dockerInfo = await host.command("docker", ["info"], { artifactName: "prereq-docker-info", @@ -132,12 +132,10 @@ test.skipIf(!shouldRunLiveE2EScenarios())( expect(openshellVersion.exitCode, openshellVersion.stderr).toBe(0); // Assertion: nvidia-api-key-present — secrets.required(...) skips the test - // if NVIDIA_INFERENCE_API_KEY is unset (correct behavior under workflow_dispatch + // if NVIDIA_API_KEY is unset (correct behavior under workflow_dispatch // without the secret wired in). - const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); + const apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); // ────────────────────────────────────────────────────────────────── // Phase 0 (deferred): pre-cleanup of leftover sandbox/session state. @@ -212,7 +210,7 @@ test.skipIf(!shouldRunLiveE2EScenarios())( artifactName: "phase-2-onboard-interrupted", env: { ...buildAvailabilityProbeEnv(), - NVIDIA_INFERENCE_API_KEY: apiKey, + NVIDIA_API_KEY: apiKey, NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, NEMOCLAW_RECREATE_SANDBOX: "1", NEMOCLAW_POLICY_MODE: "suggested", @@ -258,7 +256,7 @@ test.skipIf(!shouldRunLiveE2EScenarios())( expect(interrupted.failure?.step).toBe("policies"); // ────────────────────────────────────────────────────────────────── - // Phase 3: resume — NVIDIA_INFERENCE_API_KEY removed from env so the resume run + // Phase 3: resume — NVIDIA_API_KEY removed from env so the resume run // must hydrate the credential from the session file. // ────────────────────────────────────────────────────────────────── const resumeRun = await host.command( @@ -266,10 +264,10 @@ test.skipIf(!shouldRunLiveE2EScenarios())( [CLI_ENTRYPOINT, "onboard", "--resume", "--non-interactive"], { artifactName: "phase-3-onboard-resume", - // buildAvailabilityProbeEnv() does NOT pass NVIDIA_INFERENCE_API_KEY through — + // buildAvailabilityProbeEnv() does NOT pass NVIDIA_API_KEY through — // it's outside the fixture env allowlist. Resume must hydrate the // credential from the session file. This is exactly the bash test's - // `env -u NVIDIA_INFERENCE_API_KEY` invariant, expressed via explicit + // `env -u NVIDIA_API_KEY` invariant, expressed via explicit // secret-passthrough. env: { ...buildAvailabilityProbeEnv(), diff --git a/test/e2e-scenario/live/openclaw-tui-chat-correlation.test.ts b/test/e2e-scenario/live/openclaw-tui-chat-correlation.test.ts index 9759f12c261..94945072693 100644 --- a/test/e2e-scenario/live/openclaw-tui-chat-correlation.test.ts +++ b/test/e2e-scenario/live/openclaw-tui-chat-correlation.test.ts @@ -485,7 +485,7 @@ async function runLiveIssue2603ReproWithEventCaptureRetry( test( "openclaw-tui-chat-correlation: rapid TUI/webchat sends stay correlated on a real OpenClaw sandbox (#2603 + #3145)", async ({ artifacts, environment, onboard, sandbox, secrets }) => { - secrets.required("NVIDIA_INFERENCE_API_KEY"); + secrets.required("NVIDIA_API_KEY"); await artifacts.writeJson("scenario.json", { id: "openclaw-tui-chat-correlation", diff --git a/test/e2e-scenario/live/rebuild-openclaw.test.ts b/test/e2e-scenario/live/rebuild-openclaw.test.ts index 0c3418121e3..b5f91a31575 100644 --- a/test/e2e-scenario/live/rebuild-openclaw.test.ts +++ b/test/e2e-scenario/live/rebuild-openclaw.test.ts @@ -136,7 +136,7 @@ function dockerContextEnv(extra: NodeJS.ProcessEnv = {}): NodeJS.ProcessEnv { function cliEnv(apiKey: string, extra: NodeJS.ProcessEnv = {}): NodeJS.ProcessEnv { return dockerContextEnv({ - NVIDIA_INFERENCE_API_KEY: apiKey, + NVIDIA_API_KEY: apiKey, NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, ...extra, }); @@ -205,9 +205,9 @@ async function configureGatewayInferenceRoute( [ "set -euo pipefail", "if openshell provider get nvidia-prod >/dev/null 2>&1; then", - " openshell provider update nvidia-prod --credential NVIDIA_INFERENCE_API_KEY", + " openshell provider update nvidia-prod --credential NVIDIA_API_KEY", "else", - " openshell provider create --name nvidia-prod --type nvidia --credential NVIDIA_INFERENCE_API_KEY", + " openshell provider create --name nvidia-prod --type nvidia --credential NVIDIA_API_KEY", "fi", `openshell inference set --no-verify --provider nvidia-prod --model ${model}`, ].join("\n"), @@ -260,7 +260,7 @@ function seedRegistryAndSession(): void { failure: null, provider: "nvidia-prod", model: DEFAULT_MODEL, - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", agent: null, steps: { preflight: complete, @@ -346,10 +346,8 @@ function backupCredentialLeakPaths(backupDir: string, oldGatewayToken: string): 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, - ); + const apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); expect( fs.existsSync(CLI_ENTRYPOINT), diff --git a/test/e2e-scenario/live/sandbox-operations.test.ts b/test/e2e-scenario/live/sandbox-operations.test.ts index acaf07de8f5..81f1cef5062 100644 --- a/test/e2e-scenario/live/sandbox-operations.test.ts +++ b/test/e2e-scenario/live/sandbox-operations.test.ts @@ -98,9 +98,9 @@ async function onboardSandbox( NEMOCLAW_PROVIDER: "cloud", NEMOCLAW_SANDBOX_NAME: sandboxName, NEMOCLAW_RECREATE_SANDBOX: "1", - NVIDIA_INFERENCE_API_KEY: process.env.NVIDIA_INFERENCE_API_KEY ?? "", + NVIDIA_API_KEY: process.env.NVIDIA_API_KEY ?? "", }, - redactionValues: [process.env.NVIDIA_INFERENCE_API_KEY ?? ""], + redactionValues: [process.env.NVIDIA_API_KEY ?? ""], timeoutMs: 20 * 60_000, }, ); @@ -528,7 +528,7 @@ async function assertGatewayRecovery(host: HostCliClient, sandboxName: string): liveTest( "sandbox operations preserve list/status/logs/recovery/multi-sandbox contracts", async ({ artifacts, cleanup, environment, host, sandbox, secrets, skip }) => { - secrets.required("NVIDIA_INFERENCE_API_KEY"); + secrets.required("NVIDIA_API_KEY"); await artifacts.writeJson("scenario.json", { id: "sandbox-operations", diff --git a/test/e2e-scenario/live/sandbox-rebuild.test.ts b/test/e2e-scenario/live/sandbox-rebuild.test.ts index 86003625cdb..8acb4c7d74f 100644 --- a/test/e2e-scenario/live/sandbox-rebuild.test.ts +++ b/test/e2e-scenario/live/sandbox-rebuild.test.ts @@ -48,7 +48,7 @@ function sandboxRebuildEnv(apiKey: string, extra: NodeJS.ProcessEnv = {}): NodeJ return { ...buildAvailabilityProbeEnv(), ...extra, - NVIDIA_INFERENCE_API_KEY: apiKey, + NVIDIA_API_KEY: apiKey, NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1", NEMOCLAW_NON_INTERACTIVE: "1", NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, @@ -86,10 +86,8 @@ test.skipIf(!shouldRunLiveE2EScenarios())( stateValidation, }) => { assertTestOwnedSandboxName(); - const apiKey = secrets.required("NVIDIA_INFERENCE_API_KEY"); - expect(apiKey.startsWith("nvapi-"), "NVIDIA_INFERENCE_API_KEY must start with nvapi-").toBe( - true, - ); + const apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); const dockerInfo = await host.command("docker", ["info"], { artifactName: "prereq-docker-info", diff --git a/test/e2e-scenario/live/sandbox-survival.test.ts b/test/e2e-scenario/live/sandbox-survival.test.ts index 52e415d9df0..6fe50badc57 100644 --- a/test/e2e-scenario/live/sandbox-survival.test.ts +++ b/test/e2e-scenario/live/sandbox-survival.test.ts @@ -48,7 +48,7 @@ function extractSemver(raw: string): string | undefined { function installEnv(apiKey: string): NodeJS.ProcessEnv { return { ...buildAvailabilityProbeEnv(), - NVIDIA_INFERENCE_API_KEY: apiKey, + NVIDIA_API_KEY: apiKey, NEMOCLAW_NON_INTERACTIVE: "1", NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1", NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, @@ -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 apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); await artifacts.writeJson("scenario.json", { id: "sandbox-survival", @@ -119,9 +117,9 @@ test.skipIf(!shouldRunLiveE2EScenarios())( const modelsReachable = await host.command( "curl", - ["-sf", "--max-time", "10", "https://inference-api.nvidia.com/v1/models"], + ["-sf", "--max-time", "10", "https://integrate.api.nvidia.com/v1/models"], { - artifactName: "prereq-inference-api-models", + artifactName: "prereq-integrate-api-models", env: buildAvailabilityProbeEnv(), redactionValues: [apiKey], timeoutMs: 15_000, diff --git a/test/e2e-scenario/live/shields-config.test.ts b/test/e2e-scenario/live/shields-config.test.ts index 567e66c3b4d..a8816d54c9a 100644 --- a/test/e2e-scenario/live/shields-config.test.ts +++ b/test/e2e-scenario/live/shields-config.test.ts @@ -245,10 +245,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 apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); await cleanupSandbox(host, sandbox, "pre-cleanup"); cleanup.add(`destroy shields-config sandbox ${SANDBOX_NAME}`, async () => { @@ -261,7 +259,7 @@ RUN_SHIELDS_TEST( { artifactName: "phase-1-install-shields-config", env: commandEnv({ - NVIDIA_INFERENCE_API_KEY: apiKey, + NVIDIA_API_KEY: apiKey, 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..6ef02c350b8 100644 --- a/test/e2e-scenario/live/skill-agent.test.ts +++ b/test/e2e-scenario/live/skill-agent.test.ts @@ -220,10 +220,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 apiKey = secrets.required("NVIDIA_API_KEY"); + expect(apiKey.startsWith("nvapi-"), "NVIDIA_API_KEY must start with nvapi-").toBe(true); await artifacts.writeJson("scenario.json", { id: "skill-agent", @@ -232,7 +230,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_API_KEY is present and nvapi-prefixed", "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,7 +296,7 @@ runSkillAgentTest( artifactName: "onboard-skill-agent", env: { ...buildAvailabilityProbeEnv(), - NVIDIA_INFERENCE_API_KEY: apiKey, + NVIDIA_API_KEY: apiKey, NEMOCLAW_AGENT: "openclaw", NEMOCLAW_PROVIDER: "cloud", NEMOCLAW_SANDBOX_NAME: SANDBOX_NAME, @@ -353,7 +351,7 @@ runSkillAgentTest( cwd: REPO_ROOT, env: { ...buildAvailabilityProbeEnv(), - NVIDIA_INFERENCE_API_KEY: apiKey, + NVIDIA_API_KEY: apiKey, SANDBOX_NAME, SKILL_ID, VERIFY_TOKEN: VERIFY_PHRASE, diff --git a/test/e2e-scenario/live/token-rotation.test.ts b/test/e2e-scenario/live/token-rotation.test.ts index 2b1d77bd1f0..a35f7db82cf 100644 --- a/test/e2e-scenario/live/token-rotation.test.ts +++ b/test/e2e-scenario/live/token-rotation.test.ts @@ -155,7 +155,7 @@ function assertTokenPairsDiffer(): void { function redactionValues(): string[] { return [ "token-rotation-compatible-e2e", - process.env.NVIDIA_INFERENCE_API_KEY, + process.env.NVIDIA_API_KEY, process.env.GITHUB_TOKEN, ...Object.values(TOKEN_A), ...Object.values(TOKEN_B), @@ -304,7 +304,7 @@ liveTest( resources: [ "Docker", "install.sh/OpenShell", - "NVIDIA_INFERENCE_API_KEY or fake OpenAI-compatible endpoint", + "NVIDIA_API_KEY or fake OpenAI-compatible endpoint", "fake messaging tokens", ], }, diff --git a/test/e2e-scenario/live/whatsapp-qr-compact.test.ts b/test/e2e-scenario/live/whatsapp-qr-compact.test.ts index 1272b9a519a..09445602370 100644 --- a/test/e2e-scenario/live/whatsapp-qr-compact.test.ts +++ b/test/e2e-scenario/live/whatsapp-qr-compact.test.ts @@ -15,7 +15,7 @@ import { testTimeoutOptions } from "../../helpers/timeouts"; // @openclaw/whatsapp versions bundled by Dockerfile.base and measures the real // upstream terminal QR renderer with and without the NemoClaw compact preload. // It intentionally does not require a WhatsApp account, phone scan, sandbox, -// Docker, or NVIDIA_INFERENCE_API_KEY: the legacy contract is the renderer boundary. +// Docker, or NVIDIA_API_KEY: the legacy contract is the renderer boundary. const REPO_ROOT = path.resolve(import.meta.dirname, "../../.."); const DOCKERFILE_BASE = path.join(REPO_ROOT, "Dockerfile.base"); diff --git a/test/e2e-scenario/manifests/hermes-nvidia-discord.yaml b/test/e2e-scenario/manifests/hermes-nvidia-discord.yaml index d40d2906689..535506ae400 100644 --- a/test/e2e-scenario/manifests/hermes-nvidia-discord.yaml +++ b/test/e2e-scenario/manifests/hermes-nvidia-discord.yaml @@ -22,5 +22,5 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY - DISCORD_BOT_TOKEN diff --git a/test/e2e-scenario/manifests/hermes-nvidia-slack.yaml b/test/e2e-scenario/manifests/hermes-nvidia-slack.yaml index 584418d0037..1715c5e3640 100644 --- a/test/e2e-scenario/manifests/hermes-nvidia-slack.yaml +++ b/test/e2e-scenario/manifests/hermes-nvidia-slack.yaml @@ -22,6 +22,6 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY - SLACK_BOT_TOKEN - SLACK_APP_TOKEN diff --git a/test/e2e-scenario/manifests/hermes-nvidia.yaml b/test/e2e-scenario/manifests/hermes-nvidia.yaml index 6fa4ed0af7a..caee7a33083 100644 --- a/test/e2e-scenario/manifests/hermes-nvidia.yaml +++ b/test/e2e-scenario/manifests/hermes-nvidia.yaml @@ -21,4 +21,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-brave.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-brave.yaml index baf95271874..f6fb1151a38 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-brave.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-brave.yaml @@ -23,5 +23,5 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY - BRAVE_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-brev-launchable.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-brev-launchable.yaml index 9420693034b..9f3da8e72f1 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-brev-launchable.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-brev-launchable.yaml @@ -23,4 +23,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-custom-policies.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-custom-policies.yaml index c44f0a5c47d..091f76884b8 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-custom-policies.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-custom-policies.yaml @@ -26,4 +26,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-discord.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-discord.yaml index c90896c3b49..f5ec7d45f2f 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-discord.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-discord.yaml @@ -22,5 +22,5 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY - DISCORD_BOT_TOKEN diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-double-provider-switch.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-double-provider-switch.yaml index f2b7a705acf..687a2608d8f 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-double-provider-switch.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-double-provider-switch.yaml @@ -22,4 +22,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-double-same-provider.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-double-same-provider.yaml index 2488fcc1812..fa951a0d7d9 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-double-same-provider.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-double-same-provider.yaml @@ -22,4 +22,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-gateway-port-conflict.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-gateway-port-conflict.yaml index b11018987a6..c86e5c963d9 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-gateway-port-conflict.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-gateway-port-conflict.yaml @@ -24,4 +24,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-invalid-key.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-invalid-key.yaml index c8423359e77..7c881c8edf1 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-invalid-key.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-invalid-key.yaml @@ -22,4 +22,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-macos.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-macos.yaml index 14471421e17..06068fb6335 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-macos.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-macos.yaml @@ -21,4 +21,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-no-docker-negative.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-no-docker-negative.yaml index 0b8c20c05ba..cc26672a362 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-no-docker-negative.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-no-docker-negative.yaml @@ -22,4 +22,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-post-reboot-recovery.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-post-reboot-recovery.yaml index 8c264d76122..9e4d6f664cf 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-post-reboot-recovery.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-post-reboot-recovery.yaml @@ -40,4 +40,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-rebuild.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-rebuild.yaml index 7261bc157c8..8cf00c198fc 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-rebuild.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-rebuild.yaml @@ -24,4 +24,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-repair.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-repair.yaml index c1b53f9110b..e783edd65ab 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-repair.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-repair.yaml @@ -22,4 +22,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-resume.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-resume.yaml index bd1d31e011e..3ba269666c5 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-resume.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-resume.yaml @@ -22,4 +22,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-slack.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-slack.yaml index e82e9483f7e..100ea3e3370 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-slack.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-slack.yaml @@ -22,5 +22,5 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY - SLACK_BOT_TOKEN diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-telegram.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-telegram.yaml index 7484f111904..59c5676239b 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-telegram.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-telegram.yaml @@ -22,5 +22,5 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY - TELEGRAM_BOT_TOKEN diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-token-rotation.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-token-rotation.yaml index 34c1789ed20..bc9d6d6e402 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-token-rotation.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-token-rotation.yaml @@ -22,4 +22,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia-wsl.yaml b/test/e2e-scenario/manifests/openclaw-nvidia-wsl.yaml index 035a811c7f5..74b7563a801 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia-wsl.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia-wsl.yaml @@ -21,4 +21,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/manifests/openclaw-nvidia.yaml b/test/e2e-scenario/manifests/openclaw-nvidia.yaml index f865485aaab..30080e9db3b 100644 --- a/test/e2e-scenario/manifests/openclaw-nvidia.yaml +++ b/test/e2e-scenario/manifests/openclaw-nvidia.yaml @@ -21,4 +21,4 @@ spec: state: workspaceRef: default credentialRefs: - - NVIDIA_INFERENCE_API_KEY + - NVIDIA_API_KEY diff --git a/test/e2e-scenario/scenarios/scenarios/baseline.ts b/test/e2e-scenario/scenarios/scenarios/baseline.ts index da0e11de404..f4b3c4209cb 100644 --- a/test/e2e-scenario/scenarios/scenarios/baseline.ts +++ b/test/e2e-scenario/scenarios/scenarios/baseline.ts @@ -68,7 +68,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke", "inference", "credentials"], description: "Ubuntu repo checkout with Docker and cloud OpenClaw onboarding.", - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], }, { id: "ubuntu-repo-cloud-hermes", @@ -76,7 +76,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-hermes"), expectedStateId: "cloud-hermes-ready", suiteIds: ["smoke", "inference", "hermes-specific"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], }, { id: "gpu-repo-local-ollama-openclaw", @@ -94,7 +94,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ onboardingAssertionIds: ["base-installed"], suiteIds: ["platform-macos"], runnerRequirements: ["macos-latest"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], skippedCapabilities: macosDockerSkipped, }, { @@ -104,7 +104,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke", "platform-wsl"], runnerRequirements: ["windows-latest", "wsl2"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], }, { id: "brev-launchable-cloud-openclaw", @@ -113,7 +113,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke", "inference"], runnerRequirements: ["ubuntu-latest", "brev-api-token", "launchable-image"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], }, { id: "ubuntu-no-docker-preflight-negative", @@ -122,7 +122,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ expectedStateId: "preflight-failure-no-sandbox", onboardingAssertionIds: ["base-installed", "preflight-expected-failed"], suiteIds: [], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], expectedFailure: { phase: "preflight", errorClass: "docker-missing", @@ -144,7 +144,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDockerLifecycle("cloud-openclaw", "rebuild-current-version"), expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke", "rebuild", "upgrade"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], }, { // Failing-test-first regression scaffold for #4423. After @@ -178,7 +178,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDockerLifecycle("cloud-openclaw", "post-reboot-recovery"), expectedStateId: "post-reboot-recovery-ready", suiteIds: ["smoke"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], description: "Failing-test-first guard for #4423: post-reboot recovery must preserve " + "the local registry entry and restart the labeled Docker container.", @@ -197,7 +197,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-nvidia-openclaw-brave"), expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY", "BRAVE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY", "BRAVE_API_KEY"], }, { id: "ubuntu-repo-cloud-openclaw-telegram", @@ -205,7 +205,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-nvidia-openclaw-telegram"), expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke", "messaging-telegram"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY", "TELEGRAM_BOT_TOKEN"], + requiredSecrets: ["NVIDIA_API_KEY", "TELEGRAM_BOT_TOKEN"], }, { id: "ubuntu-repo-cloud-openclaw-discord", @@ -213,7 +213,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-nvidia-openclaw-discord"), expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke", "messaging-discord"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY", "DISCORD_BOT_TOKEN"], + requiredSecrets: ["NVIDIA_API_KEY", "DISCORD_BOT_TOKEN"], }, { id: "ubuntu-repo-cloud-openclaw-slack", @@ -221,7 +221,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-nvidia-openclaw-slack"), expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke", "messaging-slack"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY", "SLACK_BOT_TOKEN"], + requiredSecrets: ["NVIDIA_API_KEY", "SLACK_BOT_TOKEN"], }, { id: "ubuntu-repo-cloud-hermes-discord", @@ -229,7 +229,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-nvidia-hermes-discord"), expectedStateId: "cloud-hermes-ready", suiteIds: ["smoke"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY", "DISCORD_BOT_TOKEN"], + requiredSecrets: ["NVIDIA_API_KEY", "DISCORD_BOT_TOKEN"], }, { id: "ubuntu-repo-cloud-hermes-slack", @@ -237,7 +237,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-nvidia-hermes-slack"), expectedStateId: "cloud-hermes-ready", suiteIds: ["smoke"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY", "SLACK_BOT_TOKEN", "SLACK_APP_TOKEN"], + requiredSecrets: ["NVIDIA_API_KEY", "SLACK_BOT_TOKEN", "SLACK_APP_TOKEN"], }, { id: "ubuntu-repo-cloud-openclaw-resume", @@ -245,7 +245,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-nvidia-openclaw-resume-after-interrupt"), expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], }, { id: "ubuntu-repo-cloud-openclaw-repair", @@ -253,7 +253,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-nvidia-openclaw-repair-existing-config"), expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], }, { id: "ubuntu-repo-cloud-openclaw-double-same-provider", @@ -261,7 +261,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-nvidia-openclaw-double-same-provider"), expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], }, { id: "ubuntu-repo-cloud-openclaw-double-provider-switch", @@ -269,7 +269,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-nvidia-openclaw-double-provider-switch"), expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], }, { id: "ubuntu-repo-cloud-openclaw-token-rotation", @@ -277,7 +277,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ environment: ubuntuRepoDocker("cloud-nvidia-openclaw-token-rotation"), expectedStateId: "cloud-openclaw-ready", suiteIds: ["smoke", "messaging-token-rotation"], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], }, { id: "ubuntu-repo-cloud-openclaw-custom-policies", @@ -293,7 +293,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ "model-router", "snapshot-lifecycle", ], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], }, { id: "ubuntu-invalid-nvidia-key-negative", @@ -302,7 +302,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ expectedStateId: "onboarding-failure-invalid-nvidia-key", onboardingAssertionIds: ["base-installed"], suiteIds: [], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], expectedFailure: { phase: "onboarding", errorClass: "invalid-nvidia-api-key", @@ -316,7 +316,7 @@ const canonicalScenarioInputs: CanonicalScenarioInput[] = [ expectedStateId: "onboarding-failure-gateway-port-conflict", onboardingAssertionIds: ["base-installed"], suiteIds: [], - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], expectedFailure: { phase: "onboarding", errorClass: "gateway-port-conflict", diff --git a/test/e2e-scenario/scenarios/types.ts b/test/e2e-scenario/scenarios/types.ts index a72361031fb..a95f928f97d 100644 --- a/test/e2e-scenario/scenarios/types.ts +++ b/test/e2e-scenario/scenarios/types.ts @@ -239,7 +239,7 @@ export interface PhaseAction { // spawn. See fixtures/redaction.ts. Each entry must match the // secret-key shape; the fixture layer rejects non-secret names so the // allowlist-vs-declared-secret boundary stays honest. Cloud install - // declares ["NVIDIA_INFERENCE_API_KEY"]; slack onboarding declares the slack + // declares ["NVIDIA_API_KEY"]; slack onboarding declares the slack // tokens it actually needs; etc. secretEnv?: readonly string[]; } diff --git a/test/e2e-scenario/support-tests/docker-probe.test.ts b/test/e2e-scenario/support-tests/docker-probe.test.ts index 128c994b797..309893138ee 100644 --- a/test/e2e-scenario/support-tests/docker-probe.test.ts +++ b/test/e2e-scenario/support-tests/docker-probe.test.ts @@ -28,7 +28,7 @@ describe("DockerProbe secret hygiene", () => { DOCKER_HOST: "unix:///tmp/docker.sock", DOCKER_CONTEXT: "desktop-linux", DOCKERHUB_TOKEN: "dockerhub-secret-token", - NVIDIA_INFERENCE_API_KEY: "nvapi-secret-value", + NVIDIA_API_KEY: "nvapi-secret-value", RANDOM_SECRET: "other-secret-value", }, "/tmp/docker-config", @@ -42,19 +42,19 @@ describe("DockerProbe secret hygiene", () => { DOCKER_CONFIG: "/tmp/docker-config", }); expect(env).not.toHaveProperty("DOCKERHUB_TOKEN"); - expect(env).not.toHaveProperty("NVIDIA_INFERENCE_API_KEY"); + expect(env).not.toHaveProperty("NVIDIA_API_KEY"); expect(env).not.toHaveProperty("RANDOM_SECRET"); }); it("redacts secret-shaped Docker diagnostics before artifacts are written", () => { const secret = "nvapi-supersecret-token"; - const secrets = new SecretStore({ NVIDIA_INFERENCE_API_KEY: secret }, (message) => { + const secrets = new SecretStore({ NVIDIA_API_KEY: secret }, (message) => { throw new Error(message ?? "unexpected skip"); }); const result = redactDockerProbeResult( { - command: ["docker", "run", "--env", `NVIDIA_INFERENCE_API_KEY=${secret}`], + command: ["docker", "run", "--env", `NVIDIA_API_KEY=${secret}`], exitCode: 1, signal: null, stdout: `stdout ${secret}`, diff --git a/test/e2e-scenario/support-tests/e2e-fixture-context.test.ts b/test/e2e-scenario/support-tests/e2e-fixture-context.test.ts index 294ab80d78e..69db753193a 100644 --- a/test/e2e-scenario/support-tests/e2e-fixture-context.test.ts +++ b/test/e2e-scenario/support-tests/e2e-fixture-context.test.ts @@ -160,7 +160,7 @@ describe("E2E fixture primitives", () => { it("secret store redacts sensitive env values and skips missing required secrets", () => { const canonicalToken = `${"nv"}${"api"}-${"a".repeat(24)}`; const store = new SecretStore( - { NVIDIA_INFERENCE_API_KEY: "nv-secret", PLAIN_VALUE: "visible" }, + { NVIDIA_API_KEY: "nv-secret", PLAIN_VALUE: "visible" }, (note?: string): never => { throw new Error(note ?? "skipped"); }, diff --git a/test/e2e-scenario/support-tests/e2e-manifests.test.ts b/test/e2e-scenario/support-tests/e2e-manifests.test.ts index ed3e57aaa36..3b51eccd947 100644 --- a/test/e2e-scenario/support-tests/e2e-manifests.test.ts +++ b/test/e2e-scenario/support-tests/e2e-manifests.test.ts @@ -47,7 +47,7 @@ describe("NemoClawInstance manifests", () => { spec: { setup: { install: { source: "repo-current" } }, onboarding: { agent: "openclaw", provider: "nvidia", apiKey: "nvapi-literal-secret" }, - state: { credentialRefs: ["NVIDIA_INFERENCE_API_KEY"] }, + state: { credentialRefs: ["NVIDIA_API_KEY"] }, }, }; diff --git a/test/e2e-scenario/support-tests/e2e-phase-environment.test.ts b/test/e2e-scenario/support-tests/e2e-phase-environment.test.ts index 576ab316a16..acf00a359d5 100644 --- a/test/e2e-scenario/support-tests/e2e-phase-environment.test.ts +++ b/test/e2e-scenario/support-tests/e2e-phase-environment.test.ts @@ -209,11 +209,11 @@ describe("environment phase fixture", () => { }); it("scopes availability probe env instead of inheriting unrelated secrets", async () => { - const previousSecret = process.env.NVIDIA_INFERENCE_API_KEY; + const previousSecret = process.env.NVIDIA_API_KEY; const previousDockerHost = process.env.DOCKER_HOST; const previousHome = process.env.HOME; const previousPath = process.env.PATH; - process.env.NVIDIA_INFERENCE_API_KEY = "must-not-leak"; + process.env.NVIDIA_API_KEY = "must-not-leak"; process.env.DOCKER_HOST = "unix:///tmp/e2e-docker.sock"; process.env.HOME = "/tmp/e2e-home"; process.env.PATH = "/usr/bin"; @@ -231,15 +231,15 @@ describe("environment phase fixture", () => { expect(dockerEnv).toMatchObject({ DOCKER_HOST: "unix:///tmp/e2e-docker.sock" }); expect(cliEnv?.PATH).toBe("/tmp/e2e-home/.local/bin:/usr/bin"); expect(dockerEnv?.PATH).toBe("/tmp/e2e-home/.local/bin:/usr/bin"); - expect(cliEnv).not.toHaveProperty("NVIDIA_INFERENCE_API_KEY"); - expect(dockerEnv).not.toHaveProperty("NVIDIA_INFERENCE_API_KEY"); + expect(cliEnv).not.toHaveProperty("NVIDIA_API_KEY"); + expect(dockerEnv).not.toHaveProperty("NVIDIA_API_KEY"); expect(runner.calls[0]?.options?.inheritEnv).toBeUndefined(); expect(runner.calls[1]?.options?.inheritEnv).toBeUndefined(); } finally { if (previousSecret === undefined) { - delete process.env.NVIDIA_INFERENCE_API_KEY; + delete process.env.NVIDIA_API_KEY; } else { - process.env.NVIDIA_INFERENCE_API_KEY = previousSecret; + process.env.NVIDIA_API_KEY = previousSecret; } if (previousDockerHost === undefined) { delete process.env.DOCKER_HOST; diff --git a/test/e2e-scenario/support-tests/e2e-phase-onboarding.test.ts b/test/e2e-scenario/support-tests/e2e-phase-onboarding.test.ts index bb472b6f0dc..7475fd0a9ff 100644 --- a/test/e2e-scenario/support-tests/e2e-phase-onboarding.test.ts +++ b/test/e2e-scenario/support-tests/e2e-phase-onboarding.test.ts @@ -120,7 +120,7 @@ describe("onboarding phase fixture", () => { it("runs cloud OpenClaw onboarding with explicit non-interactive inputs", async () => { const runner = new FakeRunner(); runner.enqueue(shellResult(0, "onboarded\n")); - const secrets = new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret-token" }); + const secrets = new FakeSecrets({ NVIDIA_API_KEY: "secret-token" }); const onboard = new OnboardingPhaseFixture(new HostCliClient(runner), secrets); const instance = await onboard.from(ready(), { sandboxName: "e2e-ubuntu-repo-cloud-openclaw" }); @@ -133,7 +133,7 @@ describe("onboarding phase fixture", () => { providerEnv: "cloud", gatewayUrl: "http://127.0.0.1:18789", }); - expect(secrets.requiredCalls).toEqual(["NVIDIA_INFERENCE_API_KEY"]); + expect(secrets.requiredCalls).toEqual(["NVIDIA_API_KEY"]); expect(runner.calls).toEqual([ { command: "nemoclaw", @@ -144,7 +144,7 @@ describe("onboarding phase fixture", () => { NEMOCLAW_AGENT: "openclaw", NEMOCLAW_PROVIDER: "cloud", NEMOCLAW_SANDBOX_NAME: "e2e-ubuntu-repo-cloud-openclaw", - NVIDIA_INFERENCE_API_KEY: "secret-token", + NVIDIA_API_KEY: "secret-token", PATH: expect.any(String), }), redactionValues: ["secret-token"], @@ -159,7 +159,7 @@ describe("onboarding phase fixture", () => { runner.enqueue(shellResult(42, "provider rejected credential")); const onboard = new OnboardingPhaseFixture( new HostCliClient(runner), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret" }), ); await expect(onboard.from(ready())).rejects.toThrow( @@ -173,7 +173,7 @@ describe("onboarding phase fixture", () => { const cleanup = new FakeCleanup(); const onboard = new OnboardingPhaseFixture( new HostCliClient(runner), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret" }), cleanup, ); @@ -200,7 +200,7 @@ describe("onboarding phase fixture", () => { const onboard = new OnboardingPhaseFixture(new HostCliClient(runner), new FakeSecrets()); await expect(onboard.from(ready())).rejects.toThrow( - /missing required E2E secret: NVIDIA_INFERENCE_API_KEY/, + /missing required E2E secret: NVIDIA_API_KEY/, ); expect(runner.calls).toEqual([]); }); @@ -208,7 +208,7 @@ describe("onboarding phase fixture", () => { it("requires Docker for cloud OpenClaw onboarding", async () => { const onboard = new OnboardingPhaseFixture( new HostCliClient(new FakeRunner()), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret" }), ); await expect( @@ -223,7 +223,7 @@ describe("onboarding phase fixture", () => { it("rejects invalid sandbox names before cloud OpenClaw side effects", async () => { const runner = new FakeRunner(); const cleanup = new FakeCleanup(); - const secrets = new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret" }); + const secrets = new FakeSecrets({ NVIDIA_API_KEY: "secret" }); const onboard = new OnboardingPhaseFixture(new HostCliClient(runner), secrets, cleanup); await expect(onboard.from(ready(), { sandboxName: "bad name" })).rejects.toThrow( @@ -241,7 +241,7 @@ describe("onboarding phase fixture", () => { const cleanup = new FakeCleanup(); const onboard = new OnboardingPhaseFixture( new HostCliClient(runner), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret-token" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret-token" }), cleanup, ); @@ -267,7 +267,7 @@ describe("onboarding phase fixture", () => { it("runs the no-Docker negative path with a failing Docker shim", async () => { const runner = new FakeRunner(); runner.enqueue(shellResult(7, "Cannot connect to the Docker daemon")); - const secrets = new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret-token" }); + const secrets = new FakeSecrets({ NVIDIA_API_KEY: "secret-token" }); const cleanup = new FakeCleanup(); const onboard = new OnboardingPhaseFixture(new HostCliClient(runner), secrets, cleanup); @@ -302,10 +302,10 @@ describe("onboarding phase fixture", () => { NEMOCLAW_AGENT: "openclaw", NEMOCLAW_PROVIDER: "cloud", NEMOCLAW_SANDBOX_NAME: "e2e-no-docker", - NVIDIA_INFERENCE_API_KEY: "secret-token", + NVIDIA_API_KEY: "secret-token", }); expect(runner.calls[0]?.options?.env?.PATH).toContain("e2e-no-docker-"); - expect(secrets.requiredCalls).toEqual(["NVIDIA_INFERENCE_API_KEY"]); + expect(secrets.requiredCalls).toEqual(["NVIDIA_API_KEY"]); expect(cleanup.calls).toHaveLength(1); expect(cleanup.calls[0]?.name).toBe("destroy NemoClaw sandbox e2e-no-docker"); }); @@ -319,7 +319,7 @@ describe("onboarding phase fixture", () => { runner.enqueue(shellResult(7, "Docker is required before onboarding with secret-token")); const onboard = new OnboardingPhaseFixture( new HostCliClient(runner), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret-token" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret-token" }), ); await onboard.from( @@ -349,7 +349,7 @@ describe("onboarding phase fixture", () => { runner.enqueue(shellResult(7, "Docker is not reachable. Please fix Docker and try again.")); const onboard = new OnboardingPhaseFixture( new HostCliClient(runner), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret" }), ); const instance = await onboard.from( @@ -370,7 +370,7 @@ describe("onboarding phase fixture", () => { const runner = new FakeRunner(); const onboard = new OnboardingPhaseFixture( new HostCliClient(runner), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret" }), ); await expect(onboard.from(ready({ onboarding: "cloud-openclaw-no-docker" }))).rejects.toThrow( @@ -389,7 +389,7 @@ describe("onboarding phase fixture", () => { runner.enqueue(shellResult(7, "Docker is required before onboarding")); const onboard = new OnboardingPhaseFixture( new HostCliClient(runner), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret-token" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret-token" }), ); await onboard.from( @@ -423,7 +423,7 @@ describe("onboarding phase fixture", () => { const cleanup = new FakeCleanup(); const onboard = new OnboardingPhaseFixture( new HostCliClient(runner), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret" }), cleanup, ); @@ -457,7 +457,7 @@ describe("onboarding phase fixture", () => { runner.enqueue(shellResult(9, "provider rejected credential")); const onboard = new OnboardingPhaseFixture( new HostCliClient(runner), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret" }), ); await expect( @@ -489,7 +489,7 @@ describe("onboarding phase fixture", () => { runner.enqueue(shellResult(0, "onboarded\n")); const onboard = new OnboardingPhaseFixture( new HostCliClient(runner), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret-token" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret-token" }), undefined, new ArtifactSink(tmp), ); @@ -515,7 +515,7 @@ describe("onboarding phase fixture", () => { try { const onboard = new OnboardingPhaseFixture( new HostCliClient(new FakeRunner()), - new FakeSecrets({ NVIDIA_INFERENCE_API_KEY: "secret" }), + new FakeSecrets({ NVIDIA_API_KEY: "secret" }), undefined, new ArtifactSink(tmp), ); diff --git a/test/e2e-scenario/support-tests/e2e-phase-state-validation.test.ts b/test/e2e-scenario/support-tests/e2e-phase-state-validation.test.ts index 8d7a50d2801..1501991dadb 100644 --- a/test/e2e-scenario/support-tests/e2e-phase-state-validation.test.ts +++ b/test/e2e-scenario/support-tests/e2e-phase-state-validation.test.ts @@ -432,8 +432,8 @@ describe("state-validation phase fixture", () => { }); it("does not pass unrelated secret environment values to status probes", async () => { - const original = process.env.NVIDIA_INFERENCE_API_KEY; - process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-test-secret-value"; + const original = process.env.NVIDIA_API_KEY; + process.env.NVIDIA_API_KEY = "nvapi-test-secret-value"; try { const runner = new FakeRunner(); runner.enqueue(shellResult(0, "nemoclaw v0.0.0\n")); @@ -447,13 +447,13 @@ describe("state-validation phase fixture", () => { for (const call of runner.calls.slice(1)) { expect(call.options).not.toHaveProperty("inheritEnv"); expect(call.options?.env).toEqual(expect.objectContaining({ PATH: expect.any(String) })); - expect(call.options?.env).not.toHaveProperty("NVIDIA_INFERENCE_API_KEY"); + expect(call.options?.env).not.toHaveProperty("NVIDIA_API_KEY"); } } finally { if (original === undefined) { - delete process.env.NVIDIA_INFERENCE_API_KEY; + delete process.env.NVIDIA_API_KEY; } else { - process.env.NVIDIA_INFERENCE_API_KEY = original; + process.env.NVIDIA_API_KEY = original; } } }); diff --git a/test/e2e-scenario/support-tests/e2e-scenario-matrix.test.ts b/test/e2e-scenario/support-tests/e2e-scenario-matrix.test.ts index e9d3d1aaf7d..b46c1e88d36 100644 --- a/test/e2e-scenario/support-tests/e2e-scenario-matrix.test.ts +++ b/test/e2e-scenario/support-tests/e2e-scenario-matrix.test.ts @@ -88,7 +88,7 @@ describe("live Vitest scenario matrix", () => { runtime: "docker-running", onboarding: "cloud-openclaw", expectedStateId: "cloud-openclaw-ready", - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], supported: true, supportReasons: [], pendingRuntimeSuites: ["smoke", "inference", "credentials"], @@ -105,7 +105,7 @@ describe("live Vitest scenario matrix", () => { runtime: "docker-running", onboarding: "cloud-openclaw", expectedStateId: "post-reboot-recovery-ready", - requiredSecrets: ["NVIDIA_INFERENCE_API_KEY"], + requiredSecrets: ["NVIDIA_API_KEY"], supported: true, supportReasons: [], }); 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 41195ebb07a..8b50a24a7df 100644 --- a/test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts +++ b/test/e2e-scenario/support-tests/e2e-scenarios-workflow.test.ts @@ -675,7 +675,7 @@ jobs: env: E2E_ARTIFACT_DIR: \${{ github.workspace }}/.e2e/vitest NEMOCLAW_RUN_E2E_SCENARIOS: "1" - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} steps: - uses: actions/checkout@v4 with: @@ -683,7 +683,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 env: - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} - name: Run Vitest live E2E scenarios env: TEST_FILTER: \${{ inputs.test_filter }} @@ -704,7 +704,7 @@ jobs: env: E2E_ARTIFACT_DIR: \${{ github.workspace }}/.e2e/openshell-version-pin NEMOCLAW_RUN_E2E_SCENARIOS: "0" - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} steps: - uses: actions/checkout@v4 with: @@ -712,12 +712,12 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 env: - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} - name: Install root dependencies run: npm install - name: Run OpenShell version-pin live test env: - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} run: npx vitest run --project e2e-scenarios-live "\${{ inputs.test_filter }}" - name: Upload OpenShell version-pin artifacts uses: actions/upload-artifact@v4 @@ -733,7 +733,7 @@ jobs: env: E2E_ARTIFACT_DIR: \${{ github.workspace }}/.e2e/onboard-negative-paths NEMOCLAW_RUN_E2E_SCENARIOS: "0" - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} steps: - uses: actions/checkout@v4 with: @@ -741,12 +741,12 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 env: - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} - name: Install root dependencies run: npm install - name: Run onboard negative-paths live test env: - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} run: npx vitest run --project e2e-scenarios-live "\${{ inputs.test_filter }}" - name: Upload onboard negative-paths artifacts uses: actions/upload-artifact@v4 @@ -763,7 +763,7 @@ jobs: E2E_ARTIFACT_DIR: \${{ github.workspace }}/.e2e/network-policy NEMOCLAW_CLI_BIN: bin/not-nemoclaw.js NEMOCLAW_RUN_E2E_SCENARIOS: "0" - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} DOCKERHUB_USERNAME: \${{ secrets.DOCKERHUB_USERNAME }} DOCKERHUB_TOKEN: \${{ secrets.DOCKERHUB_TOKEN }} GITHUB_TOKEN: \${{ github.token }} @@ -778,7 +778,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 env: - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} - name: Install root dependencies run: npm install - name: Build CLI @@ -789,7 +789,7 @@ jobs: run: echo install - name: Run network-policy live test env: - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} run: npx vitest run --project e2e-scenarios-live "\${{ inputs.test_filter }}" - name: Upload network-policy artifacts uses: actions/upload-artifact@v4 @@ -807,7 +807,7 @@ jobs: E2E_ARTIFACT_DIR: \${{ github.workspace }}/.e2e/double-onboard NEMOCLAW_CLI_BIN: ./bad-cli.js NEMOCLAW_RUN_E2E_SCENARIOS: "0" - NVIDIA_INFERENCE_API_KEY: \${{ secrets.NVIDIA_INFERENCE_API_KEY }} + NVIDIA_API_KEY: \${{ secrets.NVIDIA_API_KEY }} DOCKERHUB_TOKEN: \${{ secrets.DOCKERHUB_TOKEN }} steps: - uses: actions/checkout@v4 @@ -850,13 +850,13 @@ jobs: "workflow_dispatch must not expose legacy test_filter input", "workflow missing generate-matrix job", "live-scenarios job must run on the matrix runner", - "live-scenarios job env must not include NVIDIA_INFERENCE_API_KEY", + "live-scenarios job env must not include NVIDIA_API_KEY", "step 'Run Vitest live E2E scenarios' run script must not interpolate dispatch inputs directly", - "Vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets", + "Vitest step must receive NVIDIA_API_KEY from secrets", "artifact upload must set include-hidden-files: false", "upload-artifact action must be pinned to a full commit SHA", "openshell-version-pin-vitest job must use the shared jobs selector condition", - "network-policy-vitest job env must not include NVIDIA_INFERENCE_API_KEY", + "network-policy-vitest job env must not include NVIDIA_API_KEY", "network-policy-vitest step 'Install OpenShell' env must not include GITHUB_TOKEN", "double-onboard-vitest job env must not include DOCKERHUB_TOKEN", "step 'Run double-onboard live Vitest test' run script must not interpolate dispatch inputs directly", diff --git a/test/e2e-scenario/support-tests/hosted-inference.test.ts b/test/e2e-scenario/support-tests/hosted-inference.test.ts deleted file mode 100644 index eaa2a60bc46..00000000000 --- a/test/e2e-scenario/support-tests/hosted-inference.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { describe, expect, it } from "vitest"; - -import { requireHostedInferenceConfig } from "../fixtures/hosted-inference.ts"; - -function secrets(values: Record) { - return { - required: (name: string) => { - const value = values[name]; - if (!value) throw new Error(`missing ${name}`); - return value; - }, - }; -} - -describe("hosted inference E2E config", () => { - it("uses NVIDIA_INFERENCE_API_KEY as the hosted compatible endpoint source secret", () => { - const cfg = requireHostedInferenceConfig( - secrets({ NVIDIA_INFERENCE_API_KEY: "repo-hosted-key" }), - {}, - ); - - expect(cfg.sourceSecretName).toBe("NVIDIA_INFERENCE_API_KEY"); - expect(cfg.provider).toBe("custom"); - expect(cfg.providerName).toBe("compatible-endpoint"); - expect(cfg.credentialEnv).toBe("COMPATIBLE_API_KEY"); - expect(cfg.env.COMPATIBLE_API_KEY).toBe("repo-hosted-key"); - }); - - it("does not require an nvapi-prefixed source secret", () => { - const cfg = requireHostedInferenceConfig( - secrets({ - NVIDIA_INFERENCE_API_KEY: "sk-compatible-key", - }), - {}, - ); - - expect(cfg.apiKey).toBe("sk-compatible-key"); - expect(cfg.credentialEnv).toBe("COMPATIBLE_API_KEY"); - }); - - it("configures the custom provider route for inference-api.nvidia.com", () => { - const cfg = requireHostedInferenceConfig( - secrets({ NVIDIA_INFERENCE_API_KEY: "repo-hosted-key" }), - { NEMOCLAW_MODEL: "nvidia/custom-model" }, - ); - - expect(cfg.env).toMatchObject({ - NEMOCLAW_PROVIDER: "custom", - NEMOCLAW_ENDPOINT_URL: "https://inference-api.nvidia.com/v1", - NEMOCLAW_MODEL: "nvidia/custom-model", - NEMOCLAW_COMPAT_MODEL: "nvidia/custom-model", - 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..1066725cdda 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 @@ -28,7 +28,7 @@ describe("network-policy transient provider validation classifier", () => { expect( isTransientProviderValidationFailure( - probeOutput("endpoint validation failed: invalid NVIDIA_INFERENCE_API_KEY credential"), + probeOutput("endpoint validation failed: invalid NVIDIA_API_KEY credential"), ), ).toBe(false); expect( diff --git a/test/e2e-script-workflow.test.ts b/test/e2e-script-workflow.test.ts index 5a0b1513716..f0f2a6afdac 100644 --- a/test/e2e-script-workflow.test.ts +++ b/test/e2e-script-workflow.test.ts @@ -45,9 +45,6 @@ const require = createRequire(import.meta.url); const traceTiming = require("../scripts/scorecard/analyze-trace-timing.ts") as TraceTimingAnalyzer; const TRACE_SUMMARY_FILE = "cloud-onboard-trace-timing-summary.json"; -const TRUSTED_REF_GUARD = "github.event_name != 'workflow_dispatch' || inputs.target_ref == ''"; -const GUARDED_HOSTED_INFERENCE_SECRET = `\${{ (${TRUSTED_REF_GUARD}) && secrets.NVIDIA_INFERENCE_API_KEY || '' }}`; -const RAW_HOSTED_INFERENCE_SECRET = "${{ secrets.NVIDIA_INFERENCE_API_KEY }}"; function timingSummary( phases: Record = { "nemoclaw.onboard.phase.preflight": 1000 }, @@ -130,12 +127,6 @@ function traceGithubFixture(options: { return github; } -function envReferencesHostedInferenceSecret(env?: Record): boolean { - return Object.values(env ?? {}).some((value) => - String(value).includes("secrets.NVIDIA_INFERENCE_API_KEY"), - ); -} - // Direct legacy bash E2Es are being migrated toward Vitest coverage. Keep the // top-level shell suite frozen so new coverage starts in the newer E2E surface // unless maintainers intentionally update this allowlist. @@ -394,21 +385,22 @@ describe("E2E reusable workflow contract", () => { it("passes only named secrets to reusable nightly jobs", () => { const reusableJobs = reusableNightlyJobs(nightlyWorkflow); const defaultSecrets = { - NVIDIA_INFERENCE_API_KEY: GUARDED_HOSTED_INFERENCE_SECRET, + NVIDIA_API_KEY: "${{ secrets.NVIDIA_API_KEY }}", BRAVE_API_KEY: "${{ secrets.BRAVE_API_KEY }}", DOCKERHUB_USERNAME: "${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.DOCKERHUB_USERNAME || '' }}", DOCKERHUB_TOKEN: "${{ (github.event_name != 'workflow_dispatch' || inputs.target_ref == '') && secrets.DOCKERHUB_TOKEN || '' }}", }; + const trustedRefGuard = "github.event_name != 'workflow_dispatch' || inputs.target_ref == ''"; const messagingLiveSecrets = { - TELEGRAM_BOT_TOKEN_REAL: `\${{ (${TRUSTED_REF_GUARD}) && secrets.TELEGRAM_BOT_TOKEN_REAL || '' }}`, - TELEGRAM_CHAT_ID_E2E: `\${{ (${TRUSTED_REF_GUARD}) && secrets.TELEGRAM_CHAT_ID_E2E || '' }}`, - DISCORD_BOT_TOKEN_REAL: `\${{ (${TRUSTED_REF_GUARD}) && secrets.DISCORD_BOT_TOKEN_REAL || '' }}`, - DISCORD_CHANNEL_ID_E2E: `\${{ (${TRUSTED_REF_GUARD}) && secrets.DISCORD_CHANNEL_ID_E2E || '' }}`, - SLACK_BOT_TOKEN_REAL: `\${{ (${TRUSTED_REF_GUARD}) && secrets.SLACK_BOT_TOKEN_REAL || '' }}`, - SLACK_APP_TOKEN_REAL: `\${{ (${TRUSTED_REF_GUARD}) && secrets.SLACK_APP_TOKEN_REAL || '' }}`, - SLACK_CHANNEL_ID_E2E: `\${{ (${TRUSTED_REF_GUARD}) && secrets.SLACK_CHANNEL_ID_E2E || '' }}`, + TELEGRAM_BOT_TOKEN_REAL: `\${{ (${trustedRefGuard}) && secrets.TELEGRAM_BOT_TOKEN_REAL || '' }}`, + TELEGRAM_CHAT_ID_E2E: `\${{ (${trustedRefGuard}) && secrets.TELEGRAM_CHAT_ID_E2E || '' }}`, + DISCORD_BOT_TOKEN_REAL: `\${{ (${trustedRefGuard}) && secrets.DISCORD_BOT_TOKEN_REAL || '' }}`, + DISCORD_CHANNEL_ID_E2E: `\${{ (${trustedRefGuard}) && secrets.DISCORD_CHANNEL_ID_E2E || '' }}`, + SLACK_BOT_TOKEN_REAL: `\${{ (${trustedRefGuard}) && secrets.SLACK_BOT_TOKEN_REAL || '' }}`, + SLACK_APP_TOKEN_REAL: `\${{ (${trustedRefGuard}) && secrets.SLACK_APP_TOKEN_REAL || '' }}`, + SLACK_CHANNEL_ID_E2E: `\${{ (${trustedRefGuard}) && secrets.SLACK_CHANNEL_ID_E2E || '' }}`, }; expect(reusableJobs.length).toBeGreaterThan(20); @@ -542,13 +534,7 @@ describe("E2E reusable workflow contract", () => { expect(runStep?.run).toContain("npx vitest run --project e2e-scenarios-live"); expect(runStep?.run).toContain("test/e2e-scenario/live/credential-migration.test.ts"); expect(runStep?.run).not.toContain("test/e2e/test-credential-migration.sh"); - expect(runStep?.env?.NVIDIA_INFERENCE_API_KEY).toBe(GUARDED_HOSTED_INFERENCE_SECRET); - expect(runStep?.env?.NEMOCLAW_PROVIDER).toBe("custom"); - expect(runStep?.env?.NEMOCLAW_ENDPOINT_URL).toBe("https://inference-api.nvidia.com/v1"); - expect(runStep?.env?.NEMOCLAW_MODEL).toBe("nvidia/nvidia/nemotron-3-super-v3"); - expect(runStep?.env?.NEMOCLAW_COMPAT_MODEL).toBe("nvidia/nvidia/nemotron-3-super-v3"); - expect(runStep?.env?.NEMOCLAW_PREFERRED_API).toBe("openai-completions"); - expect(runStep?.env?.COMPATIBLE_API_KEY).toBe(GUARDED_HOSTED_INFERENCE_SECRET); + expect(runStep?.env?.NVIDIA_API_KEY).toBe("${{ secrets.NVIDIA_API_KEY }}"); expect(runStep?.env?.GITHUB_TOKEN).toBeUndefined(); expect(runStep?.env?.NEMOCLAW_RUN_E2E_SCENARIOS).toBe("1"); expect(runStep?.env?.NEMOCLAW_SANDBOX_NAME).toBe("e2e-cred-migration"); @@ -883,102 +869,6 @@ describe("E2E reusable workflow contract", () => { expect(exportStep?.run).toContain('>> "$GITHUB_ENV"'); }); - it("routes reusable hosted inference jobs through the hosted custom endpoint", () => { - const exportStep = runnerWorkflow.jobs.run.steps.find( - (step) => step.name === "Export hosted CI inference environment", - ); - const workflowCall = runnerWorkflow.on?.workflow_call ?? runnerWorkflow.true?.workflow_call; - const hostedJobs = reusableNightlyJobs(nightlyWorkflow).filter( - ([, job]) => String(job.with?.nvidia_api_key) === "true", - ); - - expect(workflowCall?.inputs?.nvidia_api_key).toMatchObject({ - required: false, - type: "boolean", - default: false, - }); - expect(workflowCall?.inputs?.nvidia_secret_as_compatible_api_key).toBeUndefined(); - expect(exportStep?.if).toBe("${{ inputs.nvidia_api_key }}"); - expect(exportStep?.env?.NVIDIA_INFERENCE_API_KEY).toBe(RAW_HOSTED_INFERENCE_SECRET); - expect(exportStep?.run).toContain("withheld for workflow_dispatch target_ref runs"); - expect(exportStep?.run).toContain("NEMOCLAW_E2E_USE_HOSTED_INFERENCE=1"); - expect(exportStep?.run).toContain("NEMOCLAW_PROVIDER=custom"); - expect(exportStep?.run).toContain("NEMOCLAW_ENDPOINT_URL=https://inference-api.nvidia.com/v1"); - expect(exportStep?.run).toContain("NEMOCLAW_MODEL=nvidia/nvidia/nemotron-3-super-v3"); - expect(exportStep?.run).toContain("NEMOCLAW_COMPAT_MODEL=nvidia/nvidia/nemotron-3-super-v3"); - expect(exportStep?.run).toContain("NEMOCLAW_PREFERRED_API=openai-completions"); - expect(exportStep?.run).toContain("COMPATIBLE_API_KEY=%s"); - - expect(hostedJobs.length).toBeGreaterThan(20); - for (const [name, job] of hostedJobs) { - expect(job.with?.nvidia_secret_as_compatible_api_key, name).toBeUndefined(); - } - }); - - it("routes direct hosted-secret jobs through the hosted custom inference endpoint", () => { - const trustedWorkflowSecretExceptions = new Set([ - "issue-4434-tui-unreachable-inference-e2e:Sanitize issue #4434 logs on failure", - ]); - const directSecretSteps = Object.entries(nightlyWorkflow.jobs).flatMap(([jobName, job]) => - job.uses - ? [] - : (job.steps ?? []) - .filter((step) => envReferencesHostedInferenceSecret(step.env)) - .map((step) => ({ jobName, step })), - ); - const directSecretStepNames = directSecretSteps.map( - ({ jobName, step }) => `${jobName}:${step.name ?? ""}`, - ); - - expect(directSecretStepNames).toEqual( - expect.arrayContaining([ - "openclaw-tui-chat-correlation-e2e:Run OpenClaw TUI chat correlation E2E test", - "issue-4434-tui-unreachable-inference-e2e:Run issue #4434 TUI unreachable inference E2E test", - "issue-4434-tui-unreachable-inference-e2e:Sanitize issue #4434 logs on failure", - "token-rotation-e2e:Run token rotation E2E test", - "sandbox-operations-e2e:Run sandbox operations E2E test", - "credential-migration-e2e:Run credential migration Vitest test", - "onboard-repair-e2e:Install NemoClaw", - "onboard-repair-e2e:Run onboard repair E2E test", - "onboard-resume-e2e:Install NemoClaw", - "onboard-resume-e2e:Run onboard resume E2E test", - "onboard-negative-paths-e2e:Install NemoClaw", - "onboard-negative-paths-e2e:Run onboard negative-path E2E test", - "runtime-overrides-e2e:Install NemoClaw", - "runtime-overrides-e2e:Run runtime overrides E2E test", - "credential-sanitization-e2e:Install NemoClaw and onboard sandbox", - "telegram-injection-e2e:Install NemoClaw and onboard sandbox", - "launchable-smoke-e2e:Run launchable install-flow smoke test", - ]), - ); - - expect(directSecretSteps.length).toBeGreaterThanOrEqual(17); - for (const { jobName, step } of directSecretSteps) { - const stepKey = `${jobName}:${step.name ?? ""}`; - expect(step.env?.NVIDIA_INFERENCE_API_KEY, stepKey).toBe(GUARDED_HOSTED_INFERENCE_SECRET); - if (trustedWorkflowSecretExceptions.has(stepKey)) { - expect(step.run, stepKey).toContain("[REDACTED_NVIDIA_INFERENCE_API_KEY]"); - continue; - } - expect(step.env?.NEMOCLAW_PROVIDER, jobName).toBe("custom"); - expect(step.env?.NEMOCLAW_ENDPOINT_URL, jobName).toBe("https://inference-api.nvidia.com/v1"); - expect(step.env?.NEMOCLAW_MODEL, jobName).toBe("nvidia/nvidia/nemotron-3-super-v3"); - expect(step.env?.NEMOCLAW_COMPAT_MODEL, jobName).toBe("nvidia/nvidia/nemotron-3-super-v3"); - expect(step.env?.NEMOCLAW_PREFERRED_API, jobName).toBe("openai-completions"); - expect(step.env?.COMPATIBLE_API_KEY, jobName).toBe(GUARDED_HOSTED_INFERENCE_SECRET); - } - - const runStep = nightlyWorkflow.jobs["token-rotation-e2e"].steps?.find( - (step) => step.name === "Run token rotation E2E test", - ); - const script = readFileSync(new URL("./e2e/test-token-rotation.sh", import.meta.url), "utf8"); - - expect(runStep?.env?.NVIDIA_INFERENCE_API_KEY).toBe(GUARDED_HOSTED_INFERENCE_SECRET); - expect(runStep?.env?.NEMOCLAW_E2E_USE_HOSTED_INFERENCE).toBe("1"); - expect(script).toContain("lib/ci-compatible-inference.sh"); - expect(script).toContain("nemoclaw_e2e_configure_compatible_inference"); - }); - it("keeps converted jobs dispatchable through the reusable workflow", () => { const cloudJob = nightlyWorkflow.jobs["cloud-e2e"]; diff --git a/test/e2e/brev-e2e.test.ts b/test/e2e/brev-e2e.test.ts index f02d0670b48..938dcd5ec4b 100644 --- a/test/e2e/brev-e2e.test.ts +++ b/test/e2e/brev-e2e.test.ts @@ -18,7 +18,7 @@ * npx vitest run --project e2e-branch-validation * * Required env vars: - * NVIDIA_INFERENCE_API_KEY — passed to VM for inference config during onboarding + * NVIDIA_API_KEY — passed to VM for inference config during onboarding * GITHUB_TOKEN — passed to VM for OpenShell binary download * INSTANCE_NAME — Brev instance name (e.g. pr-156-test) * @@ -264,7 +264,7 @@ function sshEnv( ): string { const gpuE2eModel = process.env.NEMOCLAW_GPU_E2E_MODEL || "qwen3.5:9b"; const envParts = [ - `export NVIDIA_INFERENCE_API_KEY='${shellEscape(process.env.NVIDIA_INFERENCE_API_KEY)}'`, + `export NVIDIA_API_KEY='${shellEscape(process.env.NVIDIA_API_KEY)}'`, `export GITHUB_TOKEN='${shellEscape(process.env.GITHUB_TOKEN)}'`, `export NEMOCLAW_NON_INTERACTIVE=1`, `export NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1`, @@ -1028,7 +1028,7 @@ function writeManualRegistry(elapsed: () => string): void { // --- suite ------------------------------------------------------------------ -const REQUIRED_VARS = ["NVIDIA_INFERENCE_API_KEY", "GITHUB_TOKEN", "INSTANCE_NAME"]; +const REQUIRED_VARS = ["NVIDIA_API_KEY", "GITHUB_TOKEN", "INSTANCE_NAME"]; const hasRequiredVars = REQUIRED_VARS.every((key) => process.env[key]); const hasAuthenticatedBrev = (() => { try { diff --git a/test/e2e/e2e-cloud-experimental/checks/03-security-checks.sh b/test/e2e/e2e-cloud-experimental/checks/03-security-checks.sh index 911bcf13da3..dd2a181bdc5 100755 --- a/test/e2e/e2e-cloud-experimental/checks/03-security-checks.sh +++ b/test/e2e/e2e-cloud-experimental/checks/03-security-checks.sh @@ -11,12 +11,10 @@ set -euo pipefail -# The caller can point this check at the active hosted-inference credential. -_api_key_env_name="${NEMOCLAW_E2E_CLOUD_API_KEY_ENV:-NVIDIA_INFERENCE_API_KEY}" -if [[ ! "$_api_key_env_name" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then - printf '%s\n' "03-security-checks: FAIL: invalid cloud API token env var name: ${_api_key_env_name}" >&2 - exit 1 -fi +# Env var name is assembled from fragments so static secret scanners do not match a single literal token. +_api_key_env_name_part1='NVIDIA' +_api_key_env_name_part2='_API_KEY' +_api_key_env_name="${_api_key_env_name_part1}${_api_key_env_name_part2}" : "${!_api_key_env_name:?cloud API token env var must be set (export before running)}" die() { @@ -35,20 +33,14 @@ while IFS= read -r line; do esac done <<<"$ps_lines" -# argv-style leak: NAME=. The caller can override or -# disable this marker with NEMOCLAW_E2E_CLOUD_API_KEY_ARGV_PREFIX. -_key_argv_prefix_marker="${NEMOCLAW_E2E_CLOUD_API_KEY_ARGV_PREFIX:-}" -if [ -z "${NEMOCLAW_E2E_CLOUD_API_KEY_ARGV_PREFIX+x}" ]; then - _key_argv_prefix_marker="$(printf '%.6s' "$_api_key_value")" -fi -if [ -n "$_key_argv_prefix_marker" ]; then - _key_argv_needle="${_api_key_env_name}=${_key_argv_prefix_marker}" - while IFS= read -r line; do - case "$line" in - *"${_key_argv_needle}"*) die "api-key-in-ps: env-style API key argv leak in ps" ;; - esac - done <<<"$ps_lines" -fi +# argv-style leak: NAME= (prefix via escapes; no contiguous vendor prefix literal in source). +_key_argv_prefix_marker=$'\x6e\x76\x61\x70\x69\x2d' +_key_argv_needle="${_api_key_env_name}=${_key_argv_prefix_marker}" +while IFS= read -r line; do + case "$line" in + *"${_key_argv_needle}"*) die "api-key-in-ps: env-style API key argv leak in ps" ;; + esac +done <<<"$ps_lines" printf '%s\n' "03-security-checks: OK (api-key-in-ps)" exit 0 diff --git a/test/e2e/e2e-cloud-experimental/expect-interactive-install.sh b/test/e2e/e2e-cloud-experimental/expect-interactive-install.sh index c7cc96eaacf..3c556208a20 100755 --- a/test/e2e/e2e-cloud-experimental/expect-interactive-install.sh +++ b/test/e2e/e2e-cloud-experimental/expect-interactive-install.sh @@ -4,10 +4,10 @@ # # Thin wrapper: real logic lives in test/e2e/test-e2e-cloud-experimental.sh (Phase 3 expect branch). # -# Prereq: repo checkout at cwd or run from repo; NVIDIA_INFERENCE_API_KEY for cloud onboard unless creds on disk. +# Prereq: repo checkout at cwd or run from repo; NVIDIA_API_KEY for cloud onboard unless creds on disk. # # Usage (full suite; Phase 3 is interactive by default in test-e2e-cloud-experimental.sh — this wrapper is optional): -# NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/e2e-cloud-experimental/expect-interactive-install.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/e2e-cloud-experimental/expect-interactive-install.sh # # Offline expect-only smoke: # DEMO_FAKE_ONLY=1 bash test/e2e/e2e-cloud-experimental/expect-interactive-install.sh diff --git a/test/e2e/e2e-cloud-experimental/features/skill/add-sandbox-skill.sh b/test/e2e/e2e-cloud-experimental/features/skill/add-sandbox-skill.sh index bdc50e726d3..ef7f52d2471 100755 --- a/test/e2e/e2e-cloud-experimental/features/skill/add-sandbox-skill.sh +++ b/test/e2e/e2e-cloud-experimental/features/skill/add-sandbox-skill.sh @@ -20,7 +20,7 @@ # test/e2e/e2e-cloud-experimental/fixtures/skill-smoke-template.SKILL.md # # After deploy, optional: run one agent turn to prove the skill is used: -# NVIDIA_INFERENCE_API_KEY=nvapi-... SANDBOX_NAME=... SKILL_ID=... bash test/e2e/e2e-cloud-experimental/features/skill/verify-sandbox-skill-via-agent.sh +# NVIDIA_API_KEY=nvapi-... SANDBOX_NAME=... SKILL_ID=... bash test/e2e/e2e-cloud-experimental/features/skill/verify-sandbox-skill-via-agent.sh # # Exit code: # 0 = add + query succeeded diff --git a/test/e2e/e2e-cloud-experimental/features/skill/verify-sandbox-skill-via-agent.sh b/test/e2e/e2e-cloud-experimental/features/skill/verify-sandbox-skill-via-agent.sh index fa90daab2b3..a88e31bea65 100755 --- a/test/e2e/e2e-cloud-experimental/features/skill/verify-sandbox-skill-via-agent.sh +++ b/test/e2e/e2e-cloud-experimental/features/skill/verify-sandbox-skill-via-agent.sh @@ -9,7 +9,7 @@ # (includes SKILL_SMOKE_VERIFY_K9X2). Re-run add-sandbox-skill.sh after template updates. # # Usage (from repo root): -# NVIDIA_INFERENCE_API_KEY=nvapi-... SANDBOX_NAME=test01 SKILL_ID=skill-smoke-fixture \ +# NVIDIA_API_KEY=nvapi-... SANDBOX_NAME=test01 SKILL_ID=skill-smoke-fixture \ # bash test/e2e/e2e-cloud-experimental/features/skill/verify-sandbox-skill-via-agent.sh # # Optional: @@ -37,7 +37,7 @@ ok() { printf '%s\n' "verify-sandbox-skill-via-agent: OK: $*"; } info() { printf '%s\n' "verify-sandbox-skill-via-agent: INFO: $*"; } [ -n "$SANDBOX_NAME" ] || die "set SANDBOX_NAME (or NEMOCLAW_SANDBOX_NAME)" -[ -n "${NVIDIA_INFERENCE_API_KEY:-}" ] || die "set NVIDIA_INFERENCE_API_KEY (needed for inference inside sandbox)" +[ -n "${NVIDIA_API_KEY:-}" ] || die "set NVIDIA_API_KEY (needed for inference inside sandbox)" # Do NOT include ${VERIFY_TOKEN} in the prompt itself. The token must come # from the agent reading the skill's SKILL.md — that is the entire point of @@ -58,7 +58,7 @@ command -v openshell >/dev/null 2>&1 || die "openshell not on PATH" command -v base64 >/dev/null 2>&1 || die "base64 not on PATH" prompt_b64=$(printf '%s' "$PROMPT" | base64 | tr -d '\n') -nv_b64=$(printf '%s' "$NVIDIA_INFERENCE_API_KEY" | base64 | tr -d '\n') +nv_b64=$(printf '%s' "$NVIDIA_API_KEY" | base64 | tr -d '\n') ssh_config="$(mktemp)" trap 'rm -f "$ssh_config"' EXIT @@ -75,7 +75,7 @@ _lock_rm="" if [ "${SKILL_VERIFY_NO_CLEAR_LOCK:-0}" != "1" ]; then _lock_rm="rm -f '/sandbox/.openclaw/agents/main/sessions/${SESSION_ID}.jsonl.lock' 2>/dev/null || true; " fi -remote_cmd="pm=\$(printf '%s' '${prompt_b64}' | base64 -d) || exit 1; nv=\$(printf '%s' '${nv_b64}' | base64 -d) || exit 1; export NVIDIA_INFERENCE_API_KEY=\"\$nv\"; ${_lock_rm}${AGENT_LAUNCHER}openclaw agent --agent main --local -m \"\$pm\" --session-id '${SESSION_ID}'" +remote_cmd="pm=\$(printf '%s' '${prompt_b64}' | base64 -d) || exit 1; nv=\$(printf '%s' '${nv_b64}' | base64 -d) || exit 1; export NVIDIA_API_KEY=\"\$nv\"; ${_lock_rm}${AGENT_LAUNCHER}openclaw agent --agent main --local -m \"\$pm\" --session-id '${SESSION_ID}'" info "Running openclaw agent in sandbox '${SANDBOX_NAME}' (session ${SESSION_ID})..." diff --git a/test/e2e/e2e-cloud-experimental/test-port8080-conflict.sh b/test/e2e/e2e-cloud-experimental/test-port8080-conflict.sh index 03aa92e82fe..67dd4a5f69a 100755 --- a/test/e2e/e2e-cloud-experimental/test-port8080-conflict.sh +++ b/test/e2e/e2e-cloud-experimental/test-port8080-conflict.sh @@ -21,10 +21,10 @@ # NEMOCLAW_SANDBOX_NAME — default: e2e-cloud-experimental # NEMOCLAW_NON_INTERACTIVE — should be 1 (onboard non-interactive) # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 — required for non-interactive onboard/re-onboard -# NVIDIA_INFERENCE_API_KEY — required if onboard reaches cloud inference (restore path) +# NVIDIA_API_KEY — required if onboard reaches cloud inference (restore path) # # Usage: -# NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/e2e-cloud-experimental/test-port8080-conflict.sh +# NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 NVIDIA_API_KEY=nvapi-... bash test/e2e/e2e-cloud-experimental/test-port8080-conflict.sh set -uo pipefail diff --git a/test/e2e/lib/ci-compatible-inference.sh b/test/e2e/lib/ci-compatible-inference.sh deleted file mode 100755 index 01b677d26cd..00000000000 --- a/test/e2e/lib/ci-compatible-inference.sh +++ /dev/null @@ -1,151 +0,0 @@ -#!/bin/bash -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -# CI-only hosted inference shim: live E2E lanes use the repository's -# NVIDIA_INFERENCE_API_KEY secret against the hosted OpenAI-compatible endpoint -# at inference-api.nvidia.com. Keep this helper in test/e2e so the -# product-facing provider/default endpoint remain unchanged. - -NEMOCLAW_E2E_COMPATIBLE_INFERENCE_MODEL_DEFAULT="nvidia/nvidia/nemotron-3-super-v3" -NEMOCLAW_E2E_HOSTED_INFERENCE_PROVIDER_DEFAULT="compatible-endpoint" -NEMOCLAW_E2E_NVIDIA_INFERENCE_MODEL_DEFAULT="nvidia/nemotron-3-super-120b-a12b" - -nemoclaw_e2e_using_compatible_inference() { - if [ "${NEMOCLAW_E2E_USE_HOSTED_INFERENCE:-}" = "1" ]; then - return 0 - fi - case "${NEMOCLAW_PROVIDER:-}" in - build | cloud | nvidia | nvidia-prod) - return 1 - ;; - esac - [ -n "${NVIDIA_INFERENCE_API_KEY:-}" ] && [[ "${NVIDIA_INFERENCE_API_KEY}" != nvapi-* ]] -} - -nemoclaw_e2e_configure_compatible_inference() { - if ! nemoclaw_e2e_using_compatible_inference; then - return 0 - fi - - if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - echo "ERROR: NVIDIA_INFERENCE_API_KEY is required for hosted CI inference" >&2 - return 1 - fi - - export NEMOCLAW_PROVIDER="${NEMOCLAW_PROVIDER:-custom}" - export NEMOCLAW_ENDPOINT_URL="${NEMOCLAW_ENDPOINT_URL:-https://inference-api.nvidia.com/v1}" - export NEMOCLAW_MODEL="${NEMOCLAW_MODEL:-${NEMOCLAW_CLOUD_EXPERIMENTAL_MODEL:-$NEMOCLAW_E2E_COMPATIBLE_INFERENCE_MODEL_DEFAULT}}" - export NEMOCLAW_COMPAT_MODEL="${NEMOCLAW_COMPAT_MODEL:-$NEMOCLAW_MODEL}" - export NEMOCLAW_PREFERRED_API="${NEMOCLAW_PREFERRED_API:-openai-completions}" - export COMPATIBLE_API_KEY="$NVIDIA_INFERENCE_API_KEY" -} - -nemoclaw_e2e_hosted_inference_key() { - printf '%s' "${NVIDIA_INFERENCE_API_KEY:-}" -} - -nemoclaw_e2e_hosted_inference_base_url() { - if nemoclaw_e2e_using_compatible_inference; then - printf '%s' "${NEMOCLAW_ENDPOINT_URL:-https://inference-api.nvidia.com/v1}" - else - printf '%s' "https://inference-api.nvidia.com/v1" - fi -} - -nemoclaw_e2e_expected_route_provider() { - if nemoclaw_e2e_using_compatible_inference; then - printf '%s' "$NEMOCLAW_E2E_HOSTED_INFERENCE_PROVIDER_DEFAULT" - else - printf '%s' "nvidia-prod" - fi -} - -nemoclaw_e2e_strip_ansi() { - if command -v perl >/dev/null 2>&1; then - perl -pe 's/\x1b\][^\a]*(?:\a|\x1b\\)//g; s/\x1b\[[0-9;?]*[ -\/]*[@-~]//g' - else - sed -E $'s/\x1B\\[[0-9;?]*[ -\\/]*[@-~]//g' - fi -} - -nemoclaw_e2e_inference_output_matches() { - local output="$1" - local provider="$2" - local model="${3:-}" - local plain - - plain="$(printf '%s' "$output" | nemoclaw_e2e_strip_ansi)" - grep -Eqi "Provider:[[:space:]]*${provider}" <<<"$plain" || return 1 - [ -z "$model" ] || grep -Fq "$model" <<<"$plain" -} - -nemoclaw_e2e_note_pass() { - if declare -F pass >/dev/null 2>&1; then - pass "$@" - else - printf 'PASS: %s\n' "$*" - fi -} - -nemoclaw_e2e_note_fail() { - if declare -F fail >/dev/null 2>&1; then - fail "$@" - else - printf 'ERROR: %s\n' "$*" >&2 - fi -} - -nemoclaw_e2e_hosted_inference_model() { - if nemoclaw_e2e_using_compatible_inference; then - printf '%s' "${NEMOCLAW_MODEL:-${NEMOCLAW_CLOUD_EXPERIMENTAL_MODEL:-$NEMOCLAW_E2E_COMPATIBLE_INFERENCE_MODEL_DEFAULT}}" - else - printf '%s' "${NEMOCLAW_MODEL:-${NEMOCLAW_CLOUD_EXPERIMENTAL_MODEL:-$NEMOCLAW_E2E_NVIDIA_INFERENCE_MODEL_DEFAULT}}" - fi -} - -nemoclaw_e2e_probe_hosted_inference() { - local base_url key - base_url="$(nemoclaw_e2e_hosted_inference_base_url)" - key="$(nemoclaw_e2e_hosted_inference_key)" - - if nemoclaw_e2e_using_compatible_inference; then - local model payload - model="$(nemoclaw_e2e_hosted_inference_model)" - payload=$( - printf '{"model":"%s","messages":[{"role":"user","content":"Respond with OK."}],"temperature":0,"max_tokens":8}' "$model" - ) - curl -sf --max-time 30 \ - -X POST "${base_url}/chat/completions" \ - -H "Authorization: Bearer $key" \ - -H "Content-Type: application/json" \ - -d "$payload" >/dev/null 2>&1 - return $? - fi - - curl -sf --max-time 10 \ - -H "Authorization: Bearer $key" \ - "${base_url}/models" >/dev/null 2>&1 -} - -nemoclaw_e2e_require_hosted_inference_key() { - local key - key="$(nemoclaw_e2e_hosted_inference_key)" - - if nemoclaw_e2e_using_compatible_inference; then - if [ -n "$key" ]; then - nemoclaw_e2e_note_pass "NVIDIA_INFERENCE_API_KEY is set for hosted CI inference" - else - nemoclaw_e2e_note_fail "NVIDIA_INFERENCE_API_KEY not set - required for hosted CI inference" - return 1 - fi - return 0 - fi - - if [ -n "$key" ] && [[ "$key" == nvapi-* ]]; then - nemoclaw_e2e_note_pass "NVIDIA_INFERENCE_API_KEY is set (starts with nvapi-)" - else - nemoclaw_e2e_note_fail "NVIDIA_INFERENCE_API_KEY not set or invalid - required for live inference" - return 1 - fi -} diff --git a/test/e2e/test-agent-turn-latency-e2e.sh b/test/e2e/test-agent-turn-latency-e2e.sh index 694317f7a1d..ff729d4294a 100755 --- a/test/e2e/test-agent-turn-latency-e2e.sh +++ b/test/e2e/test-agent-turn-latency-e2e.sh @@ -4,13 +4,13 @@ # # Real agent turn latency E2E. # -# Installs one OpenClaw sandbox and one Hermes sandbox against the configured -# hosted inference endpoint, verifies that both are configured for the requested -# model, and times one real model-backed turn through each runtime. +# Installs one OpenClaw sandbox and one Hermes sandbox against NVIDIA Endpoints, +# verifies that both are configured for the requested model, and times one real +# model-backed turn through each runtime. # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set for hosted inference +# - NVIDIA_API_KEY set (real key, starts with nvapi-) # - NEMOCLAW_NON_INTERACTIVE=1 # - NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 # @@ -32,8 +32,6 @@ source "${SCRIPT_DIR}/e2e-timeout.sh" source "${SCRIPT_DIR}/lib/openclaw-json.sh" # shellcheck source=test/e2e/lib/sandbox-teardown.sh source "${SCRIPT_DIR}/lib/sandbox-teardown.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${SCRIPT_DIR}/lib/ci-compatible-inference.sh" # shellcheck source=test/e2e/lib/install-path-refresh.sh source "${SCRIPT_DIR}/lib/install-path-refresh.sh" @@ -93,7 +91,7 @@ PY } strip_ansi() { - nemoclaw_e2e_strip_ansi + python3 -c 'import re, sys; sys.stdout.write(re.sub(r"\x1b\[[0-9;]*m", "", sys.stdin.read()))' } parse_chat_content() { @@ -138,7 +136,8 @@ assert_route() { fi plain_output=$(printf '%s' "$output" | strip_ansi) - if nemoclaw_e2e_inference_output_matches "$plain_output" "$EXPECTED_ROUTE_PROVIDER" "$TURN_MODEL"; then + if grep -Fq "Provider: ${EXPECTED_ROUTE_PROVIDER}" <<<"$plain_output" \ + && grep -Fq "Model: ${TURN_MODEL}" <<<"$plain_output"; then pass "${label}: OpenShell route is ${EXPECTED_ROUTE_PROVIDER} / ${TURN_MODEL}" else fail "${label}: route is not ${EXPECTED_ROUTE_PROVIDER} / ${TURN_MODEL}: ${plain_output:0:400}" @@ -552,14 +551,14 @@ else exit 1 fi +TURN_MODEL="${NEMOCLAW_TURN_LATENCY_MODEL:-${NEMOCLAW_MODEL:-nvidia/nemotron-3-ultra-550b-a55b}}" +TURN_PROVIDER_KEY="${NEMOCLAW_TURN_LATENCY_PROVIDER:-build}" +EXPECTED_ROUTE_PROVIDER="${NEMOCLAW_TURN_LATENCY_ROUTE_PROVIDER:-nvidia-prod}" OPENCLAW_SANDBOX_NAME="${NEMOCLAW_OPENCLAW_TURN_LATENCY_SANDBOX_NAME:-e2e-openclaw-turn-latency}" HERMES_SANDBOX_NAME="${NEMOCLAW_HERMES_TURN_LATENCY_SANDBOX_NAME:-e2e-hermes-turn-latency}" OPENCLAW_INSTALL_LOG="/tmp/nemoclaw-e2e-openclaw-turn-latency-install.log" HERMES_INSTALL_LOG="/tmp/nemoclaw-e2e-hermes-turn-latency-install.log" RESULTS_JSON="/tmp/nemoclaw-e2e-agent-turn-latency.json" -TURN_MODEL="" -TURN_PROVIDER_KEY="" -EXPECTED_ROUTE_PROVIDER="" MAX_TURN_SECONDS="${NEMOCLAW_TURN_LATENCY_MAX_SECONDS:-300}" is_positive_int "$MAX_TURN_SECONDS" || MAX_TURN_SECONDS=300 @@ -576,20 +575,6 @@ HERMES_REPLY="" register_sandbox_for_teardown "$OPENCLAW_SANDBOX_NAME" register_sandbox_for_teardown "$HERMES_SANDBOX_NAME" nemoclaw_ensure_local_bin_on_path -nemoclaw_e2e_configure_compatible_inference || { - fail "Hosted CI inference could not be configured" - finish -} - -if nemoclaw_e2e_using_compatible_inference; then - TURN_MODEL="${NEMOCLAW_TURN_LATENCY_MODEL:-$(nemoclaw_e2e_hosted_inference_model)}" - TURN_PROVIDER_KEY="${NEMOCLAW_TURN_LATENCY_PROVIDER:-custom}" - EXPECTED_ROUTE_PROVIDER="${NEMOCLAW_TURN_LATENCY_ROUTE_PROVIDER:-$(nemoclaw_e2e_expected_route_provider)}" -else - TURN_MODEL="${NEMOCLAW_TURN_LATENCY_MODEL:-${NEMOCLAW_MODEL:-nvidia/nemotron-3-ultra-550b-a55b}}" - TURN_PROVIDER_KEY="${NEMOCLAW_TURN_LATENCY_PROVIDER:-build}" - EXPECTED_ROUTE_PROVIDER="${NEMOCLAW_TURN_LATENCY_ROUTE_PROVIDER:-nvidia-prod}" -fi section "Prerequisites" if docker info >/dev/null 2>&1; then @@ -599,7 +584,10 @@ else finish fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set" +else + fail "NVIDIA_API_KEY not set or invalid" finish fi diff --git a/test/e2e/test-bedrock-runtime-compatible-anthropic.sh b/test/e2e/test-bedrock-runtime-compatible-anthropic.sh index e1cfcdd1eed..2f792f906fc 100755 --- a/test/e2e/test-bedrock-runtime-compatible-anthropic.sh +++ b/test/e2e/test-bedrock-runtime-compatible-anthropic.sh @@ -432,7 +432,7 @@ run_bedrock_onboard() { unset AWS_WEB_IDENTITY_TOKEN_FILE AWS_CONTAINER_CREDENTIALS_RELATIVE_URI unset AWS_CONTAINER_CREDENTIALS_FULL_URI AWS_BEARER_TOKEN_BEDROCK unset AWS_REGION AWS_DEFAULT_REGION - unset NVIDIA_INFERENCE_API_KEY OPENAI_API_KEY ANTHROPIC_API_KEY GEMINI_API_KEY COMPATIBLE_API_KEY + unset NVIDIA_API_KEY OPENAI_API_KEY ANTHROPIC_API_KEY GEMINI_API_KEY COMPATIBLE_API_KEY unset TELEGRAM_BOT_TOKEN DISCORD_BOT_TOKEN SLACK_BOT_TOKEN SLACK_APP_TOKEN destroy_sandbox_best_effort diff --git a/test/e2e/test-brave-search-e2e.sh b/test/e2e/test-brave-search-e2e.sh index 9de1c06aa0a..678fc9b209d 100755 --- a/test/e2e/test-brave-search-e2e.sh +++ b/test/e2e/test-brave-search-e2e.sh @@ -16,7 +16,7 @@ # # Required env (CI injects from secrets): # BRAVE_API_KEY real Brave Search subscription token (skip-suite gate) -# NVIDIA_INFERENCE_API_KEY drives the agent inference turn in B4a +# NVIDIA_API_KEY drives the agent inference turn in B4a # # Secret hygiene: BRAVE_API_KEY is never echoed raw. All output that may # contain it pipes through redact_stream; GitHub Actions auto-mask is the @@ -24,7 +24,7 @@ # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# BRAVE_API_KEY=... NVIDIA_INFERENCE_API_KEY=... \ +# BRAVE_API_KEY=... NVIDIA_API_KEY=... \ # bash test/e2e/test-brave-search-e2e.sh set -uo pipefail diff --git a/test/e2e/test-channels-add-remove.sh b/test/e2e/test-channels-add-remove.sh index 45033ffbd40..1147dc417b1 100755 --- a/test/e2e/test-channels-add-remove.sh +++ b/test/e2e/test-channels-add-remove.sh @@ -16,12 +16,12 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (real key or fake OpenAI endpoint) +# - NVIDIA_API_KEY set (real key or fake OpenAI endpoint) # - NEMOCLAW_NON_INTERACTIVE=1, NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-channels-add-remove.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-channels-add-remove.sh set -uo pipefail @@ -306,11 +306,11 @@ telegram_egress_open() { # ══════════════════════════════════════════════════════════════════ section "Phase 0: Prerequisites" -if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - fail "C0: NVIDIA_INFERENCE_API_KEY is required" +if [ -z "${NVIDIA_API_KEY:-}" ]; then + fail "C0: NVIDIA_API_KEY is required" print_summary fi -pass "C0: NVIDIA_INFERENCE_API_KEY is set" +pass "C0: NVIDIA_API_KEY is set" if [ "${NEMOCLAW_NON_INTERACTIVE:-}" != "1" ]; then fail "C0: NEMOCLAW_NON_INTERACTIVE=1 is required" @@ -446,14 +446,14 @@ export TELEGRAM_REQUIRE_MENTION="$TELEGRAM_REQUIRE_MENTION_VALUE" maybe_skip_telegram_reachability_for_fake_token # Gateway-credential reuse gate. Before the fix, the rebuild preflight -# aborted with "provider credential not found" when NVIDIA_INFERENCE_API_KEY was unset +# aborted with "provider credential not found" when NVIDIA_API_KEY was unset # in the host env even though the inference provider was already registered # in the OpenShell gateway. Drop the key from the env around `channels add` # + rebuild so the post-add rebuild has to reuse the gateway-stored # credential instead of demanding it back on the host. -NVIDIA_INFERENCE_API_KEY_BACKUP="${NVIDIA_INFERENCE_API_KEY:-}" -unset NVIDIA_INFERENCE_API_KEY -info "NVIDIA_INFERENCE_API_KEY unset for gateway-credential-reuse gate; gateway must hold the credential" +NVIDIA_API_KEY_BACKUP="${NVIDIA_API_KEY:-}" +unset NVIDIA_API_KEY +info "NVIDIA_API_KEY unset for gateway-credential-reuse gate; gateway must hold the credential" if nemoclaw "$SANDBOX_NAME" channels add telegram >/tmp/nc-add.log 2>&1; then add_rc=0 @@ -478,8 +478,8 @@ else tail -100 /tmp/nc-rebuild-add.log 2>/dev/null || true # Restore env before bailing so later phases (and operators rerunning # the script interactively) still see the original key. - if [ -n "$NVIDIA_INFERENCE_API_KEY_BACKUP" ]; then - export NVIDIA_INFERENCE_API_KEY="$NVIDIA_INFERENCE_API_KEY_BACKUP" + if [ -n "$NVIDIA_API_KEY_BACKUP" ]; then + export NVIDIA_API_KEY="$NVIDIA_API_KEY_BACKUP" fi print_summary fi @@ -487,17 +487,17 @@ fi # Gateway-credential reuse assertion: the rebuild must not have aborted with # the "provider credential not found" error. if grep -q "provider credential not found" /tmp/nc-rebuild-add.log; then - fail "C3c: REGRESSION — rebuild aborted on missing NVIDIA_INFERENCE_API_KEY despite gateway-registered credential" + fail "C3c: REGRESSION — rebuild aborted on missing NVIDIA_API_KEY despite gateway-registered credential" else - pass "C3c: rebuild reused gateway-stored credential without NVIDIA_INFERENCE_API_KEY" + pass "C3c: rebuild reused gateway-stored credential without NVIDIA_API_KEY" fi # Restore for the remaining phases — `channels remove` + rebuild should # work in the normal env-present case too. -if [ -n "$NVIDIA_INFERENCE_API_KEY_BACKUP" ]; then - export NVIDIA_INFERENCE_API_KEY="$NVIDIA_INFERENCE_API_KEY_BACKUP" +if [ -n "$NVIDIA_API_KEY_BACKUP" ]; then + export NVIDIA_API_KEY="$NVIDIA_API_KEY_BACKUP" fi -unset NVIDIA_INFERENCE_API_KEY_BACKUP +unset NVIDIA_API_KEY_BACKUP # ══════════════════════════════════════════════════════════════════ # Phase 4: Post-add assertions (Test 2 acceptance, regression #3437) diff --git a/test/e2e/test-channels-stop-start.sh b/test/e2e/test-channels-stop-start.sh index c788d224ceb..935ad1521be 100755 --- a/test/e2e/test-channels-stop-start.sh +++ b/test/e2e/test-channels-stop-start.sh @@ -18,13 +18,13 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set +# - NVIDIA_API_KEY set # - NEMOCLAW_NON_INTERACTIVE=1 # - NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-channels-stop-start.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-channels-stop-start.sh set -uo pipefail @@ -826,12 +826,12 @@ run_agent_scenario() { section "Phase 0: Prerequisites" -if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - msg="C0: NVIDIA_INFERENCE_API_KEY is required" +if [ -z "${NVIDIA_API_KEY:-}" ]; then + msg="C0: NVIDIA_API_KEY is required" fail_msg "$msg" print_summary fi -msg="C0: NVIDIA_INFERENCE_API_KEY is set" +msg="C0: NVIDIA_API_KEY is set" pass_msg "$msg" if [ "${NEMOCLAW_NON_INTERACTIVE:-}" != "1" ]; then diff --git a/test/e2e/test-cloud-inference-e2e.sh b/test/e2e/test-cloud-inference-e2e.sh index 8e1a3c4a0bc..651ff67d772 100755 --- a/test/e2e/test-cloud-inference-e2e.sh +++ b/test/e2e/test-cloud-inference-e2e.sh @@ -12,7 +12,7 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (real key, starts with nvapi-) +# - NVIDIA_API_KEY set (real key, starts with nvapi-) # - NEMOCLAW_NON_INTERACTIVE=1, NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 # # Environment: @@ -24,7 +24,7 @@ # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-cloud-inference-e2e.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-cloud-inference-e2e.sh set -uo pipefail @@ -90,9 +90,6 @@ CLOUD_MODEL="${NEMOCLAW_CLOUD_EXPERIMENTAL_MODEL:-nvidia/nemotron-3-super-120b-a . "${E2E_DIR}/lib/sandbox-teardown.sh" # shellcheck source=test/e2e/lib/install-path-refresh.sh . "${E2E_DIR}/lib/install-path-refresh.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${E2E_DIR}/lib/ci-compatible-inference.sh" -nemoclaw_e2e_configure_compatible_inference register_sandbox_for_teardown "$SANDBOX_NAME" # ══════════════════════════════════════════════════════════════════════ @@ -106,9 +103,11 @@ if ! docker info >/dev/null 2>&1; then fi pass "Docker is running" -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -z "${NVIDIA_API_KEY:-}" ] || [[ "${NVIDIA_API_KEY}" != nvapi-* ]]; then + fail "NVIDIA_API_KEY not set or invalid" exit 1 fi +pass "NVIDIA_API_KEY is set" cd "$REPO" || { fail "Could not cd to repo root" diff --git a/test/e2e/test-cloud-onboard-e2e.sh b/test/e2e/test-cloud-onboard-e2e.sh index 84a500e8f1c..5203a3cbdce 100755 --- a/test/e2e/test-cloud-onboard-e2e.sh +++ b/test/e2e/test-cloud-onboard-e2e.sh @@ -13,8 +13,8 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (real key, starts with nvapi-) -# - Network access to inference-api.nvidia.com +# - NVIDIA_API_KEY set (real key, starts with nvapi-) +# - Network access to integrate.api.nvidia.com # # Environment: # NEMOCLAW_NON_INTERACTIVE=1 — required for non-interactive install @@ -32,7 +32,7 @@ # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-cloud-onboard-e2e.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-cloud-onboard-e2e.sh set -uo pipefail @@ -88,12 +88,6 @@ PUBLIC_INSTALL_CWD="${NEMOCLAW_PUBLIC_INSTALL_CWD:-}" . "${E2E_DIR}/lib/sandbox-teardown.sh" # shellcheck source=test/e2e/lib/install-path-refresh.sh . "${E2E_DIR}/lib/install-path-refresh.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${E2E_DIR}/lib/ci-compatible-inference.sh" -nemoclaw_e2e_configure_compatible_inference -if nemoclaw_e2e_using_compatible_inference; then - CLOUD_MODEL="$(nemoclaw_e2e_hosted_inference_model)" -fi register_sandbox_for_teardown "$SANDBOX_NAME" # ══════════════════════════════════════════════════════════════════════ @@ -117,16 +111,17 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set (starts with nvapi-)" +else + fail "NVIDIA_API_KEY not set or invalid — required for cloud onboard" exit 1 fi -HOSTED_INFERENCE_BASE_URL="$(nemoclaw_e2e_hosted_inference_base_url)" - -if nemoclaw_e2e_probe_hosted_inference; then - pass "Network access to ${HOSTED_INFERENCE_BASE_URL}" +if curl -sf --max-time 10 https://integrate.api.nvidia.com/v1/models >/dev/null 2>&1; then + pass "Network access to integrate.api.nvidia.com" else - fail "Cannot reach ${HOSTED_INFERENCE_BASE_URL}" + fail "Cannot reach integrate.api.nvidia.com" exit 1 fi @@ -157,8 +152,8 @@ section "Phase 3: Install via public URL" export NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" export NEMOCLAW_EXPERIMENTAL=1 -export NEMOCLAW_PROVIDER="${NEMOCLAW_PROVIDER:-cloud}" -export NEMOCLAW_MODEL="${NEMOCLAW_MODEL:-$CLOUD_MODEL}" +export NEMOCLAW_PROVIDER=cloud +export NEMOCLAW_MODEL="$CLOUD_MODEL" export NEMOCLAW_POLICY_MODE="${NEMOCLAW_POLICY_MODE:-custom}" export NEMOCLAW_POLICY_PRESETS="${NEMOCLAW_POLICY_PRESETS:-npm,pypi}" @@ -280,12 +275,7 @@ fi # ══════════════════════════════════════════════════════════════════════ section "Phase 4: Sandbox checks (Landlock, security, inference.local)" -if nemoclaw_e2e_using_compatible_inference; then - export NEMOCLAW_E2E_CLOUD_API_KEY_ENV=COMPATIBLE_API_KEY -else - export NEMOCLAW_E2E_CLOUD_API_KEY_ENV=NVIDIA_INFERENCE_API_KEY -fi -export SANDBOX_NAME CLOUD_EXPERIMENTAL_MODEL="$CLOUD_MODEL" REPO NVIDIA_INFERENCE_API_KEY COMPATIBLE_API_KEY +export SANDBOX_NAME CLOUD_EXPERIMENTAL_MODEL="$CLOUD_MODEL" REPO NVIDIA_API_KEY export PATH="/usr/local/bin:${HOME}/.local/bin:${PATH}" shopt -s nullglob diff --git a/test/e2e/test-common-egress-agent-e2e.sh b/test/e2e/test-common-egress-agent-e2e.sh index 53415555a0c..5bb702b2b86 100755 --- a/test/e2e/test-common-egress-agent-e2e.sh +++ b/test/e2e/test-common-egress-agent-e2e.sh @@ -11,7 +11,7 @@ # and the Hermes agent fetches Wikidata through its API-server agent path. # # Required env: -# NVIDIA_INFERENCE_API_KEY hosted inference credential +# NVIDIA_API_KEY real NVIDIA Endpoints key for inference # NEMOCLAW_NON_INTERACTIVE=1 required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 required # @@ -392,10 +392,6 @@ echo " Common Egress Agent E2E" echo " $(date)" echo "============================================================" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/ci-compatible-inference.sh" -nemoclaw_e2e_configure_compatible_inference || summary - section "Phase 0: Prerequisites" load_shell_path info "Repo: $REPO" @@ -406,9 +402,11 @@ if ! docker info >/dev/null 2>&1; then fi pass "Docker is running" -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -z "${NVIDIA_API_KEY:-}" ] || [[ "${NVIDIA_API_KEY}" != nvapi-* ]]; then + fail "NVIDIA_API_KEY not set or invalid" summary fi +pass "NVIDIA_API_KEY is set" if [ "${NEMOCLAW_NON_INTERACTIVE:-}" != "1" ]; then fail "NEMOCLAW_NON_INTERACTIVE=1 is required" diff --git a/test/e2e/test-credential-migration.sh b/test/e2e/test-credential-migration.sh index cd7ddf64c07..64215d1cb48 100755 --- a/test/e2e/test-credential-migration.sh +++ b/test/e2e/test-credential-migration.sh @@ -35,11 +35,11 @@ # Prerequisites: # - Docker running # - openshell + nemoclaw on PATH -# - NVIDIA_INFERENCE_API_KEY set (used as the migrated value) +# - NVIDIA_API_KEY set (used as the migrated value) # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-credential-migration.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-credential-migration.sh set -uo pipefail @@ -93,11 +93,11 @@ register_sandbox_for_teardown "$SANDBOX_NAME" # ══════════════════════════════════════════════════════════════════ section "Phase 0: Prerequisites" -if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - fail "NVIDIA_INFERENCE_API_KEY not set" +if [ -z "${NVIDIA_API_KEY:-}" ]; then + fail "NVIDIA_API_KEY not set" exit 1 fi -pass "NVIDIA_INFERENCE_API_KEY is set" +pass "NVIDIA_API_KEY is set" if ! command -v openshell >/dev/null 2>&1 || ! command -v nemoclaw >/dev/null 2>&1; then info "openshell or nemoclaw not found; running install" @@ -120,7 +120,7 @@ command -v nemoclaw >/dev/null 2>&1 || { } pass "openshell + nemoclaw on PATH" -REAL_API_KEY="$NVIDIA_INFERENCE_API_KEY" +REAL_API_KEY="$NVIDIA_API_KEY" NEMOCLAW_DIR="$HOME/.nemoclaw" LEGACY_FILE="$NEMOCLAW_DIR/credentials.json" @@ -137,7 +137,7 @@ chmod 700 "$NEMOCLAW_DIR" # Tampered fixture: includes an unrelated key the migrator must ignore. cat >"$LEGACY_FILE" </dev/null || stat -f '%i' "$LEGACY_FILE" 2>/dev/null || echo "") [ -n "$LEGACY_INODE_BEFORE" ] && info "Legacy file inode before onboard: $LEGACY_INODE_BEFORE" -# Run onboard WITHOUT NVIDIA_INFERENCE_API_KEY in the env. The only place the value +# Run onboard WITHOUT NVIDIA_API_KEY in the env. The only place the value # can come from is the legacy credentials.json — exactly the migration # path we want to exercise. ONBOARD_LOG="$(mktemp)" ( - unset NVIDIA_INFERENCE_API_KEY + unset NVIDIA_API_KEY NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" \ @@ -200,7 +200,7 @@ fi info "Providers in nemoclaw gateway:" printf '%s\n' "$PROVIDERS_OUT" | indent -# The legacy NVIDIA_INFERENCE_API_KEY should have been registered as one of the +# The legacy NVIDIA_API_KEY should have been registered as one of the # inference providers (nvidia-prod, nvidia-nim, etc. — the exact name # depends on what onboarding chose). Just assert that at least one # provider was registered. diff --git a/test/e2e/test-credential-sanitization.sh b/test/e2e/test-credential-sanitization.sh index e85af483f09..9ccf806060f 100755 --- a/test/e2e/test-credential-sanitization.sh +++ b/test/e2e/test-credential-sanitization.sh @@ -17,15 +17,15 @@ # Prerequisites: # - Docker running # - NemoClaw installed and sandbox running (test-full-e2e.sh Phase 0-3) -# - NVIDIA_INFERENCE_API_KEY set +# - NVIDIA_API_KEY set # - openshell on PATH # # Environment variables: # NEMOCLAW_SANDBOX_NAME — sandbox name (default: e2e-test) -# NVIDIA_INFERENCE_API_KEY — required +# NVIDIA_API_KEY — required # # Usage: -# NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-credential-sanitization.sh +# NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 NVIDIA_API_KEY=nvapi-... bash test/e2e/test-credential-sanitization.sh # # See: https://github.com/NVIDIA/NemoClaw/pull/156 @@ -110,11 +110,11 @@ sandbox_exec() { # ══════════════════════════════════════════════════════════════════ section "Phase 0: Prerequisites" -if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - fail "NVIDIA_INFERENCE_API_KEY not set" +if [ -z "${NVIDIA_API_KEY:-}" ]; then + fail "NVIDIA_API_KEY not set" exit 1 fi -pass "NVIDIA_INFERENCE_API_KEY is set" +pass "NVIDIA_API_KEY is set" if ! command -v openshell >/dev/null 2>&1; then fail "openshell not found on PATH" @@ -193,7 +193,7 @@ cat >"$AUTH_DIR/auth-profiles.json" </dev/null 2>&1; then echo " Total: $TOTAL Pass: $PASS Fail: $FAIL Skip: $SKIP" exit 0 fi -if ! nemoclaw_e2e_configure_compatible_inference; then - fail "hosted CI inference could not be configured" +if [ -z "${NVIDIA_API_KEY:-}" ]; then + skip "NVIDIA_API_KEY not set" echo " Total: $TOTAL Pass: $PASS Fail: $FAIL Skip: $SKIP" - exit 1 + exit 0 fi -if nemoclaw_e2e_using_compatible_inference; then - if ! nemoclaw_e2e_require_hosted_inference_key; then - echo " Total: $TOTAL Pass: $PASS Fail: $FAIL Skip: $SKIP" - exit 1 - fi -else - if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - skip "NVIDIA_INFERENCE_API_KEY not set" - echo " Total: $TOTAL Pass: $PASS Fail: $FAIL Skip: $SKIP" - exit 0 - fi - if [ "${NVIDIA_INFERENCE_API_KEY:0:6}" != "nvapi-" ]; then - skip "NVIDIA_INFERENCE_API_KEY does not start with nvapi-" - echo " Total: $TOTAL Pass: $PASS Fail: $FAIL Skip: $SKIP" - exit 0 - fi +if [ "${NVIDIA_API_KEY:0:6}" != "nvapi-" ]; then + skip "NVIDIA_API_KEY does not start with nvapi-" + echo " Total: $TOTAL Pass: $PASS Fail: $FAIL Skip: $SKIP" + exit 0 fi if [ "${NEMOCLAW_NON_INTERACTIVE:-}" != "1" ]; then skip "NEMOCLAW_NON_INTERACTIVE must be 1; refusing to risk an interactive onboard prompt" diff --git a/test/e2e/test-device-auth-health.sh b/test/e2e/test-device-auth-health.sh index ff7a5922230..23b77768d9b 100755 --- a/test/e2e/test-device-auth-health.sh +++ b/test/e2e/test-device-auth-health.sh @@ -21,13 +21,13 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (real key, starts with nvapi-) -# - Network access to inference-api.nvidia.com +# - NVIDIA_API_KEY set (real key, starts with nvapi-) +# - Network access to integrate.api.nvidia.com # # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 — required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 — required -# NVIDIA_INFERENCE_API_KEY — required +# NVIDIA_API_KEY — required # NEMOCLAW_SANDBOX_NAME — sandbox name (default: e2e-health-auth) # NEMOCLAW_E2E_TIMEOUT_SECONDS — overall timeout (default: 600) # NEMOCLAW_DASHBOARD_PORT — dashboard port (default: 18789) @@ -35,7 +35,7 @@ # Usage: # NEMOCLAW_NON_INTERACTIVE=1 \ # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... \ +# NVIDIA_API_KEY=nvapi-... \ # bash test/e2e/test-device-auth-health.sh # ============================================================================= @@ -123,8 +123,8 @@ sandbox_exec() { # ══════════════════════════════════════════════════════════════════════════════ section "Phase 0: Preflight" -if [[ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]]; then - echo "ERROR: NVIDIA_INFERENCE_API_KEY not set" >&2 +if [[ -z "${NVIDIA_API_KEY:-}" ]]; then + echo "ERROR: NVIDIA_API_KEY not set" >&2 exit 1 fi diff --git a/test/e2e/test-diagnostics.sh b/test/e2e/test-diagnostics.sh index 64f3716b50f..9109f6d9aba 100755 --- a/test/e2e/test-diagnostics.sh +++ b/test/e2e/test-diagnostics.sh @@ -16,7 +16,7 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set +# - NVIDIA_API_KEY set # ============================================================================= set -euo pipefail @@ -99,7 +99,7 @@ install_nemoclaw() { fi log "=== Installing NemoClaw via install.sh ===" NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" \ - NVIDIA_INFERENCE_API_KEY="${NVIDIA_INFERENCE_API_KEY:-nvapi-DUMMY-FOR-INSTALL}" \ + NVIDIA_API_KEY="${NVIDIA_API_KEY:-nvapi-DUMMY-FOR-INSTALL}" \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ bash "$REPO_ROOT/install.sh" --non-interactive --yes-i-accept-third-party-software \ @@ -120,9 +120,9 @@ preflight() { fi log "Docker is running" - local api_key="${NVIDIA_INFERENCE_API_KEY:-}" + local api_key="${NVIDIA_API_KEY:-}" if [[ -z "$api_key" ]]; then - log "ERROR: NVIDIA_INFERENCE_API_KEY not set" + log "ERROR: NVIDIA_API_KEY not set" exit 1 fi @@ -265,9 +265,9 @@ test_diag_01_debug_tarball() { return fi - local real_key="${NVIDIA_INFERENCE_API_KEY:-}" + local real_key="${NVIDIA_API_KEY:-}" if [[ -z "$real_key" ]]; then - skip "TC-DIAG-01: Credential check" "NVIDIA_INFERENCE_API_KEY not set" + skip "TC-DIAG-01: Credential check" "NVIDIA_API_KEY not set" rm -rf "$debug_dir" return fi @@ -387,7 +387,7 @@ test_diag_05_sandbox_config() { test_diag_03_credentials() { log "=== TC-DIAG-03: Credentials List and Reset ===" - local real_key="${NVIDIA_INFERENCE_API_KEY:-}" + local real_key="${NVIDIA_API_KEY:-}" log " Step 1: Running credentials list..." local list_output list_rc=0 @@ -411,7 +411,7 @@ test_diag_03_credentials() { return fi - if echo "$list_output" | grep -qiE "NVIDIA_INFERENCE_API_KEY\|nvidia.api"; then + if echo "$list_output" | grep -qiE "NVIDIA_API_KEY\|nvidia.api"; then pass "TC-DIAG-03: credentials list shows key name" else skip "TC-DIAG-03: Key name" "Expected credential key not found in list" @@ -424,9 +424,9 @@ test_diag_03_credentials() { pass "TC-DIAG-03: credentials list does not expose key values" fi - log " Step 2: Running credentials reset NVIDIA_INFERENCE_API_KEY..." + log " Step 2: Running credentials reset NVIDIA_API_KEY..." local reset_output reset_rc=0 - reset_output=$(nemoclaw credentials reset NVIDIA_INFERENCE_API_KEY --yes 2>&1) || reset_rc=$? + reset_output=$(nemoclaw credentials reset NVIDIA_API_KEY --yes 2>&1) || reset_rc=$? log " Reset output (exit $reset_rc): ${reset_output:0:300}" if [[ $reset_rc -eq 0 ]]; then @@ -439,10 +439,10 @@ test_diag_03_credentials() { log " Step 3: Verifying key removed from list..." local post_list post_list=$(nemoclaw credentials list 2>&1) || true - if echo "$post_list" | grep -qiE "NVIDIA_INFERENCE_API_KEY"; then - fail "TC-DIAG-03: Post-reset" "NVIDIA_INFERENCE_API_KEY still in list after reset" + if echo "$post_list" | grep -qiE "NVIDIA_API_KEY"; then + fail "TC-DIAG-03: Post-reset" "NVIDIA_API_KEY still in list after reset" else - pass "TC-DIAG-03: NVIDIA_INFERENCE_API_KEY removed after reset" + pass "TC-DIAG-03: NVIDIA_API_KEY removed after reset" fi } diff --git a/test/e2e/test-double-onboard.sh b/test/e2e/test-double-onboard.sh index 4a67e3b5fb6..16129222ac5 100755 --- a/test/e2e/test-double-onboard.sh +++ b/test/e2e/test-double-onboard.sh @@ -10,7 +10,7 @@ # # This script intentionally uses a local fake OpenAI-compatible endpoint so it # matches the current onboarding flow. Older versions of this test relied on a -# missing/invalid NVIDIA_INFERENCE_API_KEY causing a late failure after sandbox creation; +# missing/invalid NVIDIA_API_KEY causing a late failure after sandbox creation; # that no longer reflects current non-interactive onboarding behavior. # ShellCheck cannot see EXIT trap invocations of cleanup helpers in this E2E script. diff --git a/test/e2e/test-full-e2e.sh b/test/e2e/test-full-e2e.sh index 6d144f13ae3..f824b1c2e13 100755 --- a/test/e2e/test-full-e2e.sh +++ b/test/e2e/test-full-e2e.sh @@ -10,18 +10,18 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (real key, starts with nvapi-) -# - Network access to inference-api.nvidia.com +# - NVIDIA_API_KEY set (real key, starts with nvapi-) +# - Network access to integrate.api.nvidia.com # # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 — required (enables non-interactive install + onboard) # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 — required for non-interactive install/onboard # NEMOCLAW_SANDBOX_NAME — sandbox name (default: e2e-nightly) # NEMOCLAW_RECREATE_SANDBOX=1 — recreate sandbox if it exists from a previous run -# NVIDIA_INFERENCE_API_KEY — required for NVIDIA Endpoints inference +# NVIDIA_API_KEY — required for NVIDIA Endpoints inference # # Usage: -# NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-full-e2e.sh +# NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 NVIDIA_API_KEY=nvapi-... bash test/e2e/test-full-e2e.sh # # See: https://github.com/NVIDIA/NemoClaw/issues/71 @@ -71,8 +71,6 @@ except Exception as e: # shellcheck source=test/e2e/lib/openclaw-json.sh . "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/openclaw-json.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/ci-compatible-inference.sh" # Determine repo root if [ -d /workspace ] && [ -f /workspace/install.sh ]; then @@ -85,7 +83,6 @@ else fi SANDBOX_NAME="${NEMOCLAW_SANDBOX_NAME:-e2e-nightly}" -nemoclaw_e2e_configure_compatible_inference # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/sandbox-teardown.sh" @@ -117,18 +114,17 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set (starts with nvapi-)" +else + fail "NVIDIA_API_KEY not set or invalid — required for live inference" exit 1 fi -HOSTED_INFERENCE_BASE_URL="$(nemoclaw_e2e_hosted_inference_base_url)" -HOSTED_INFERENCE_MODEL="$(nemoclaw_e2e_hosted_inference_model)" -HOSTED_INFERENCE_KEY="$(nemoclaw_e2e_hosted_inference_key)" - -if nemoclaw_e2e_probe_hosted_inference; then - pass "Network access to ${HOSTED_INFERENCE_BASE_URL}" +if curl -sf --max-time 10 https://integrate.api.nvidia.com/v1/models >/dev/null 2>&1; then + pass "Network access to integrate.api.nvidia.com" else - fail "Cannot reach ${HOSTED_INFERENCE_BASE_URL}" + fail "Cannot reach integrate.api.nvidia.com" exit 1 fi @@ -240,14 +236,7 @@ fi # 3c: Inference must be configured by onboard (no fallback — if onboard # failed to configure it, that's a bug we want to catch) if inf_check=$(openshell inference get 2>&1); then - inf_check_plain="$(sed -E $'s/\x1B\\[[0-9;]*[A-Za-z]//g' <<<"$inf_check")" - if nemoclaw_e2e_using_compatible_inference; then - if grep -Eqi "Provider:[[:space:]]*(custom|compatible-endpoint)" <<<"$inf_check_plain" && grep -Fq "$HOSTED_INFERENCE_MODEL" <<<"$inf_check_plain"; then - pass "Inference configured via onboard (CI-compatible endpoint)" - else - fail "Inference not configured — onboard did not set up CI-compatible provider: ${inf_check_plain:0:200}" - fi - elif grep -qi "nvidia-prod" <<<"$inf_check_plain"; then + if grep -qi "nvidia-prod" <<<"$inf_check"; then pass "Inference configured via onboard" else fail "Inference not configured — onboard did not set up nvidia-prod provider" @@ -317,13 +306,13 @@ fi section "Phase 4: Live inference" # ── Test 4a: Direct NVIDIA Endpoints ── -info "[LIVE] Direct API test → ${HOSTED_INFERENCE_BASE_URL}..." +info "[LIVE] Direct API test → integrate.api.nvidia.com..." api_response=$(curl -s --max-time 30 \ - -X POST "${HOSTED_INFERENCE_BASE_URL}/chat/completions" \ + -X POST https://integrate.api.nvidia.com/v1/chat/completions \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer $HOSTED_INFERENCE_KEY" \ + -H "Authorization: Bearer $NVIDIA_API_KEY" \ -d '{ - "model": "'"${HOSTED_INFERENCE_MODEL}"'", + "model": "nvidia/nemotron-3-super-120b-a12b", "messages": [{"role": "user", "content": "Reply with exactly one word: PONG"}], "max_tokens": 100 }' 2>/dev/null) || true diff --git a/test/e2e/test-hermes-discord-e2e.sh b/test/e2e/test-hermes-discord-e2e.sh index 1aabaa0dba3..e565f9f2e3b 100755 --- a/test/e2e/test-hermes-discord-e2e.sh +++ b/test/e2e/test-hermes-discord-e2e.sh @@ -21,7 +21,7 @@ # NEMOCLAW_RECREATE_SANDBOX=1 - auto-set # NEMOCLAW_FRESH=1 - auto-set to discard interrupted onboard sessions # NEMOCLAW_OPENSHELL_BIN - optional OpenShell binary under test -# NVIDIA_INFERENCE_API_KEY - required for Hermes onboarding +# NVIDIA_API_KEY - required for Hermes onboarding # DISCORD_BOT_TOKEN - defaults to a fake token # DISCORD_SERVER_IDS - defaults to a fake snowflake # DISCORD_ALLOWED_IDS - defaults to a fake snowflake @@ -29,7 +29,7 @@ # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=... bash test/e2e/test-hermes-discord-e2e.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-hermes-discord-e2e.sh set -uo pipefail @@ -183,10 +183,7 @@ export DISCORD_REQUIRE_MENTION="${DISCORD_REQUIRE_MENTION:-0}" # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/sandbox-teardown.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "$(dirname "${BASH_SOURCE[0]}")/lib/ci-compatible-inference.sh" register_sandbox_for_teardown "$SANDBOX_NAME" -nemoclaw_e2e_configure_compatible_inference || exit 1 # shellcheck source=test/e2e/lib/discord-gateway-proof.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/discord-gateway-proof.sh" @@ -200,7 +197,10 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set (starts with nvapi-)" +else + fail "NVIDIA_API_KEY not set or invalid" exit 1 fi @@ -584,7 +584,7 @@ fi section "Phase 8: Gateway-stored credential rebuild" -# Rebuild with NVIDIA_INFERENCE_API_KEY unset so the preflight is forced to reuse the +# Rebuild with NVIDIA_API_KEY unset so the preflight is forced to reuse the # gateway-stored inference credential. Catches the Hermes regression that # motivated the gateway-aware credential check in setupNim + rebuild. @@ -601,10 +601,9 @@ if [ -d "$REPO/.tmp" ]; then sudo rm -rf "$REPO/.tmp"/fake-discord.* 2>/dev/null || rm -rf "$REPO/.tmp"/fake-discord.* 2>/dev/null || true fi -NVIDIA_INFERENCE_API_KEY_BACKUP="${NVIDIA_INFERENCE_API_KEY:-}" NVIDIA_API_KEY_BACKUP="${NVIDIA_API_KEY:-}" -unset NVIDIA_INFERENCE_API_KEY NVIDIA_API_KEY -info "NVIDIA_INFERENCE_API_KEY and NVIDIA_API_KEY unset; gateway must hold the inference credential" +unset NVIDIA_API_KEY +info "NVIDIA_API_KEY unset; gateway must hold the inference credential" HERMES_REBUILD_LOG="/tmp/nc-hermes-rebuild-noenv.log" if nemoclaw "$SANDBOX_NAME" rebuild --yes >"$HERMES_REBUILD_LOG" 2>&1; then @@ -614,21 +613,17 @@ else fi if [ "$rebuild_rc" -ne 0 ]; then - fail "Hermes rebuild failed with NVIDIA_INFERENCE_API_KEY unset (rc=${rebuild_rc})" + fail "Hermes rebuild failed with NVIDIA_API_KEY unset (rc=${rebuild_rc})" tail -80 "$HERMES_REBUILD_LOG" 2>/dev/null || true elif grep -q "provider credential not found" "$HERMES_REBUILD_LOG"; then - fail "REGRESSION — rebuild aborted on missing NVIDIA_INFERENCE_API_KEY despite gateway-registered credential" + fail "REGRESSION — rebuild aborted on missing NVIDIA_API_KEY despite gateway-registered credential" else - pass "Hermes rebuild reused gateway-stored credential without NVIDIA_INFERENCE_API_KEY" + pass "Hermes rebuild reused gateway-stored credential without NVIDIA_API_KEY" fi -if [ -n "$NVIDIA_INFERENCE_API_KEY_BACKUP" ]; then - export NVIDIA_INFERENCE_API_KEY="$NVIDIA_INFERENCE_API_KEY_BACKUP" -fi if [ -n "$NVIDIA_API_KEY_BACKUP" ]; then export NVIDIA_API_KEY="$NVIDIA_API_KEY_BACKUP" fi -unset NVIDIA_INFERENCE_API_KEY_BACKUP unset NVIDIA_API_KEY_BACKUP section "Phase 9: Cleanup" diff --git a/test/e2e/test-hermes-e2e.sh b/test/e2e/test-hermes-e2e.sh index e0589eea2d9..db087fea95a 100755 --- a/test/e2e/test-hermes-e2e.sh +++ b/test/e2e/test-hermes-e2e.sh @@ -11,8 +11,8 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set for hosted inference -# - Network access to inference-api.nvidia.com +# - NVIDIA_API_KEY set (real key, starts with nvapi-) +# - Network access to integrate.api.nvidia.com # # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 — required (enables non-interactive install + onboard) @@ -22,10 +22,10 @@ # NEMOCLAW_RECREATE_SANDBOX=1 — recreate sandbox if it exists from a previous run # NEMOCLAW_E2E_HERMES_DASHBOARD=1 — validate the built-in Hermes web dashboard end-to-end # NEMOCLAW_HERMES_DASHBOARD_TUI=1 — enable Hermes' optional in-browser TUI tab during onboard -# NVIDIA_INFERENCE_API_KEY — required for hosted inference +# NVIDIA_API_KEY — required for NVIDIA Endpoints inference # # Usage: -# NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 NVIDIA_INFERENCE_API_KEY=... bash test/e2e/test-hermes-e2e.sh +# NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 NVIDIA_API_KEY=nvapi-... bash test/e2e/test-hermes-e2e.sh set -uo pipefail @@ -114,9 +114,6 @@ is_truthy_env_value() { esac } -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/ci-compatible-inference.sh" - hermes_dashboard_e2e_enabled() { is_truthy_env_value "${NEMOCLAW_E2E_HERMES_DASHBOARD:-}" \ || is_truthy_env_value "${NEMOCLAW_HERMES_DASHBOARD:-}" @@ -162,10 +159,6 @@ fi SANDBOX_NAME="${NEMOCLAW_SANDBOX_NAME:-e2e-hermes}" export NEMOCLAW_AGENT="${NEMOCLAW_AGENT:-hermes}" -nemoclaw_e2e_configure_compatible_inference || exit 1 -HOSTED_INFERENCE_BASE_URL="$(nemoclaw_e2e_hosted_inference_base_url)" -HOSTED_INFERENCE_MODEL="$(nemoclaw_e2e_hosted_inference_model)" -HOSTED_INFERENCE_KEY="$(nemoclaw_e2e_hosted_inference_key)" # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/sandbox-teardown.sh" @@ -203,14 +196,17 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set (starts with nvapi-)" +else + fail "NVIDIA_API_KEY not set or invalid — required for live inference" exit 1 fi -if nemoclaw_e2e_probe_hosted_inference; then - pass "Network access to ${HOSTED_INFERENCE_BASE_URL}" +if curl -sf --max-time 10 https://integrate.api.nvidia.com/v1/models >/dev/null 2>&1; then + pass "Network access to integrate.api.nvidia.com" else - fail "Cannot reach ${HOSTED_INFERENCE_BASE_URL}" + fail "Cannot reach integrate.api.nvidia.com" exit 1 fi @@ -360,16 +356,10 @@ fi # 3d: Inference must be configured by onboard if inf_check=$(openshell inference get 2>&1); then - expected_provider="$(nemoclaw_e2e_expected_route_provider)" - expected_model="" - if nemoclaw_e2e_using_compatible_inference; then - expected_model="$HOSTED_INFERENCE_MODEL" - fi - if nemoclaw_e2e_inference_output_matches "$inf_check" "$expected_provider" "$expected_model"; then - pass "Inference configured via onboard (${expected_provider})" + if grep -qi "nvidia-prod" <<<"$inf_check"; then + pass "Inference configured via onboard" else - inf_check_plain="$(printf '%s' "$inf_check" | nemoclaw_e2e_strip_ansi)" - fail "Inference not configured - onboard did not set up ${expected_provider}: ${inf_check_plain:0:200}" + fail "Inference not configured — onboard did not set up nvidia-prod provider" fi else fail "openshell inference get failed: ${inf_check:0:200}" @@ -608,13 +598,17 @@ rm -f "$ssh_config" # ══════════════════════════════════════════════════════════════════ section "Phase 5: Live inference" -# ── Test 5a: Direct hosted inference endpoint ── -info "[LIVE] Direct API test → ${HOSTED_INFERENCE_BASE_URL}..." +# ── Test 5a: Direct NVIDIA Endpoints ── +info "[LIVE] Direct API test → integrate.api.nvidia.com..." api_response=$(curl -s --max-time 30 \ - -X POST "${HOSTED_INFERENCE_BASE_URL}/chat/completions" \ + -X POST https://integrate.api.nvidia.com/v1/chat/completions \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer $HOSTED_INFERENCE_KEY" \ - -d "$(printf '{"model":"%s","messages":[{"role":"user","content":"Reply with exactly one word: PONG"}],"max_tokens":100}' "$HOSTED_INFERENCE_MODEL")" 2>/dev/null) || true + -H "Authorization: Bearer $NVIDIA_API_KEY" \ + -d '{ + "model": "nvidia/nemotron-3-super-120b-a12b", + "messages": [{"role": "user", "content": "Reply with exactly one word: PONG"}], + "max_tokens": 100 + }' 2>/dev/null) || true if [ -n "$api_response" ]; then api_content=$(echo "$api_response" | parse_chat_content 2>/dev/null) || true @@ -649,7 +643,7 @@ if openshell sandbox ssh-config "$SANDBOX_NAME" >"$ssh_config" 2>/dev/null; then "openshell-${SANDBOX_NAME}" \ "curl -s --max-time 60 https://inference.local/v1/chat/completions \ -H 'Content-Type: application/json' \ - -d '{\"model\":\"$HOSTED_INFERENCE_MODEL\",\"messages\":[{\"role\":\"user\",\"content\":\"Reply with exactly one word: PONG\"}],\"max_tokens\":100}'" \ + -d '{\"model\":\"nvidia/nemotron-3-super-120b-a12b\",\"messages\":[{\"role\":\"user\",\"content\":\"Reply with exactly one word: PONG\"}],\"max_tokens\":100}'" \ 2>&1) || true fi rm -f "$ssh_config" @@ -657,8 +651,8 @@ rm -f "$ssh_config" if [ -n "$sandbox_response" ]; then sandbox_content=$(echo "$sandbox_response" | parse_chat_content 2>/dev/null) || true if grep -qi "PONG" <<<"$sandbox_content"; then - pass "[ROUTING] inference.local: OpenShell routed curl to the hosted inference endpoint and returned PONG" - info "Routing path proven: sandbox curl → DNS forwarder → gateway proxy → hosted inference endpoint (does not exercise the Hermes agent runtime or openclaw HTTP client)" + pass "[ROUTING] inference.local: OpenShell routed curl to NVIDIA Endpoints and returned PONG" + info "Routing path proven: sandbox curl → DNS forwarder → gateway proxy → NVIDIA Endpoints (does not exercise the Hermes agent runtime or openclaw HTTP client)" else fail "[ROUTING] inference.local: expected PONG, got: ${sandbox_content:0:200}" fi diff --git a/test/e2e/test-hermes-inference-switch.sh b/test/e2e/test-hermes-inference-switch.sh index b38c64f2f85..6ae1543b973 100755 --- a/test/e2e/test-hermes-inference-switch.sh +++ b/test/e2e/test-hermes-inference-switch.sh @@ -10,7 +10,7 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set for hosted inference +# - NVIDIA_API_KEY set (real key, starts with nvapi-) # - NEMOCLAW_NON_INTERACTIVE=1 # - NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 @@ -441,22 +441,12 @@ E2E_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" . "${E2E_DIR}/lib/inference-switch-retry.sh" # shellcheck source=test/e2e/lib/anthropic-switch-provider.sh . "${E2E_DIR}/lib/anthropic-switch-provider.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${E2E_DIR}/lib/ci-compatible-inference.sh" SANDBOX_NAME="${NEMOCLAW_SANDBOX_NAME:-e2e-hermes-inference-switch}" -if nemoclaw_e2e_using_compatible_inference; then - SWITCH_PROVIDER="${NEMOCLAW_SWITCH_PROVIDER:-$(nemoclaw_e2e_expected_route_provider)}" - SWITCH_MODEL="${NEMOCLAW_SWITCH_MODEL:-$(nemoclaw_e2e_hosted_inference_model)}" -else - SWITCH_PROVIDER="${NEMOCLAW_SWITCH_PROVIDER:-nvidia-prod}" - SWITCH_MODEL="${NEMOCLAW_SWITCH_MODEL:-z-ai/glm-5.1}" -fi +SWITCH_PROVIDER="${NEMOCLAW_SWITCH_PROVIDER:-nvidia-prod}" +SWITCH_MODEL="${NEMOCLAW_SWITCH_MODEL:-z-ai/glm-5.1}" SWITCH_INFERENCE_API="${NEMOCLAW_SWITCH_INFERENCE_API:-openai-completions}" -# shellcheck disable=SC2034 # consumed by sourced anthropic-switch-provider.sh SWITCH_ENDPOINT_URL="${NEMOCLAW_SWITCH_ENDPOINT_URL:-}" -# shellcheck disable=SC2034 # consumed by sourced anthropic-switch-provider.sh SWITCH_MOCK_ANTHROPIC="${NEMOCLAW_SWITCH_MOCK_ANTHROPIC:-0}" -# shellcheck disable=SC2034 # consumed by sourced anthropic-switch-provider.sh SWITCH_MOCK_PORT="${NEMOCLAW_SWITCH_MOCK_PORT:-18766}" INSTALL_LOG="/tmp/nemoclaw-e2e-hermes-inference-switch-install.log" ENV_HASH_BEFORE="" @@ -469,7 +459,6 @@ trap 'stop_mock_anthropic_switch_provider; _nemoclaw_sandbox_teardown' EXIT # shellcheck source=test/e2e/lib/install-path-refresh.sh . "${E2E_DIR}/lib/install-path-refresh.sh" register_sandbox_for_teardown "$SANDBOX_NAME" -nemoclaw_e2e_configure_compatible_inference || exit 1 section "Phase 0: Pre-cleanup" if command -v nemohermes >/dev/null 2>&1; then @@ -491,7 +480,10 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set" +else + fail "NVIDIA_API_KEY not set or invalid" exit 1 fi diff --git a/test/e2e/test-hermes-slack-e2e.sh b/test/e2e/test-hermes-slack-e2e.sh index 8934dad48cc..57ae0318852 100755 --- a/test/e2e/test-hermes-slack-e2e.sh +++ b/test/e2e/test-hermes-slack-e2e.sh @@ -17,13 +17,13 @@ # NEMOCLAW_POLICY_TIER=open - auto-set if not already set # NEMOCLAW_SANDBOX_NAME - sandbox name (default: e2e-hermes-slack) # NEMOCLAW_RECREATE_SANDBOX=1 - auto-set -# NVIDIA_INFERENCE_API_KEY - required for Hermes onboarding +# NVIDIA_API_KEY - required for Hermes onboarding # SLACK_BOT_TOKEN - defaults to a fake xoxb- token # SLACK_APP_TOKEN - defaults to a fake xapp- token # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=... bash test/e2e/test-hermes-slack-e2e.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-hermes-slack-e2e.sh set -uo pipefail @@ -173,10 +173,7 @@ fi # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/sandbox-teardown.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "$(dirname "${BASH_SOURCE[0]}")/lib/ci-compatible-inference.sh" register_sandbox_for_teardown "$SANDBOX_NAME" -nemoclaw_e2e_configure_compatible_inference || exit 1 section "Phase 0: Prerequisites" @@ -187,7 +184,10 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set (starts with nvapi-)" +else + fail "NVIDIA_API_KEY not set or invalid" exit 1 fi diff --git a/test/e2e/test-inference-routing.sh b/test/e2e/test-inference-routing.sh index 2ceeee0b71d..2e7b1fc9f83 100755 --- a/test/e2e/test-inference-routing.sh +++ b/test/e2e/test-inference-routing.sh @@ -12,7 +12,7 @@ # Covers: # TC-INF-02: OpenAI provider end-to-end inference (requires OPENAI_API_KEY) # TC-INF-03: Anthropic provider end-to-end inference (requires ANTHROPIC_API_KEY) -# TC-INF-05: Credential isolation inside sandbox (requires NVIDIA_INFERENCE_API_KEY) +# TC-INF-05: Credential isolation inside sandbox (requires NVIDIA_API_KEY) # TC-INF-06: Invalid API key → classified "credential" error (PR-safe) # TC-INF-07: Unreachable endpoint → classified "transport" error (PR-safe) # TC-INF-09: Custom OpenAI-compatible endpoint (requires NEMOCLAW_ENDPOINT_URL + COMPATIBLE_API_KEY) @@ -103,7 +103,7 @@ install_nemoclaw() { # Use a dummy key so install.sh doesn't prompt — the key will fail # validation, but install.sh only needs it for the onboard step which # we control separately in each test case. - NVIDIA_INFERENCE_API_KEY="nvapi-DUMMY-FOR-INSTALL" \ + NVIDIA_API_KEY="nvapi-DUMMY-FOR-INSTALL" \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ bash "$REPO_ROOT/install.sh" --non-interactive --yes-i-accept-third-party-software \ @@ -187,9 +187,9 @@ test_inf_05_credential_isolation() { log "=== TC-INF-05: Credential Isolation ===" # Determine the real API key to search for - local real_key="${NVIDIA_INFERENCE_API_KEY:-}" + local real_key="${NVIDIA_API_KEY:-}" if [[ -z "$real_key" ]]; then - skip "TC-INF-05" "NVIDIA_INFERENCE_API_KEY not set — cannot test credential isolation" + skip "TC-INF-05" "NVIDIA_API_KEY not set — cannot test credential isolation" return fi @@ -279,13 +279,13 @@ try { # TC-INF-05d: Placeholder token IS present in environment local placeholder - placeholder=$(sandbox_exec "printenv NVIDIA_INFERENCE_API_KEY 2>/dev/null || true") || true + placeholder=$(sandbox_exec "printenv NVIDIA_API_KEY 2>/dev/null || true") || true if [[ -n "$placeholder" && "$placeholder" != "$real_key" ]]; then pass "TC-INF-05d: Placeholder token present in sandbox (not the real key)" elif [[ "$placeholder" == "$real_key" ]]; then fail "TC-INF-05d: Placeholder" "Sandbox has the REAL key, not a placeholder" else - skip "TC-INF-05d: Placeholder" "NVIDIA_INFERENCE_API_KEY not set in sandbox (placeholder injection may not be active)" + skip "TC-INF-05d: Placeholder" "NVIDIA_API_KEY not set in sandbox (placeholder injection may not be active)" fi } @@ -297,9 +297,8 @@ test_inf_06_invalid_api_key() { rm -f "$HOME/.nemoclaw/onboard.lock" 2>/dev/null || true - local invalid_api_key="nvapi-INTENTIONALLY-INVALID-KEY-FOR-E2E-TEST" # gitleaks:allow local output exit_code=0 - output=$(NVIDIA_INFERENCE_API_KEY="$invalid_api_key" \ + output=$(NVIDIA_API_KEY="nvapi-INTENTIONALLY-INVALID-KEY-FOR-E2E-TEST" \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_SANDBOX_NAME="e2e-invalid-key" \ @@ -363,7 +362,7 @@ test_inf_07_unreachable_endpoint() { # Use an RFC 2606 invalid domain — deterministic DNS failure across runners local output exit_code=0 - output=$(NVIDIA_INFERENCE_API_KEY="nvapi-valid-format-but-fake-key-1234567890" \ + output=$(NVIDIA_API_KEY="nvapi-valid-format-but-fake-key-1234567890" \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_SANDBOX_NAME="e2e-unreachable" \ diff --git a/test/e2e/test-issue-2478-crash-loop-recovery.sh b/test/e2e/test-issue-2478-crash-loop-recovery.sh index e6f91a91719..67de5b6734e 100755 --- a/test/e2e/test-issue-2478-crash-loop-recovery.sh +++ b/test/e2e/test-issue-2478-crash-loop-recovery.sh @@ -58,8 +58,7 @@ # NEMOCLAW_E2E_TIMEOUT_SECONDS — overall timeout (default: 1500) # NEMOCLAW_E2E_CRASH_CYCLES — crash-recover cycles (default: 5) # NEMOCLAW_E2E_SOAK_SECONDS — idle soak window (default: 300) -# NVIDIA_INFERENCE_API_KEY — required only with NEMOCLAW_E2E_USE_COMPAT_MOCK=0 -# NVIDIA_API_KEY — legacy fallback for NVIDIA_INFERENCE_API_KEY +# NVIDIA_API_KEY — required only with NEMOCLAW_E2E_USE_COMPAT_MOCK=0 # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 \ @@ -426,14 +425,11 @@ if [ "$USE_COMPAT_MOCK" = "1" ]; then fi pass "Compatible endpoint mock prerequisites available" else - if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ] && [ -n "${NVIDIA_API_KEY:-}" ]; then - export NVIDIA_INFERENCE_API_KEY="$NVIDIA_API_KEY" - fi - if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ] || [[ "${NVIDIA_INFERENCE_API_KEY}" != nvapi-* ]]; then - fail "NVIDIA_INFERENCE_API_KEY not set or invalid" + if [ -z "${NVIDIA_API_KEY:-}" ] || [[ "${NVIDIA_API_KEY}" != nvapi-* ]]; then + fail "NVIDIA_API_KEY not set or invalid" exit 1 fi - pass "NVIDIA_INFERENCE_API_KEY set" + pass "NVIDIA_API_KEY set" fi if [ "${NEMOCLAW_NON_INTERACTIVE:-}" != "1" ] || [ "${NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE:-}" != "1" ]; then diff --git a/test/e2e/test-issue-4434-tui-unreachable-inference.sh b/test/e2e/test-issue-4434-tui-unreachable-inference.sh index e0a04c5bf50..3ea95c341b0 100755 --- a/test/e2e/test-issue-4434-tui-unreachable-inference.sh +++ b/test/e2e/test-issue-4434-tui-unreachable-inference.sh @@ -8,14 +8,12 @@ # # This mutates host firewall state. Run only on a Linux Docker host you control: # -# NEMOCLAW_ISSUE_4434_LIVE=1 NVIDIA_INFERENCE_API_KEY=... \ +# NEMOCLAW_ISSUE_4434_LIVE=1 NVIDIA_API_KEY=nvapi-... \ # bash test/e2e/test-issue-4434-tui-unreachable-inference.sh set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${SCRIPT_DIR}/lib/ci-compatible-inference.sh" SANDBOX_NAME="${NEMOCLAW_SANDBOX_NAME:-e2e-issue-4434-tui-unreachable}" INSTALL_LOG="${E2E_ISSUE_4434_INSTALL_LOG:-/tmp/nemoclaw-e2e-issue-4434-install.log}" @@ -65,11 +63,6 @@ if [ "${NEMOCLAW_ISSUE_4434_LIVE:-0}" != "1" ]; then exit 0 fi -if nemoclaw_e2e_using_compatible_inference; then - info "skipping: hosted compatible inference is gateway-managed; this repro only blocks sandbox egress" - exit 0 -fi - if [ "$(uname -s)" != "Linux" ]; then fail "Linux host required for DOCKER-USER iptables repro" fi @@ -78,8 +71,9 @@ for command in docker sudo expect curl timeout perl; do done docker info >/dev/null 2>&1 || fail "Docker is not running" sudo -n true >/dev/null 2>&1 || fail "passwordless sudo is required for non-interactive iptables cleanup" -nemoclaw_e2e_configure_compatible_inference || fail "hosted CI inference could not be configured" -nemoclaw_e2e_require_hosted_inference_key || exit 1 +if [ -z "${NVIDIA_API_KEY:-}" ] || [[ "${NVIDIA_API_KEY}" != nvapi-* ]]; then + fail "NVIDIA_API_KEY must be set and start with nvapi-" +fi mkdir -p "$CAPTURE_DIR" CLEANUP_SANDBOX=1 @@ -116,33 +110,7 @@ if ! nemoclaw "$SANDBOX_NAME" status >"$status_log" 2>&1; then fail "nemoclaw ${SANDBOX_NAME} status failed before firewall block" fi if ! grep -Eiq "inference.*healthy|healthy.*inference" "$status_log"; then - if grep -Eiq "Inference:[[:space:]]*not probed" "$status_log"; then - info "status skipped inference reachability; probing inference.local directly" - else - fail "pre-block status did not report healthy or not-probed inference" - fi -fi - -route_log="${CAPTURE_DIR}/openshell-inference-before-block.log" -if ! route_output=$(openshell inference get 2>&1); then - printf '%s\n' "$route_output" >"$route_log" - fail "openshell inference get failed before firewall block" -fi -printf '%s\n' "$route_output" >"$route_log" -expected_provider="$(nemoclaw_e2e_expected_route_provider)" -expected_model="$(nemoclaw_e2e_hosted_inference_model)" -if ! nemoclaw_e2e_inference_output_matches "$route_output" "$expected_provider" "$expected_model"; then - route_plain="$(printf '%s' "$route_output" | nemoclaw_e2e_strip_ansi)" - fail "pre-block OpenShell route was not ${expected_provider} / ${expected_model}: ${route_plain:0:240}" -fi - -preblock_probe_log="${CAPTURE_DIR}/inference-local-before-block.log" -preblock_payload="$(printf '{"model":"%s","messages":[{"role":"user","content":"Reply with OK."}],"max_tokens":8}' "$expected_model")" -preblock_payload_arg="$(printf '%q' "$preblock_payload")" -if ! timeout 90 openshell sandbox exec --name "$SANDBOX_NAME" -- sh -lc \ - "curl -sf --max-time 60 https://inference.local/v1/chat/completions -H 'Content-Type: application/json' -d $preblock_payload_arg >/dev/null" \ - >"$preblock_probe_log" 2>&1; then - fail "inference.local was not reachable from inside the sandbox before firewall block" + fail "pre-block status did not report healthy inference" fi connect_probe_log="${CAPTURE_DIR}/nemoclaw-connect-probe-before-block.log" @@ -159,12 +127,12 @@ done block_probe_log="${CAPTURE_DIR}/blocked-endpoint-probe.log" set +e timeout 25 openshell sandbox exec --name "$SANDBOX_NAME" -- sh -lc \ - 'curl -sk --connect-timeout 5 --max-time 12 https://inference-api.nvidia.com/v1/models >/tmp/issue4434-models.out 2>&1' \ + 'curl -sk --connect-timeout 5 --max-time 12 https://integrate.api.nvidia.com/v1/models >/tmp/issue4434-models.out 2>&1' \ >"$block_probe_log" 2>&1 block_probe_rc=$? set -e if [ "$block_probe_rc" -eq 0 ]; then - fail "inference-api.nvidia.com was still reachable from inside the sandbox after firewall block" + fail "integrate.api.nvidia.com was still reachable from inside the sandbox after firewall block" fi info "sandbox endpoint block verified (probe exit ${block_probe_rc})" diff --git a/test/e2e/test-issue-4462-scope-upgrade-approval.sh b/test/e2e/test-issue-4462-scope-upgrade-approval.sh index 30f7015e5be..8933626a707 100755 --- a/test/e2e/test-issue-4462-scope-upgrade-approval.sh +++ b/test/e2e/test-issue-4462-scope-upgrade-approval.sh @@ -20,7 +20,7 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set +# - NVIDIA_API_KEY set # - NEMOCLAW_NON_INTERACTIVE=1 # - NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 @@ -717,11 +717,11 @@ tail -20 /tmp/auto-pair.log 2>/dev/null || true section "Phase 0: Preflight" -if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - fail "NVIDIA_INFERENCE_API_KEY not set" +if [ -z "${NVIDIA_API_KEY:-}" ]; then + fail "NVIDIA_API_KEY not set" exit 1 fi -pass "NVIDIA_INFERENCE_API_KEY is set" +pass "NVIDIA_API_KEY is set" if ! docker info >/dev/null 2>&1; then fail "Docker is not running" diff --git a/test/e2e/test-kimi-inference-compat.sh b/test/e2e/test-kimi-inference-compat.sh index 31bab4b542e..3a401327628 100755 --- a/test/e2e/test-kimi-inference-compat.sh +++ b/test/e2e/test-kimi-inference-compat.sh @@ -394,7 +394,7 @@ run_kimi_onboard() { export NEMOCLAW_POLICY_TIER=restricted export NEMOCLAW_POLICY_MODE=skip export COMPATIBLE_API_KEY="$KIMI_MOCK_API_KEY" - unset NVIDIA_INFERENCE_API_KEY NVIDIA_API_KEY OPENAI_API_KEY ANTHROPIC_API_KEY GEMINI_API_KEY + unset NVIDIA_API_KEY OPENAI_API_KEY ANTHROPIC_API_KEY GEMINI_API_KEY unset TELEGRAM_BOT_TOKEN DISCORD_BOT_TOKEN SLACK_BOT_TOKEN SLACK_APP_TOKEN prepare_source_cli || prep_exit=$? diff --git a/test/e2e/test-launchable-smoke.sh b/test/e2e/test-launchable-smoke.sh index 73d993f227d..0511b1565b0 100755 --- a/test/e2e/test-launchable-smoke.sh +++ b/test/e2e/test-launchable-smoke.sh @@ -20,7 +20,7 @@ # What this tests: # 1. Run brev-launchable-ci-cpu.sh with NEMOCLAW_REF=current branch # 2. Verify installation artifacts (nemoclaw, openshell, Node.js ≥22, Docker, sentinel) -# 3. nemoclaw onboard --non-interactive with hosted inference +# 3. nemoclaw onboard --non-interactive with NVIDIA_API_KEY (cloud provider) # 4. Sandbox health: nemoclaw list, status, gateway running # 5. Live inference through the sandbox (same pattern as test-full-e2e.sh Phase 4) # 6. Destroy + cleanup @@ -28,8 +28,8 @@ # Prerequisites: # - Ubuntu runner (ubuntu-latest) # - Docker running -# - NVIDIA_INFERENCE_API_KEY set for hosted inference -# - Network access to inference-api.nvidia.com +# - NVIDIA_API_KEY set (real key, starts with nvapi-) +# - Network access to integrate.api.nvidia.com # - NEMOCLAW_NON_INTERACTIVE=1 # - NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 # @@ -37,12 +37,12 @@ # NEMOCLAW_REF — git ref for brev-launchable-ci-cpu.sh (default: current branch) # NEMOCLAW_SANDBOX_NAME — sandbox name (default: e2e-launchable) # NEMOCLAW_RECREATE_SANDBOX — set to 1 to recreate if exists -# NVIDIA_INFERENCE_API_KEY — required for hosted inference +# NVIDIA_API_KEY — required for NVIDIA Endpoints inference # SKIP_DOCKER_PULL — set to 1 to skip Docker image pre-pulls (speeds up CI) # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=... bash test/e2e/test-launchable-smoke.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-launchable-smoke.sh # # See: https://github.com/NVIDIA/NemoClaw/issues/2599 @@ -97,9 +97,6 @@ except Exception as e: " } -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/ci-compatible-inference.sh" - # Determine repo root if [ -f "$(cd "$(dirname "$0")/../.." && pwd)/scripts/brev-launchable-ci-cpu.sh" ]; then REPO="$(cd "$(dirname "$0")/../.." && pwd)" @@ -136,10 +133,6 @@ exec > >(tee -a "$TEST_LOG") 2>&1 # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/sandbox-teardown.sh" register_sandbox_for_teardown "$SANDBOX_NAME" -nemoclaw_e2e_configure_compatible_inference || exit 1 -HOSTED_INFERENCE_BASE_URL="$(nemoclaw_e2e_hosted_inference_base_url)" -HOSTED_INFERENCE_MODEL="$(nemoclaw_e2e_hosted_inference_model)" -HOSTED_INFERENCE_KEY="$(nemoclaw_e2e_hosted_inference_key)" # ══════════════════════════════════════════════════════════════════ # Phase 0: Pre-cleanup @@ -184,14 +177,17 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set (starts with nvapi-)" +else + fail "NVIDIA_API_KEY not set or invalid — required for live inference" exit 1 fi -if nemoclaw_e2e_probe_hosted_inference; then - pass "Network access to ${HOSTED_INFERENCE_BASE_URL}" +if curl -sf --max-time 10 https://integrate.api.nvidia.com/v1/models >/dev/null 2>&1; then + pass "Network access to integrate.api.nvidia.com" else - fail "Cannot reach ${HOSTED_INFERENCE_BASE_URL}" + fail "Cannot reach integrate.api.nvidia.com" exit 1 fi @@ -345,9 +341,9 @@ else fi # ══════════════════════════════════════════════════════════════════ -# Phase 4: Onboard (non-interactive, hosted inference) +# Phase 4: Onboard (non-interactive, cloud provider) # ══════════════════════════════════════════════════════════════════ -section "Phase 4: Onboard (non-interactive, hosted inference)" +section "Phase 4: Onboard (non-interactive, NVIDIA Endpoints)" # Run onboard from the launchable clone directory — this is the real # community path: the user's NemoClaw is in ~/NemoClaw, not a CI checkout. @@ -357,7 +353,7 @@ cd "$NEMOCLAW_CLONE_DIR" || { } info "Running nemoclaw onboard --non-interactive..." -info "Provider: ${NEMOCLAW_PROVIDER:-configured hosted inference}" +info "Provider: NVIDIA Endpoints (cloud)" info "Sandbox name: $SANDBOX_NAME" ONBOARD_LOG="/tmp/nemoclaw-launchable-onboard.log" @@ -407,16 +403,10 @@ fi # 5c: Inference configured by onboard if inf_check=$(openshell inference get 2>&1); then - expected_provider="$(nemoclaw_e2e_expected_route_provider)" - expected_model="" - if nemoclaw_e2e_using_compatible_inference; then - expected_model="$HOSTED_INFERENCE_MODEL" - fi - if nemoclaw_e2e_inference_output_matches "$inf_check" "$expected_provider" "$expected_model"; then - pass "Inference configured via onboard (${expected_provider})" + if grep -qi "nvidia-prod" <<<"$inf_check"; then + pass "Inference configured via onboard (nvidia-prod)" else - inf_check_plain="$(printf '%s' "$inf_check" | nemoclaw_e2e_strip_ansi)" - fail "Inference not configured - onboard did not set up ${expected_provider}: ${inf_check_plain:0:200}" + fail "Inference not configured — onboard did not set up nvidia-prod provider" fi else fail "openshell inference get failed: ${inf_check:0:200}" @@ -434,13 +424,17 @@ fi # ══════════════════════════════════════════════════════════════════ section "Phase 6: Live inference" -# ── Test 6a: Direct hosted inference endpoint (sanity check) ── -info "[LIVE] Direct API test → ${HOSTED_INFERENCE_BASE_URL}..." +# ── Test 6a: Direct NVIDIA Endpoints (sanity check) ── +info "[LIVE] Direct API test → integrate.api.nvidia.com..." api_response=$(curl -s --max-time 30 \ - -X POST "${HOSTED_INFERENCE_BASE_URL}/chat/completions" \ + -X POST https://integrate.api.nvidia.com/v1/chat/completions \ -H "Content-Type: application/json" \ - -H "Authorization: Bearer $HOSTED_INFERENCE_KEY" \ - -d "$(printf '{"model":"%s","messages":[{"role":"user","content":"Reply with exactly one word: PONG"}],"max_tokens":100}' "$HOSTED_INFERENCE_MODEL")" 2>/dev/null) || true + -H "Authorization: Bearer $NVIDIA_API_KEY" \ + -d '{ + "model": "nvidia/nemotron-3-super-120b-a12b", + "messages": [{"role": "user", "content": "Reply with exactly one word: PONG"}], + "max_tokens": 100 + }' 2>/dev/null) || true if [ -n "$api_response" ]; then api_content=$(echo "$api_response" | parse_chat_content 2>/dev/null) || true @@ -467,7 +461,7 @@ if openshell sandbox ssh-config "$SANDBOX_NAME" >"$ssh_config" 2>/dev/null; then "openshell-${SANDBOX_NAME}" \ "curl -s --max-time 60 https://inference.local/v1/chat/completions \ -H 'Content-Type: application/json' \ - -d '{\"model\":\"$HOSTED_INFERENCE_MODEL\",\"messages\":[{\"role\":\"user\",\"content\":\"Reply with exactly one word: PONG\"}],\"max_tokens\":100}'" \ + -d '{\"model\":\"nvidia/nemotron-3-super-120b-a12b\",\"messages\":[{\"role\":\"user\",\"content\":\"Reply with exactly one word: PONG\"}],\"max_tokens\":100}'" \ 2>&1) || true fi rm -f "$ssh_config" @@ -500,14 +494,14 @@ for pong_attempt in 1 2 3; do "openshell-${SANDBOX_NAME}" \ "curl -s --max-time 60 https://inference.local/v1/chat/completions \ -H 'Content-Type: application/json' \ - -d '{\"model\":\"$HOSTED_INFERENCE_MODEL\",\"messages\":[{\"role\":\"user\",\"content\":\"Reply with exactly one word: PONG\"}],\"max_tokens\":100}'" \ + -d '{\"model\":\"nvidia/nemotron-3-super-120b-a12b\",\"messages\":[{\"role\":\"user\",\"content\":\"Reply with exactly one word: PONG\"}],\"max_tokens\":100}'" \ 2>&1) || true fi rm -f "$ssh_config" done if $pong_ok; then - pass "[ROUTING] inference.local: OpenShell routed curl to the hosted inference endpoint and returned PONG" + pass "[ROUTING] inference.local: OpenShell routed curl to NVIDIA Endpoints and returned PONG" else fail "[ROUTING] inference.local: expected PONG after 3 attempts, got: ${sandbox_content:0:200}" fi @@ -582,9 +576,9 @@ echo "" echo " What this tested (issue #2599):" echo " - brev-launchable-ci-cpu.sh bootstrap (Docker, Node.js, OpenShell, NemoClaw)" echo " - Installation artifacts (binaries on PATH, sentinel file, built outputs)" -echo " - Onboard via launchable-installed NemoClaw (hosted inference)" +echo " - Onboard via launchable-installed NemoClaw (cloud provider)" echo " - Sandbox health (list, status, inference config, gateway)" -echo " - Direct hosted inference" +echo " - Direct NVIDIA Endpoints inference" echo " - Sandbox inference routing (curl → inference.local)" echo " - openclaw agent mediated inference (the full stack)" echo " - Destroy + cleanup" diff --git a/test/e2e/test-messaging-providers.sh b/test/e2e/test-messaging-providers.sh index 8ce252a8904..bfc79d3aede 100755 --- a/test/e2e/test-messaging-providers.sh +++ b/test/e2e/test-messaging-providers.sh @@ -36,11 +36,11 @@ # Prerequisites: # - Docker running # - NemoClaw installed (install.sh or brev-setup.sh already ran) -# - NVIDIA_INFERENCE_API_KEY set +# - NVIDIA_API_KEY set # - openshell on PATH # # Environment variables: -# NVIDIA_INFERENCE_API_KEY — required +# NVIDIA_API_KEY — required # NEMOCLAW_NON_INTERACTIVE=1 — required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 — required # NEMOCLAW_SANDBOX_NAME — sandbox name (default: e2e-msg-provider) @@ -80,7 +80,7 @@ # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-messaging-providers.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-messaging-providers.sh # # See: https://github.com/NVIDIA/NemoClaw/pull/1081 @@ -633,15 +633,11 @@ openclaw_message_send_exit_code() { # ══════════════════════════════════════════════════════════════════ section "Phase 0: Prerequisites" -if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ] && [ -n "${NVIDIA_API_KEY:-}" ]; then - export NVIDIA_INFERENCE_API_KEY="${NVIDIA_API_KEY}" - info "Using legacy NVIDIA_API_KEY as fallback for NVIDIA_INFERENCE_API_KEY" -fi -if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - fail "NVIDIA_INFERENCE_API_KEY not set" +if [ -z "${NVIDIA_API_KEY:-}" ]; then + fail "NVIDIA_API_KEY not set" exit 1 fi -pass "NVIDIA_INFERENCE_API_KEY is set" +pass "NVIDIA_API_KEY is set" if ! docker info >/dev/null 2>&1; then fail "Docker is not running" diff --git a/test/e2e/test-model-router-provider-routed-inference.sh b/test/e2e/test-model-router-provider-routed-inference.sh index cac9687626c..4daf611cbce 100755 --- a/test/e2e/test-model-router-provider-routed-inference.sh +++ b/test/e2e/test-model-router-provider-routed-inference.sh @@ -68,7 +68,7 @@ redact_file() { python3 - "$file" <<'PY' import os, sys path = sys.argv[1] -secrets = [os.environ.get("NVIDIA_INFERENCE_API_KEY", ""), os.environ.get("NEMOCLAW_PROVIDER_KEY", "")] +secrets = [os.environ.get("NVIDIA_API_KEY", ""), os.environ.get("NEMOCLAW_PROVIDER_KEY", "")] text = open(path, "r", errors="replace").read() for secret in filter(None, secrets): text = text.replace(secret, "") @@ -97,10 +97,10 @@ else exit 1 fi -if [ -n "${NVIDIA_INFERENCE_API_KEY:-}" ] && [[ "${NVIDIA_INFERENCE_API_KEY}" == nvapi-* ]]; then - pass "NVIDIA_INFERENCE_API_KEY is set" +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set" else - fail "NVIDIA_INFERENCE_API_KEY is required and must start with nvapi-" + fail "NVIDIA_API_KEY is required and must start with nvapi-" exit 1 fi @@ -124,13 +124,13 @@ rm -f "$HOME/.nemoclaw/onboard.lock" 2>/dev/null || true nemoclaw "$SANDBOX_NAME" destroy --yes >/dev/null 2>&1 || true env \ - NEMOCLAW_PROVIDER_KEY="$NVIDIA_INFERENCE_API_KEY" \ + NEMOCLAW_PROVIDER_KEY="$NVIDIA_API_KEY" \ NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_POLICY_TIER="open" \ NEMOCLAW_PROVIDER="routed" \ - NVIDIA_INFERENCE_API_KEY="$NVIDIA_INFERENCE_API_KEY" \ + NVIDIA_API_KEY="$NVIDIA_API_KEY" \ "$TIMEOUT_CMD" 1500 nemoclaw onboard --fresh --non-interactive --yes-i-accept-third-party-software \ >"$ONBOARD_LOG" 2>&1 onboard_rc=$? diff --git a/test/e2e/test-network-policy.sh b/test/e2e/test-network-policy.sh index e03afe78031..d7d7ca7499c 100755 --- a/test/e2e/test-network-policy.sh +++ b/test/e2e/test-network-policy.sh @@ -23,7 +23,7 @@ # Prerequisites: # - Docker running # - NemoClaw installed (or install.sh available) -# - NVIDIA_INFERENCE_API_KEY for sandbox onboard +# - NVIDIA_API_KEY for sandbox onboard # ============================================================================= set -euo pipefail @@ -92,7 +92,7 @@ install_nemoclaw() { fi log "=== Installing NemoClaw via install.sh ===" NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" \ - NVIDIA_INFERENCE_API_KEY="${NVIDIA_INFERENCE_API_KEY:-nvapi-DUMMY-FOR-INSTALL}" \ + NVIDIA_API_KEY="${NVIDIA_API_KEY:-nvapi-DUMMY-FOR-INSTALL}" \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_POLICY_TIER="restricted" \ @@ -242,9 +242,9 @@ wait_for_e2e_http_port() { # ── Onboard sandbox ───────────────────────────────────────────────────────── setup_sandbox() { - local api_key="${NVIDIA_INFERENCE_API_KEY:-}" + local api_key="${NVIDIA_API_KEY:-}" if [[ -z "$api_key" ]]; then - log "ERROR: NVIDIA_INFERENCE_API_KEY not set" + log "ERROR: NVIDIA_API_KEY not set" exit 1 fi @@ -681,7 +681,7 @@ test_net_07_inference_exemption() { log " Step 2: Attempt direct connection to provider (should be blocked)..." local direct_response direct_response=$(sandbox_exec "node -e \" -fetch('https://inference-api.nvidia.com/v1/models', {signal: AbortSignal.timeout(15000)}) +fetch('https://integrate.api.nvidia.com/v1/models', {signal: AbortSignal.timeout(15000)}) .then(r => console.log('STATUS_' + r.status)) .catch(e => console.log('ERROR_' + (e.cause?.code || e.code || e.message))) \"" 2>&1) || true diff --git a/test/e2e/test-onboard-negative-paths.sh b/test/e2e/test-onboard-negative-paths.sh index 30ff8c85800..83d2f5d1ee5 100755 --- a/test/e2e/test-onboard-negative-paths.sh +++ b/test/e2e/test-onboard-negative-paths.sh @@ -24,8 +24,6 @@ export NEMOCLAW_E2E_DEFAULT_TIMEOUT=1800 SCRIPT_DIR_TIMEOUT="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" # shellcheck source=test/e2e/e2e-timeout.sh source "${SCRIPT_DIR_TIMEOUT}/e2e-timeout.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${SCRIPT_DIR_TIMEOUT}/lib/ci-compatible-inference.sh" LOG_FILE="${NEMOCLAW_E2E_LOG:-/tmp/nemoclaw-e2e-onboard-negative-paths.log}" exec > >(tee "$LOG_FILE") 2>&1 @@ -75,35 +73,11 @@ if ! command -v nemoclaw >/dev/null 2>&1; then fi SANDBOX_NAME="${NEMOCLAW_SANDBOX_NAME:-e2e-onboard-negative}" +CLOUD_MODEL="${NEMOCLAW_ONBOARD_NEGATIVE_MODEL:-nvidia/nemotron-3-super-120b-a12b}" PORT_CONFLICT_PORT="${NEMOCLAW_ONBOARD_NEGATIVE_CONFLICT_PORT:-18080}" SESSION_FILE="$HOME/.nemoclaw/onboard-session.json" REGISTRY_FILE="$HOME/.nemoclaw/sandboxes.json" -RESTORE_API_KEY="${NVIDIA_INFERENCE_API_KEY:-}" -if [ -n "$RESTORE_API_KEY" ]; then - export NVIDIA_INFERENCE_API_KEY="$RESTORE_API_KEY" -fi -nemoclaw_e2e_configure_compatible_inference || { - fail "Hosted CI inference could not be configured" - exit 1 -} -CLOUD_MODEL="${NEMOCLAW_ONBOARD_NEGATIVE_MODEL:-$(nemoclaw_e2e_hosted_inference_model)}" -HOSTED_INFERENCE_BASE_URL="$(nemoclaw_e2e_hosted_inference_base_url)" -EXPECTED_PROVIDER="$(nemoclaw_e2e_expected_route_provider)" -ONBOARD_INFERENCE_ENV=( - "NEMOCLAW_PROVIDER=cloud" - "NEMOCLAW_MODEL=$CLOUD_MODEL" - "NVIDIA_INFERENCE_API_KEY=$RESTORE_API_KEY" -) -if nemoclaw_e2e_using_compatible_inference; then - ONBOARD_INFERENCE_ENV=( - "NEMOCLAW_PROVIDER=custom" - "NEMOCLAW_ENDPOINT_URL=$HOSTED_INFERENCE_BASE_URL" - "NEMOCLAW_MODEL=$CLOUD_MODEL" - "NEMOCLAW_COMPAT_MODEL=$CLOUD_MODEL" - "COMPATIBLE_API_KEY=$RESTORE_API_KEY" - "NVIDIA_INFERENCE_API_KEY=$RESTORE_API_KEY" - ) -fi +RESTORE_API_KEY="${NVIDIA_API_KEY:-}" # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/sandbox-teardown.sh" @@ -243,7 +217,7 @@ const path = require("node:path"); const repo = process.argv[2]; const { validateNvidiaApiKeyValue } = require(path.join(repo, "dist", "lib", "validation.js")); -const nvidiaError = validateNvidiaApiKeyValue("not-a-nvidia-key", "NVIDIA_INFERENCE_API_KEY"); +const nvidiaError = validateNvidiaApiKeyValue("not-a-nvidia-key", "NVIDIA_API_KEY"); if (!nvidiaError || !nvidiaError.includes("Must start with nvapi-")) { throw new Error(`expected NVIDIA key prefix rejection, got: ${nvidiaError}`); } @@ -320,7 +294,10 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [[ -n "$RESTORE_API_KEY" && "$RESTORE_API_KEY" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set" +else + fail "NVIDIA_API_KEY not set or invalid; required for live onboard scenarios" print_summary exit 1 fi @@ -356,10 +333,11 @@ section "Phase 3: Entry option validation" FROM_GUARD_LOG="$(mktemp)" env -u NEMOCLAW_SANDBOX_NAME \ - "${ONBOARD_INFERENCE_ENV[@]}" \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ + NEMOCLAW_PROVIDER=cloud \ NEMOCLAW_POLICY_MODE=skip \ + NVIDIA_API_KEY="$RESTORE_API_KEY" \ node "$REPO/bin/nemoclaw.js" onboard --non-interactive --from "$REPO/Dockerfile" \ >"$FROM_GUARD_LOG" 2>&1 from_guard_exit=$? @@ -387,11 +365,12 @@ fi FROM_ENV_NAME_LOG="$(mktemp)" env \ - "${ONBOARD_INFERENCE_ENV[@]}" \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_SANDBOX_NAME="bad name" \ + NEMOCLAW_PROVIDER=cloud \ NEMOCLAW_POLICY_MODE=skip \ + NVIDIA_API_KEY="$RESTORE_API_KEY" \ node "$REPO/bin/nemoclaw.js" onboard --non-interactive --from "$REPO/Dockerfile" \ >"$FROM_ENV_NAME_LOG" 2>&1 from_env_name_exit=$? @@ -426,7 +405,7 @@ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_RECREATE_SANDBOX=1 \ NEMOCLAW_PROVIDER=cloud \ NEMOCLAW_POLICY_MODE=skip \ - NVIDIA_INFERENCE_API_KEY=not-a-nvidia-key \ + NVIDIA_API_KEY=not-a-nvidia-key \ node "$REPO/bin/nemoclaw.js" onboard --non-interactive >"$INVALID_KEY_LOG" 2>&1 invalid_key_exit=$? invalid_key_output="$(cat "$INVALID_KEY_LOG")" @@ -467,14 +446,14 @@ else fi PORT_CONFLICT_LOG="$(mktemp)" -env \ - "${ONBOARD_INFERENCE_ENV[@]}" \ - NEMOCLAW_NON_INTERACTIVE=1 \ +NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_SANDBOX_NAME="${SANDBOX_NAME}-port" \ NEMOCLAW_RECREATE_SANDBOX=1 \ NEMOCLAW_GATEWAY_PORT="$PORT_CONFLICT_PORT" \ + NEMOCLAW_PROVIDER=cloud \ NEMOCLAW_POLICY_MODE=skip \ + NVIDIA_API_KEY="$RESTORE_API_KEY" \ node "$REPO/bin/nemoclaw.js" onboard --non-interactive >"$PORT_CONFLICT_LOG" 2>&1 port_conflict_exit=$? port_conflict_output="$(cat "$PORT_CONFLICT_LOG")" @@ -508,14 +487,15 @@ fi section "Phase 6: Live non-interactive onboard honors presets and model" LIVE_LOG="$(mktemp)" -env \ - "${ONBOARD_INFERENCE_ENV[@]}" \ - NEMOCLAW_NON_INTERACTIVE=1 \ +NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" \ NEMOCLAW_RECREATE_SANDBOX=1 \ + NEMOCLAW_PROVIDER=cloud \ + NEMOCLAW_MODEL="$CLOUD_MODEL" \ NEMOCLAW_POLICY_MODE=custom \ NEMOCLAW_POLICY_PRESETS=npm,pypi \ + NVIDIA_API_KEY="$RESTORE_API_KEY" \ node "$REPO/bin/nemoclaw.js" onboard --non-interactive >"$LIVE_LOG" 2>&1 live_exit=$? live_output="$(cat "$LIVE_LOG")" @@ -530,20 +510,20 @@ else exit 1 fi -if printf '%s\n' "$live_output" | grep -Fq "$CLOUD_MODEL"; then - pass "Live onboard selected requested hosted model" +if printf '%s\n' "$live_output" | grep -q "Using NVIDIA Endpoints with model: ${CLOUD_MODEL}"; then + pass "Live onboard selected requested cloud model" else - fail "Live onboard output did not confirm requested hosted model" + fail "Live onboard output did not confirm requested cloud model" fi -if node - "$REGISTRY_FILE" "$SANDBOX_NAME" "$CLOUD_MODEL" "$EXPECTED_PROVIDER" <<'NODE'; then +if node - "$REGISTRY_FILE" "$SANDBOX_NAME" "$CLOUD_MODEL" <<'NODE'; then const fs = require("node:fs"); -const [registryPath, sandboxName, expectedModel, expectedProvider] = process.argv.slice(2); +const [registryPath, sandboxName, expectedModel] = process.argv.slice(2); const registry = JSON.parse(fs.readFileSync(registryPath, "utf8")); const sandbox = registry.sandboxes && registry.sandboxes[sandboxName]; if (!sandbox) throw new Error(`missing sandbox registry entry: ${sandboxName}`); -if (sandbox.provider !== expectedProvider) { - throw new Error(`expected provider ${expectedProvider}, got ${sandbox.provider}`); +if (sandbox.provider !== "nvidia-prod") { + throw new Error(`expected provider nvidia-prod, got ${sandbox.provider}`); } if (sandbox.model !== expectedModel) { throw new Error(`expected model ${expectedModel}, got ${sandbox.model}`); @@ -560,13 +540,13 @@ else fail "Registry did not record requested provider, model, and policy presets" fi -if node - "$SESSION_FILE" "$SANDBOX_NAME" "$CLOUD_MODEL" "$EXPECTED_PROVIDER" <<'NODE'; then +if node - "$SESSION_FILE" "$SANDBOX_NAME" "$CLOUD_MODEL" <<'NODE'; then const fs = require("node:fs"); -const [sessionPath, sandboxName, expectedModel, expectedProvider] = process.argv.slice(2); +const [sessionPath, sandboxName, expectedModel] = process.argv.slice(2); const session = JSON.parse(fs.readFileSync(sessionPath, "utf8")); if (session.status !== "complete") throw new Error(`session status ${session.status}`); if (session.sandboxName !== sandboxName) throw new Error(`session sandbox ${session.sandboxName}`); -if (session.provider !== expectedProvider) throw new Error(`session provider ${session.provider}`); +if (session.provider !== "nvidia-prod") throw new Error(`session provider ${session.provider}`); if (session.model !== expectedModel) throw new Error(`session model ${session.model}`); const presets = Array.isArray(session.policyPresets) ? session.policyPresets : []; for (const preset of ["npm", "pypi"]) { diff --git a/test/e2e/test-onboard-repair.sh b/test/e2e/test-onboard-repair.sh index c62db5ce006..feac4117ee7 100755 --- a/test/e2e/test-onboard-repair.sh +++ b/test/e2e/test-onboard-repair.sh @@ -14,10 +14,10 @@ # - Docker running # - openshell CLI installed # - Node.js available -# - NVIDIA_INFERENCE_API_KEY set before starting the test +# - NVIDIA_API_KEY set to a valid nvapi-* key before starting the test # # Usage: -# NVIDIA_INFERENCE_API_KEY=... bash test/e2e/test-onboard-repair.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-onboard-repair.sh set -uo pipefail @@ -73,8 +73,6 @@ fi # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/sandbox-teardown.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "$(dirname "${BASH_SOURCE[0]}")/lib/ci-compatible-inference.sh" register_sandbox_for_teardown "$SANDBOX_NAME" register_sandbox_for_teardown "$OTHER_SANDBOX_NAME" if [ -n "$INSTALL_SANDBOX_NAME" ]; then @@ -82,7 +80,7 @@ if [ -n "$INSTALL_SANDBOX_NAME" ]; then fi SESSION_FILE="$HOME/.nemoclaw/onboard-session.json" -RESTORE_API_KEY="${NVIDIA_INFERENCE_API_KEY:-}" +RESTORE_API_KEY="${NVIDIA_API_KEY:-}" wait_openshell_sandbox_absent() { local sandbox_name="$1" @@ -150,15 +148,15 @@ else exit 1 fi -if [[ -z "$RESTORE_API_KEY" ]]; then - fail "NVIDIA_INFERENCE_API_KEY not set or invalid — required for resume completion" +if [[ -n "$RESTORE_API_KEY" && "$RESTORE_API_KEY" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set (starts with nvapi-)" +else + fail "NVIDIA_API_KEY not set or invalid — required for resume completion" exit 1 fi -pass "NVIDIA_INFERENCE_API_KEY is set" -export NVIDIA_INFERENCE_API_KEY="$RESTORE_API_KEY" -nemoclaw_e2e_configure_compatible_inference || exit 1 -pass "Exported NVIDIA_INFERENCE_API_KEY for the repair run (host writes nothing to disk; OpenShell gateway is the system of record)" +export NVIDIA_API_KEY="$RESTORE_API_KEY" +pass "Exported NVIDIA_API_KEY for the repair run (host writes nothing to disk; OpenShell gateway is the system of record)" # ══════════════════════════════════════════════════════════════════ # Phase 2: Create interrupted resumable state @@ -228,7 +226,7 @@ else fi REPAIR_LOG="$(mktemp)" -env -u NVIDIA_INFERENCE_API_KEY -u COMPATIBLE_API_KEY \ +env -u NVIDIA_API_KEY \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" \ @@ -301,7 +299,7 @@ pass "Re-created interrupted session for conflict tests" info "Attempting resume with a different sandbox name..." SANDBOX_CONFLICT_LOG="$(mktemp)" -env -u NVIDIA_INFERENCE_API_KEY -u COMPATIBLE_API_KEY \ +env -u NVIDIA_API_KEY \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_SANDBOX_NAME="$OTHER_SANDBOX_NAME" \ @@ -330,7 +328,7 @@ section "Phase 5: Reject conflicting provider and model" info "Attempting resume with conflicting provider/model inputs..." PROVIDER_CONFLICT_LOG="$(mktemp)" -env -u NVIDIA_INFERENCE_API_KEY -u COMPATIBLE_API_KEY \ +env -u NVIDIA_API_KEY \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" \ diff --git a/test/e2e/test-onboard-resume.sh b/test/e2e/test-onboard-resume.sh index 3145f5013d3..129f121e530 100755 --- a/test/e2e/test-onboard-resume.sh +++ b/test/e2e/test-onboard-resume.sh @@ -15,10 +15,10 @@ # - Docker running # - openshell CLI installed # - Node.js available -# - NVIDIA_INFERENCE_API_KEY set before starting the test +# - NVIDIA_API_KEY set to a valid nvapi-* key before starting the test # # Usage: -# NVIDIA_INFERENCE_API_KEY=... bash test/e2e/test-onboard-resume.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-onboard-resume.sh set -uo pipefail @@ -77,13 +77,11 @@ fi # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/sandbox-teardown.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "$(dirname "${BASH_SOURCE[0]}")/lib/ci-compatible-inference.sh" register_sandbox_for_teardown "$SANDBOX_NAME" SESSION_FILE="$HOME/.nemoclaw/onboard-session.json" REGISTRY="$HOME/.nemoclaw/sandboxes.json" -RESTORE_API_KEY="${NVIDIA_INFERENCE_API_KEY:-}" +RESTORE_API_KEY="${NVIDIA_API_KEY:-}" # ══════════════════════════════════════════════════════════════════ # Phase 0: Pre-cleanup @@ -123,25 +121,22 @@ else exit 1 fi -if [[ -z "$RESTORE_API_KEY" ]]; then - fail "NVIDIA_INFERENCE_API_KEY not set or invalid — required for resume completion" +if [[ -n "$RESTORE_API_KEY" && "$RESTORE_API_KEY" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set (starts with nvapi-)" +else + fail "NVIDIA_API_KEY not set or invalid — required for resume completion" exit 1 fi -pass "NVIDIA_INFERENCE_API_KEY is set" - -export NVIDIA_INFERENCE_API_KEY="$RESTORE_API_KEY" -nemoclaw_e2e_configure_compatible_inference || exit 1 -HOSTED_INFERENCE_BASE_URL="$(nemoclaw_e2e_hosted_inference_base_url)" -EXPECTED_PROVIDER="$(nemoclaw_e2e_expected_route_provider)" -if nemoclaw_e2e_probe_hosted_inference; then - pass "Network access to ${HOSTED_INFERENCE_BASE_URL}" +if curl -sf --max-time 10 https://integrate.api.nvidia.com/v1/models >/dev/null 2>&1; then + pass "Network access to integrate.api.nvidia.com" else - fail "Cannot reach ${HOSTED_INFERENCE_BASE_URL}" + fail "Cannot reach integrate.api.nvidia.com" exit 1 fi -pass "Exported NVIDIA_INFERENCE_API_KEY for the resume run (host writes nothing to disk; OpenShell gateway is the system of record)" +export NVIDIA_API_KEY="$RESTORE_API_KEY" +pass "Exported NVIDIA_API_KEY for the resume run (host writes nothing to disk; OpenShell gateway is the system of record)" # ══════════════════════════════════════════════════════════════════ # Phase 2: First onboard (forced failure after sandbox creation) @@ -214,10 +209,10 @@ esac # Phase 3: Resume and complete # ══════════════════════════════════════════════════════════════════ section "Phase 3: Resume" -info "Running onboard --resume with NVIDIA_INFERENCE_API_KEY removed from env..." +info "Running onboard --resume with NVIDIA_API_KEY removed from env..." RESUME_LOG="$(mktemp)" -env -u NVIDIA_INFERENCE_API_KEY -u COMPATIBLE_API_KEY \ +env -u NVIDIA_API_KEY \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" \ @@ -291,10 +286,9 @@ fi node -e ' const fs = require("fs"); const file = process.argv[1]; -const expectedProvider = process.argv[2]; const data = JSON.parse(fs.readFileSync(file, "utf8")); if (data.status !== "complete") process.exit(1); -if (data.provider !== expectedProvider) process.exit(2); +if (data.provider !== "nvidia-prod") process.exit(2); if (data.steps.preflight.status !== "complete") process.exit(3); if (data.steps.gateway.status !== "complete") process.exit(4); if (data.steps.sandbox.status !== "complete") process.exit(5); @@ -302,7 +296,7 @@ if (data.steps.provider_selection.status !== "complete") process.exit(6); if (data.steps.inference.status !== "complete") process.exit(7); if (data.steps.openclaw.status !== "complete") process.exit(8); if (data.steps.policies.status !== "complete") process.exit(9); -' "$SESSION_FILE" "$EXPECTED_PROVIDER" +' "$SESSION_FILE" case $? in 0) pass "Session file recorded full completion after resume" ;; *) fail "Session file did not record the expected completed state after resume" ;; diff --git a/test/e2e/test-openclaw-discord-pairing.sh b/test/e2e/test-openclaw-discord-pairing.sh index 29e6f64e17c..506ae183675 100755 --- a/test/e2e/test-openclaw-discord-pairing.sh +++ b/test/e2e/test-openclaw-discord-pairing.sh @@ -18,13 +18,13 @@ # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 - required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 - required -# NVIDIA_INFERENCE_API_KEY - required for onboarding +# NVIDIA_API_KEY - required for onboarding # NEMOCLAW_SANDBOX_NAME - sandbox name (default: e2e-openclaw-discord-pairing) # DISCORD_BOT_TOKEN - defaults to a fake token # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-openclaw-discord-pairing.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-openclaw-discord-pairing.sh # shellcheck disable=SC2016,SC2329 # SC2016: Single-quoted strings are intentional for commands evaluated inside @@ -211,11 +211,11 @@ NODE section "Phase 0: Prerequisites" -if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - fail "NVIDIA_INFERENCE_API_KEY not set" +if [ -z "${NVIDIA_API_KEY:-}" ]; then + fail "NVIDIA_API_KEY not set" exit 1 fi -pass "NVIDIA_INFERENCE_API_KEY is set" +pass "NVIDIA_API_KEY is set" if ! docker info >/dev/null 2>&1; then fail "Docker is not running" diff --git a/test/e2e/test-openclaw-inference-switch.sh b/test/e2e/test-openclaw-inference-switch.sh index d513f68390c..937ab09b879 100755 --- a/test/e2e/test-openclaw-inference-switch.sh +++ b/test/e2e/test-openclaw-inference-switch.sh @@ -10,7 +10,7 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set for hosted inference +# - NVIDIA_API_KEY set (real key, starts with nvapi-) # - NEMOCLAW_NON_INTERACTIVE=1 # - NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 @@ -353,16 +353,9 @@ E2E_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" . "${E2E_DIR}/lib/inference-switch-retry.sh" # shellcheck source=test/e2e/lib/anthropic-switch-provider.sh . "${E2E_DIR}/lib/anthropic-switch-provider.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${E2E_DIR}/lib/ci-compatible-inference.sh" SANDBOX_NAME="${NEMOCLAW_SANDBOX_NAME:-e2e-openclaw-inference-switch}" -if nemoclaw_e2e_using_compatible_inference; then - SWITCH_PROVIDER="${NEMOCLAW_SWITCH_PROVIDER:-$(nemoclaw_e2e_expected_route_provider)}" - SWITCH_MODEL="${NEMOCLAW_SWITCH_MODEL:-$(nemoclaw_e2e_hosted_inference_model)}" -else - SWITCH_PROVIDER="${NEMOCLAW_SWITCH_PROVIDER:-nvidia-prod}" - SWITCH_MODEL="${NEMOCLAW_SWITCH_MODEL:-z-ai/glm-5.1}" -fi +SWITCH_PROVIDER="${NEMOCLAW_SWITCH_PROVIDER:-nvidia-prod}" +SWITCH_MODEL="${NEMOCLAW_SWITCH_MODEL:-z-ai/glm-5.1}" SWITCH_INFERENCE_API="${NEMOCLAW_SWITCH_INFERENCE_API:-openai-completions}" # shellcheck disable=SC2034 # consumed by anthropic-switch-provider.sh helpers SWITCH_ENDPOINT_URL="${NEMOCLAW_SWITCH_ENDPOINT_URL:-}" @@ -378,7 +371,6 @@ trap 'stop_mock_anthropic_switch_provider; _nemoclaw_sandbox_teardown' EXIT # shellcheck source=test/e2e/lib/install-path-refresh.sh . "${E2E_DIR}/lib/install-path-refresh.sh" register_sandbox_for_teardown "$SANDBOX_NAME" -nemoclaw_e2e_configure_compatible_inference || exit 1 section "Phase 0: Pre-cleanup" if command -v nemoclaw >/dev/null 2>&1; then @@ -398,7 +390,10 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set" +else + fail "NVIDIA_API_KEY not set or invalid" exit 1 fi diff --git a/test/e2e/test-openclaw-plugin-runtime-exdev.sh b/test/e2e/test-openclaw-plugin-runtime-exdev.sh index 53817878621..55554501491 100755 --- a/test/e2e/test-openclaw-plugin-runtime-exdev.sh +++ b/test/e2e/test-openclaw-plugin-runtime-exdev.sh @@ -48,7 +48,7 @@ redact_file() { python3 - "$file" <<'PY' import os, sys path = sys.argv[1] -secrets = [os.environ.get("NVIDIA_INFERENCE_API_KEY", ""), os.environ.get("NEMOCLAW_PROVIDER_KEY", "")] +secrets = [os.environ.get("NVIDIA_API_KEY", ""), os.environ.get("NEMOCLAW_PROVIDER_KEY", "")] text = open(path, "r", errors="replace").read() for secret in filter(None, secrets): text = text.replace(secret, "") @@ -71,10 +71,10 @@ else exit 1 fi -if [ -n "${NVIDIA_INFERENCE_API_KEY:-}" ] && [[ "${NVIDIA_INFERENCE_API_KEY}" == nvapi-* ]]; then - pass "NVIDIA_INFERENCE_API_KEY is set" +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set" else - fail "NVIDIA_INFERENCE_API_KEY is required and must start with nvapi-" + fail "NVIDIA_API_KEY is required and must start with nvapi-" exit 1 fi @@ -119,13 +119,13 @@ for path in policy_paths: path.write_text(text.replace(needle, needle + additions, 1)) PY env \ - NEMOCLAW_PROVIDER_KEY="$NVIDIA_INFERENCE_API_KEY" \ + NEMOCLAW_PROVIDER_KEY="$NVIDIA_API_KEY" \ NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ NEMOCLAW_POLICY_MODE="skip" \ NEMOCLAW_PROVIDER="build" \ - NVIDIA_INFERENCE_API_KEY="$NVIDIA_INFERENCE_API_KEY" \ + NVIDIA_API_KEY="$NVIDIA_API_KEY" \ "$TIMEOUT_CMD" 1500 nemoclaw onboard --fresh --non-interactive --yes-i-accept-third-party-software --agent openclaw --from "$REPO/Dockerfile" \ >"$ONBOARD_LOG" 2>&1 onboard_rc=$? diff --git a/test/e2e/test-openclaw-skill-cli-e2e.sh b/test/e2e/test-openclaw-skill-cli-e2e.sh index 8229b6893ad..77fae6d9820 100755 --- a/test/e2e/test-openclaw-skill-cli-e2e.sh +++ b/test/e2e/test-openclaw-skill-cli-e2e.sh @@ -16,7 +16,7 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (needed to onboard the sandbox) +# - NVIDIA_API_KEY set (needed to onboard the sandbox) # - NEMOCLAW_NON_INTERACTIVE=1, NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 # # Environment: @@ -25,7 +25,7 @@ # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=... bash test/e2e/test-openclaw-skill-cli-e2e.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-openclaw-skill-cli-e2e.sh # shellcheck disable=SC2317 set -uo pipefail @@ -71,10 +71,7 @@ SKILL_DESCRIPTION="E2E fixture proving openclaw skills install + list roundtrip" # Source shared teardown helper # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "${E2E_DIR}/lib/sandbox-teardown.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${E2E_DIR}/lib/ci-compatible-inference.sh" register_sandbox_for_teardown "$SANDBOX_NAME" -nemoclaw_e2e_configure_compatible_inference || exit 1 # ══════════════════════════════════════════════════════════════════════ # Phase 1: Install + Prerequisites @@ -87,9 +84,11 @@ if ! docker info >/dev/null 2>&1; then fi pass "Docker is running" -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -z "${NVIDIA_API_KEY:-}" ] || [[ "${NVIDIA_API_KEY}" != nvapi-* ]]; then + fail "NVIDIA_API_KEY not set or invalid" exit 1 fi +pass "NVIDIA_API_KEY is set" cd "$REPO" || { fail "Could not cd to repo root" diff --git a/test/e2e/test-openclaw-slack-pairing.sh b/test/e2e/test-openclaw-slack-pairing.sh index 2da00c60c5f..eb183d42bee 100755 --- a/test/e2e/test-openclaw-slack-pairing.sh +++ b/test/e2e/test-openclaw-slack-pairing.sh @@ -16,14 +16,14 @@ # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 - required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 - required -# NVIDIA_INFERENCE_API_KEY - required for onboarding +# NVIDIA_API_KEY - required for onboarding # NEMOCLAW_SANDBOX_NAME - sandbox name (default: e2e-openclaw-slack-pairing) # SLACK_BOT_TOKEN - defaults to a fake xoxb- token # SLACK_APP_TOKEN - defaults to a fake xapp- token # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-openclaw-slack-pairing.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-openclaw-slack-pairing.sh # shellcheck disable=SC2016 # SC2016: Single-quoted strings are intentional for commands evaluated inside @@ -208,11 +208,11 @@ NODE section "Phase 0: Prerequisites" -if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - fail "NVIDIA_INFERENCE_API_KEY not set" +if [ -z "${NVIDIA_API_KEY:-}" ]; then + fail "NVIDIA_API_KEY not set" exit 1 fi -pass "NVIDIA_INFERENCE_API_KEY is set" +pass "NVIDIA_API_KEY is set" if ! docker info >/dev/null 2>&1; then fail "Docker is not running" diff --git a/test/e2e/test-overlayfs-autofix.sh b/test/e2e/test-overlayfs-autofix.sh index 686f9f00236..2a5df82f702 100755 --- a/test/e2e/test-overlayfs-autofix.sh +++ b/test/e2e/test-overlayfs-autofix.sh @@ -18,7 +18,7 @@ # needs entry in the same PR that deletes src/lib/cluster-image-patch.ts. # # Test phases: -# 1. Prerequisites — Docker running, NVIDIA_INFERENCE_API_KEY, sudo, etc. +# 1. Prerequisites — Docker running, NVIDIA_API_KEY, sudo, etc. # 2. Setup — flip /etc/docker/daemon.json to enable containerd-snapshotter, # restart Docker, verify the conflict config is active. Auto-skip on # runners whose Docker does not support the feature flag. @@ -46,12 +46,12 @@ # - Docker installed (any version that supports `features.containerd-snapshotter`, # i.e. Docker 23+; the test skips cleanly on older versions) # - Passwordless sudo (for editing /etc/docker/daemon.json + restarting Docker) -# - NVIDIA_INFERENCE_API_KEY set (real key; required by install.sh) +# - NVIDIA_API_KEY set (real key; required by install.sh) # # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 — required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 — required -# NVIDIA_INFERENCE_API_KEY — required +# NVIDIA_API_KEY — required # NEMOCLAW_SANDBOX_NAME — sandbox name (default: e2e-overlayfs) # NEMOCLAW_E2E_TIMEOUT_SECONDS — overall timeout (default: 1500) # NEMOCLAW_OVERLAYFS_E2E_NEGATIVE_TIMEOUT — negative-phase k3s wait (default: 300) @@ -59,7 +59,7 @@ # Usage: # NEMOCLAW_NON_INTERACTIVE=1 \ # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=... \ +# NVIDIA_API_KEY=nvapi-... \ # bash test/e2e/test-overlayfs-autofix.sh # ShellCheck cannot see EXIT trap invocations of cleanup helpers in this E2E script. @@ -70,8 +70,6 @@ export NEMOCLAW_E2E_DEFAULT_TIMEOUT=1500 SCRIPT_DIR_TIMEOUT="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" # shellcheck source=test/e2e/e2e-timeout.sh source "${SCRIPT_DIR_TIMEOUT}/e2e-timeout.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${SCRIPT_DIR_TIMEOUT}/lib/ci-compatible-inference.sh" PASS=0 FAIL=0 @@ -129,7 +127,6 @@ ONBOARD_LOG_NEGATIVE="/tmp/nemoclaw-e2e-onboard-negative.log" # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/sandbox-teardown.sh" register_sandbox_for_teardown "$SANDBOX_NAME" -nemoclaw_e2e_configure_compatible_inference || exit 1 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" @@ -175,7 +172,10 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set" +else + fail "NVIDIA_API_KEY not set or invalid" exit 1 fi diff --git a/test/e2e/test-rebuild-hermes.sh b/test/e2e/test-rebuild-hermes.sh index f9de6f7e04d..cbc2bdbea3b 100755 --- a/test/e2e/test-rebuild-hermes.sh +++ b/test/e2e/test-rebuild-hermes.sh @@ -19,12 +19,12 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (real key, starts with nvapi-) +# - NVIDIA_API_KEY set (real key, starts with nvapi-) # # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 — required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 — required -# NVIDIA_INFERENCE_API_KEY — required +# NVIDIA_API_KEY — required set -euo pipefail @@ -93,7 +93,7 @@ dump_hermes_sandbox_logs() { export NEMOCLAW_REBUILD_VERBOSE=1 # ── Preflight ─────────────────────────────────────────────────────── -[ -n "${NVIDIA_INFERENCE_API_KEY:-}" ] || fail "NVIDIA_INFERENCE_API_KEY is required" +[ -n "${NVIDIA_API_KEY:-}" ] || fail "NVIDIA_API_KEY is required" [ "${NEMOCLAW_NON_INTERACTIVE:-}" = "1" ] || fail "NEMOCLAW_NON_INTERACTIVE=1 is required" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" diff --git a/test/e2e/test-rebuild-openclaw.sh b/test/e2e/test-rebuild-openclaw.sh index 6794649fff2..6146db25362 100755 --- a/test/e2e/test-rebuild-openclaw.sh +++ b/test/e2e/test-rebuild-openclaw.sh @@ -19,12 +19,12 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (real key, starts with nvapi-) +# - NVIDIA_API_KEY set (real key, starts with nvapi-) # # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 — required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 — required -# NVIDIA_INFERENCE_API_KEY — required +# NVIDIA_API_KEY — required set -euo pipefail @@ -80,7 +80,7 @@ read_sandbox_config_hash() { export NEMOCLAW_REBUILD_VERBOSE=1 # ── Preflight ─────────────────────────────────────────────────────── -[ -n "${NVIDIA_INFERENCE_API_KEY:-}" ] || fail "NVIDIA_INFERENCE_API_KEY is required" +[ -n "${NVIDIA_API_KEY:-}" ] || fail "NVIDIA_API_KEY is required" [ "${NEMOCLAW_NON_INTERACTIVE:-}" = "1" ] || fail "NEMOCLAW_NON_INTERACTIVE=1 is required" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" diff --git a/test/e2e/test-sandbox-operations.sh b/test/e2e/test-sandbox-operations.sh index 98d1b015379..0d702a21d66 100755 --- a/test/e2e/test-sandbox-operations.sh +++ b/test/e2e/test-sandbox-operations.sh @@ -282,7 +282,7 @@ preflight() { fi log "Docker is running" - if [[ -z "${NVIDIA_INFERENCE_API_KEY:-}" && -z "${OPENAI_API_KEY:-}" && -z "${ANTHROPIC_API_KEY:-}" ]]; then + if [[ -z "${NVIDIA_API_KEY:-}" && -z "${OPENAI_API_KEY:-}" && -z "${ANTHROPIC_API_KEY:-}" ]]; then echo -e "${YELLOW}WARNING: No API key detected.${NC}" fi diff --git a/test/e2e/test-sandbox-rebuild.sh b/test/e2e/test-sandbox-rebuild.sh index df68ad1afa9..f066e4ff6a8 100755 --- a/test/e2e/test-sandbox-rebuild.sh +++ b/test/e2e/test-sandbox-rebuild.sh @@ -14,20 +14,20 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (real key, starts with nvapi-) -# - Network access to inference-api.nvidia.com +# - NVIDIA_API_KEY set (real key, starts with nvapi-) +# - Network access to integrate.api.nvidia.com # # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 — required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 — required -# NVIDIA_INFERENCE_API_KEY — required +# NVIDIA_API_KEY — required # NEMOCLAW_SANDBOX_NAME — sandbox name (default: e2e-rebuild) # NEMOCLAW_E2E_TIMEOUT_SECONDS — overall timeout (default: 1200) # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 \ # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... \ +# NVIDIA_API_KEY=nvapi-... \ # bash test/e2e/test-sandbox-rebuild.sh set -euo pipefail @@ -57,7 +57,7 @@ fail() { info() { echo -e "${YELLOW}[INFO]${NC} $1"; } # ── Preflight ─────────────────────────────────────────────────────── -[ -n "${NVIDIA_INFERENCE_API_KEY:-}" ] || fail "NVIDIA_INFERENCE_API_KEY is required" +[ -n "${NVIDIA_API_KEY:-}" ] || fail "NVIDIA_API_KEY is required" [ "${NEMOCLAW_NON_INTERACTIVE:-}" = "1" ] || fail "NEMOCLAW_NON_INTERACTIVE=1 is required" info "Starting rebuild E2E test (sandbox: ${SANDBOX_NAME}, timeout: ${TIMEOUT}s)" diff --git a/test/e2e/test-sandbox-survival.sh b/test/e2e/test-sandbox-survival.sh index 39117cf5b0b..ca509e611c5 100755 --- a/test/e2e/test-sandbox-survival.sh +++ b/test/e2e/test-sandbox-survival.sh @@ -22,20 +22,20 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set for hosted inference -# - Network access to inference-api.nvidia.com +# - NVIDIA_API_KEY set (real key, starts with nvapi-) +# - Network access to integrate.api.nvidia.com # # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 — required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 — required -# NVIDIA_INFERENCE_API_KEY — required for hosted inference +# NVIDIA_API_KEY — required for real NVIDIA Endpoints inference # NEMOCLAW_SANDBOX_NAME — sandbox name (default: e2e-survival) # NEMOCLAW_E2E_TIMEOUT_SECONDS — overall timeout (default: 900) # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 \ # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=... \ +# NVIDIA_API_KEY=nvapi-... \ # bash test/e2e/test-sandbox-survival.sh set -uo pipefail @@ -44,8 +44,6 @@ export NEMOCLAW_E2E_DEFAULT_TIMEOUT=900 SCRIPT_DIR_TIMEOUT="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" # shellcheck source=test/e2e/e2e-timeout.sh source "${SCRIPT_DIR_TIMEOUT}/e2e-timeout.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${SCRIPT_DIR_TIMEOUT}/lib/ci-compatible-inference.sh" PASS=0 FAIL=0 @@ -95,9 +93,6 @@ version_gte() { } SANDBOX_NAME="${NEMOCLAW_SANDBOX_NAME:-e2e-survival}" -nemoclaw_e2e_configure_compatible_inference || exit 1 -HOSTED_INFERENCE_BASE_URL="$(nemoclaw_e2e_hosted_inference_base_url)" -MODEL="$(nemoclaw_e2e_hosted_inference_model)" # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/sandbox-teardown.sh" @@ -107,6 +102,7 @@ REGISTRY="$HOME/.nemoclaw/sandboxes.json" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" MIN_OPENSHELL="0.0.24" +MODEL="nvidia/nemotron-3-super-120b-a12b" # SSH helper — sets up SSH config and common options for sandbox access # Sets: ssh_config, SSH_OPTS, SSH_TARGET @@ -211,14 +207,17 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set (starts with nvapi-)" +else + fail "NVIDIA_API_KEY not set or invalid — required for live inference" exit 1 fi -if nemoclaw_e2e_probe_hosted_inference; then - pass "Network access to ${HOSTED_INFERENCE_BASE_URL}" +if curl -sf --max-time 10 https://integrate.api.nvidia.com/v1/models >/dev/null 2>&1; then + pass "Network access to integrate.api.nvidia.com" else - fail "Cannot reach ${HOSTED_INFERENCE_BASE_URL}" + fail "Cannot reach integrate.api.nvidia.com" exit 1 fi @@ -383,7 +382,7 @@ else fi # 4b: Live inference through sandbox -info "[LIVE] Baseline inference: user → sandbox → gateway → hosted inference endpoint..." +info "[LIVE] Baseline inference: user → sandbox → gateway → NVIDIA Endpoints..." # shellcheck disable=SC2029 # client-side expansion is intentional baseline_response=$(run_with_timeout 90 ssh "${SSH_OPTS[@]}" "$SSH_TARGET" \ "curl -s --max-time 60 https://inference.local/v1/chat/completions \ @@ -719,7 +718,7 @@ fi # ══════════════════════════════════════════════════════════════════ section "Phase 10: Live inference after restart (THE definitive test)" -info "[LIVE] Post-restart inference: user → sandbox → gateway → hosted inference endpoint..." +info "[LIVE] Post-restart inference: user → sandbox → gateway → NVIDIA Endpoints..." # shellcheck disable=SC2029 post_response=$(run_with_timeout 90 ssh "${SSH_OPTS[@]}" "$SSH_TARGET" \ "curl -s --max-time 60 https://inference.local/v1/chat/completions \ @@ -751,7 +750,7 @@ for pong_attempt in 1 2 3; do done if $pong_ok; then pass "[LIVE] Post-restart: model responded with PONG through sandbox" - info "Full path proven: user → sandbox → openshell gateway (resumed) → hosted inference endpoint → response" + info "Full path proven: user → sandbox → openshell gateway (resumed) → NVIDIA Endpoints → response" info "This proves #859's ask: reliable non-destructive gateway lifecycle with working inference" else fail "[LIVE] Post-restart: expected PONG after 3 attempts, got: ${post_content:0:200}" diff --git a/test/e2e/test-sessions-agents-cli.sh b/test/e2e/test-sessions-agents-cli.sh index d9160fba0c9..87175261847 100755 --- a/test/e2e/test-sessions-agents-cli.sh +++ b/test/e2e/test-sessions-agents-cli.sh @@ -28,12 +28,12 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (real key or fake OpenAI endpoint) +# - NVIDIA_API_KEY set (real key or fake OpenAI endpoint) # - NEMOCLAW_NON_INTERACTIVE=1, NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-sessions-agents-cli.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-sessions-agents-cli.sh # ============================================================================= set -uo pipefail @@ -156,12 +156,12 @@ preflight() { print_summary exit 1 fi - if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - skip "preflight: NVIDIA_INFERENCE_API_KEY not set; sessions/agents E2E requires a working onboard credential" + if [ -z "${NVIDIA_API_KEY:-}" ]; then + skip "preflight: NVIDIA_API_KEY not set; sessions/agents E2E requires a working onboard credential" print_summary exit 0 fi - pass "preflight: docker + NVIDIA_INFERENCE_API_KEY available" + pass "preflight: docker + NVIDIA_API_KEY available" } onboard_sandbox() { diff --git a/test/e2e/test-shields-config.sh b/test/e2e/test-shields-config.sh index 20b1529fee5..7ed586e7c9c 100755 --- a/test/e2e/test-shields-config.sh +++ b/test/e2e/test-shields-config.sh @@ -19,12 +19,12 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set for hosted inference +# - NVIDIA_API_KEY set (real key, starts with nvapi-) # # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 — required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 — required -# NVIDIA_INFERENCE_API_KEY — required +# NVIDIA_API_KEY — required # NEMOCLAW_SANDBOX_NAME — sandbox name (default: e2e-shields) # NEMOCLAW_E2E_TIMEOUT_SECONDS — overall timeout (default: 900) @@ -34,8 +34,6 @@ export NEMOCLAW_E2E_DEFAULT_TIMEOUT=900 SCRIPT_DIR_TIMEOUT="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" # shellcheck source=test/e2e/e2e-timeout.sh source "${SCRIPT_DIR_TIMEOUT}/e2e-timeout.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${SCRIPT_DIR_TIMEOUT}/lib/ci-compatible-inference.sh" PASS=0 FAIL=0 @@ -62,7 +60,6 @@ SANDBOX_NAME="${NEMOCLAW_SANDBOX_NAME:-e2e-shields}" # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "$(dirname "${BASH_SOURCE[0]}")/lib/sandbox-teardown.sh" register_sandbox_for_teardown "$SANDBOX_NAME" -nemoclaw_e2e_configure_compatible_inference || exit 1 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" @@ -82,7 +79,10 @@ else exit 1 fi -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -n "${NVIDIA_API_KEY:-}" ] && [[ "${NVIDIA_API_KEY}" == nvapi-* ]]; then + pass "NVIDIA_API_KEY is set" +else + fail "NVIDIA_API_KEY not set or invalid" exit 1 fi diff --git a/test/e2e/test-skill-agent-e2e.sh b/test/e2e/test-skill-agent-e2e.sh index f4ef86a929c..f08e0ccc538 100755 --- a/test/e2e/test-skill-agent-e2e.sh +++ b/test/e2e/test-skill-agent-e2e.sh @@ -13,7 +13,7 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set for hosted inference +# - NVIDIA_API_KEY set (real key, starts with nvapi-) # - NEMOCLAW_NON_INTERACTIVE=1, NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 # # Environment: @@ -24,7 +24,7 @@ # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=... bash test/e2e/test-skill-agent-e2e.sh +# NVIDIA_API_KEY=nvapi-... bash test/e2e/test-skill-agent-e2e.sh # ShellCheck cannot see EXIT trap invocations of cleanup helpers in this E2E script. # shellcheck disable=SC2317 @@ -98,10 +98,7 @@ RETRY_SLEEP="${E2E_SKILL_AGENT_RETRY_SLEEP_SEC:-15}" # Source shared teardown helper # shellcheck source=test/e2e/lib/sandbox-teardown.sh . "${E2E_DIR}/lib/sandbox-teardown.sh" -# shellcheck source=test/e2e/lib/ci-compatible-inference.sh -. "${E2E_DIR}/lib/ci-compatible-inference.sh" register_sandbox_for_teardown "$SANDBOX_NAME" -nemoclaw_e2e_configure_compatible_inference || exit 1 # ══════════════════════════════════════════════════════════════════════ # Phase 1: Install + Prerequisites @@ -114,9 +111,11 @@ if ! docker info >/dev/null 2>&1; then fi pass "Docker is running" -if ! nemoclaw_e2e_require_hosted_inference_key; then +if [ -z "${NVIDIA_API_KEY:-}" ] || [[ "${NVIDIA_API_KEY}" != nvapi-* ]]; then + fail "NVIDIA_API_KEY not set or invalid" exit 1 fi +pass "NVIDIA_API_KEY is set" cd "$REPO" || { fail "Could not cd to repo root" @@ -194,7 +193,7 @@ while [ "$attempt" -le "$MAX_ATTEMPTS" ]; do set +e agent_out=$( - NVIDIA_INFERENCE_API_KEY="$NVIDIA_INFERENCE_API_KEY" \ + NVIDIA_API_KEY="$NVIDIA_API_KEY" \ SANDBOX_NAME="$SANDBOX_NAME" \ SKILL_ID="$SKILL_ID" \ VERIFY_TOKEN="$VERIFY_PHRASE" \ diff --git a/test/e2e/test-snapshot-commands.sh b/test/e2e/test-snapshot-commands.sh index 2aaff425d6e..e70d4953497 100755 --- a/test/e2e/test-snapshot-commands.sh +++ b/test/e2e/test-snapshot-commands.sh @@ -15,12 +15,12 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (real key, starts with nvapi-) +# - NVIDIA_API_KEY set (real key, starts with nvapi-) # # Environment variables: # NEMOCLAW_NON_INTERACTIVE=1 — required # NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 — required -# NVIDIA_INFERENCE_API_KEY — required +# NVIDIA_API_KEY — required set -euo pipefail @@ -80,7 +80,7 @@ run_capture() { } # ── Preflight ─────────────────────────────────────────────────────── -[ -n "${NVIDIA_INFERENCE_API_KEY:-}" ] || fail "NVIDIA_INFERENCE_API_KEY is required" +[ -n "${NVIDIA_API_KEY:-}" ] || fail "NVIDIA_API_KEY is required" [ "${NEMOCLAW_NON_INTERACTIVE:-}" = "1" ] || fail "NEMOCLAW_NON_INTERACTIVE=1 is required" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" diff --git a/test/e2e/test-state-backup-restore.sh b/test/e2e/test-state-backup-restore.sh index 7e8637106b8..1763943fec0 100755 --- a/test/e2e/test-state-backup-restore.sh +++ b/test/e2e/test-state-backup-restore.sh @@ -11,8 +11,8 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set -# - Network access to inference-api.nvidia.com +# - NVIDIA_API_KEY set +# - Network access to integrate.api.nvidia.com # ============================================================================= set -euo pipefail @@ -81,7 +81,7 @@ install_nemoclaw() { fi log "=== Installing NemoClaw via install.sh ===" NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" \ - NVIDIA_INFERENCE_API_KEY="${NVIDIA_INFERENCE_API_KEY:-nvapi-DUMMY-FOR-INSTALL}" \ + NVIDIA_API_KEY="${NVIDIA_API_KEY:-nvapi-DUMMY-FOR-INSTALL}" \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ bash "$REPO_ROOT/install.sh" --non-interactive --yes-i-accept-third-party-software \ @@ -102,9 +102,9 @@ preflight() { fi log "Docker is running" - local api_key="${NVIDIA_INFERENCE_API_KEY:-}" + local api_key="${NVIDIA_API_KEY:-}" if [[ -z "$api_key" ]]; then - log "ERROR: NVIDIA_INFERENCE_API_KEY not set" + log "ERROR: NVIDIA_API_KEY not set" exit 1 fi diff --git a/test/e2e/test-telegram-injection.sh b/test/e2e/test-telegram-injection.sh index aa6834b08f6..de90ddec766 100755 --- a/test/e2e/test-telegram-injection.sh +++ b/test/e2e/test-telegram-injection.sh @@ -25,15 +25,15 @@ # Prerequisites: # - Docker running # - NemoClaw installed and sandbox running (test-full-e2e.sh Phase 0-3) -# - NVIDIA_INFERENCE_API_KEY set +# - NVIDIA_API_KEY set # - openshell on PATH # # Environment variables: # NEMOCLAW_SANDBOX_NAME — sandbox name (default: e2e-test) -# NVIDIA_INFERENCE_API_KEY — required +# NVIDIA_API_KEY — required # # Usage: -# NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 NVIDIA_INFERENCE_API_KEY=nvapi-... bash test/e2e/test-telegram-injection.sh +# NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 NVIDIA_API_KEY=nvapi-... bash test/e2e/test-telegram-injection.sh # # See: https://github.com/NVIDIA/NemoClaw/issues/118 # https://github.com/NVIDIA/NemoClaw/pull/119 @@ -145,11 +145,11 @@ sandbox_exec() { # ══════════════════════════════════════════════════════════════════ section "Phase 0: Prerequisites" -if [ -z "${NVIDIA_INFERENCE_API_KEY:-}" ]; then - fail "NVIDIA_INFERENCE_API_KEY not set" +if [ -z "${NVIDIA_API_KEY:-}" ]; then + fail "NVIDIA_API_KEY not set" exit 1 fi -pass "NVIDIA_INFERENCE_API_KEY is set" +pass "NVIDIA_API_KEY is set" if ! command -v openshell >/dev/null 2>&1; then fail "openshell not found on PATH" @@ -271,12 +271,12 @@ fi # ══════════════════════════════════════════════════════════════════ section "Phase 3: Parameter Expansion" -# T4: ${NVIDIA_INFERENCE_API_KEY} must not expand to the actual key value -info "T4: Testing \${NVIDIA_INFERENCE_API_KEY} expansion..." +# T4: ${NVIDIA_API_KEY} must not expand to the actual key value +info "T4: Testing \${NVIDIA_API_KEY} expansion..." ssh_config_t4="$(mktemp)" openshell sandbox ssh-config "$SANDBOX_NAME" >"$ssh_config_t4" 2>/dev/null -PAYLOAD_ENV='${NVIDIA_INFERENCE_API_KEY}' +PAYLOAD_ENV='${NVIDIA_API_KEY}' t4_result=$(timeout 30 ssh -F "$ssh_config_t4" \ -o StrictHostKeyChecking=no \ @@ -287,14 +287,14 @@ t4_result=$(timeout 30 ssh -F "$ssh_config_t4" \ <<<"$PAYLOAD_ENV" 2>&1) || true rm -f "$ssh_config_t4" -# The result should contain the literal string ${NVIDIA_INFERENCE_API_KEY}, not a nvapi- value +# The result should contain the literal string ${NVIDIA_API_KEY}, not a nvapi- value if echo "$t4_result" | grep -q "nvapi-"; then - fail "T4: \${NVIDIA_INFERENCE_API_KEY} expanded to actual key value — secret leaked!" -elif echo "$t4_result" | grep -qF '${NVIDIA_INFERENCE_API_KEY}'; then - pass "T4: \${NVIDIA_INFERENCE_API_KEY} treated as literal string (not expanded)" + fail "T4: \${NVIDIA_API_KEY} expanded to actual key value — secret leaked!" +elif echo "$t4_result" | grep -qF '${NVIDIA_API_KEY}'; then + pass "T4: \${NVIDIA_API_KEY} treated as literal string (not expanded)" else # Empty or other result — still safe as long as key not leaked - pass "T4: \${NVIDIA_INFERENCE_API_KEY} did not expand to key value (result: ${t4_result:0:100})" + pass "T4: \${NVIDIA_API_KEY} did not expand to key value (result: ${t4_result:0:100})" fi # ══════════════════════════════════════════════════════════════════ @@ -302,11 +302,11 @@ fi # ══════════════════════════════════════════════════════════════════ section "Phase 4: Process Table Leak Check" -# T5: NVIDIA_INFERENCE_API_KEY must not appear in ps aux output +# T5: NVIDIA_API_KEY must not appear in ps aux output info "T5: Checking process table for API key leaks..." # Get truncated key for a safe comparison (first 15 chars of key value) -API_KEY_PREFIX="${NVIDIA_INFERENCE_API_KEY:0:15}" +API_KEY_PREFIX="${NVIDIA_API_KEY:0:15}" # Check both the Brev host and inside the sandbox host_ps=$(ps aux 2>/dev/null || true) @@ -331,9 +331,9 @@ if echo "$sandbox_ps" | grep -qF "$API_KEY_PREFIX"; then fi if [ "$HOST_LEAK" = true ]; then - fail "T5: NVIDIA_INFERENCE_API_KEY found in HOST process table" + fail "T5: NVIDIA_API_KEY found in HOST process table" elif [ "$SANDBOX_LEAK" = true ]; then - fail "T5: NVIDIA_INFERENCE_API_KEY found in SANDBOX process table" + fail "T5: NVIDIA_API_KEY found in SANDBOX process table" else pass "T5: API key not visible in process tables (host or sandbox)" fi diff --git a/test/e2e/test-token-rotation.sh b/test/e2e/test-token-rotation.sh index 55be2ebf2f1..2fa16d2ed5d 100755 --- a/test/e2e/test-token-rotation.sh +++ b/test/e2e/test-token-rotation.sh @@ -16,7 +16,7 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (or CI-compatible inference env) +# - NVIDIA_API_KEY set (or fake OpenAI endpoint) # - TELEGRAM_BOT_TOKEN_A and TELEGRAM_BOT_TOKEN_B set (can be fake) # - DISCORD_BOT_TOKEN_A and DISCORD_BOT_TOKEN_B set (can be fake) # - SLACK_BOT_TOKEN_A and SLACK_BOT_TOKEN_B set (can be fake; xoxb- prefix) @@ -24,7 +24,7 @@ # # Usage: # NEMOCLAW_NON_INTERACTIVE=1 NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ -# NVIDIA_INFERENCE_API_KEY=nvapi-... \ +# NVIDIA_API_KEY=nvapi-... \ # TELEGRAM_BOT_TOKEN_A=fake-a TELEGRAM_BOT_TOKEN_B=fake-b \ # DISCORD_BOT_TOKEN_A=fake-c DISCORD_BOT_TOKEN_B=fake-d \ # SLACK_BOT_TOKEN_A=xoxb-fake-a SLACK_BOT_TOKEN_B=xoxb-fake-b \ diff --git a/test/e2e/test-tunnel-lifecycle.sh b/test/e2e/test-tunnel-lifecycle.sh index 9c7260f0b31..7b2ec9ee4a1 100755 --- a/test/e2e/test-tunnel-lifecycle.sh +++ b/test/e2e/test-tunnel-lifecycle.sh @@ -13,8 +13,8 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set -# - Network access to inference-api.nvidia.com +# - NVIDIA_API_KEY set +# - Network access to integrate.api.nvidia.com # ============================================================================= set -euo pipefail @@ -86,7 +86,7 @@ install_nemoclaw() { fi log "=== Installing NemoClaw via install.sh ===" NEMOCLAW_SANDBOX_NAME="$SANDBOX_NAME" \ - NVIDIA_INFERENCE_API_KEY="${NVIDIA_INFERENCE_API_KEY:-nvapi-DUMMY-FOR-INSTALL}" \ + NVIDIA_API_KEY="${NVIDIA_API_KEY:-nvapi-DUMMY-FOR-INSTALL}" \ NEMOCLAW_NON_INTERACTIVE=1 \ NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \ bash "$REPO_ROOT/install.sh" --non-interactive --yes-i-accept-third-party-software \ @@ -107,9 +107,9 @@ preflight() { fi log "Docker is running" - local api_key="${NVIDIA_INFERENCE_API_KEY:-}" + local api_key="${NVIDIA_API_KEY:-}" if [[ -z "$api_key" ]]; then - log "ERROR: NVIDIA_INFERENCE_API_KEY not set" + log "ERROR: NVIDIA_API_KEY not set" exit 1 fi diff --git a/test/e2e/test-upgrade-stale-sandbox.sh b/test/e2e/test-upgrade-stale-sandbox.sh index 3b3790ae7d9..b2bad3dbe3c 100755 --- a/test/e2e/test-upgrade-stale-sandbox.sh +++ b/test/e2e/test-upgrade-stale-sandbox.sh @@ -18,7 +18,7 @@ # # Prerequisites: # - Docker running -# - NVIDIA_INFERENCE_API_KEY set (real key, starts with nvapi-) +# - NVIDIA_API_KEY set (real key, starts with nvapi-) set -euo pipefail @@ -51,7 +51,7 @@ info() { echo -e "${YELLOW}[INFO]${NC} $1"; } diag() { echo -e "${YELLOW}[DIAG]${NC} $1"; } # ── Preflight ─────────────────────────────────────────────────────── -[ -n "${NVIDIA_INFERENCE_API_KEY:-}" ] || fail "NVIDIA_INFERENCE_API_KEY is required" +[ -n "${NVIDIA_API_KEY:-}" ] || fail "NVIDIA_API_KEY is required" [ "${NEMOCLAW_NON_INTERACTIVE:-}" = "1" ] || fail "NEMOCLAW_NON_INTERACTIVE=1 is required" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" diff --git a/test/gateway-state-reconcile-2276.test.ts b/test/gateway-state-reconcile-2276.test.ts index 11ff6948089..eb894ce0bc4 100644 --- a/test/gateway-state-reconcile-2276.test.ts +++ b/test/gateway-state-reconcile-2276.test.ts @@ -756,7 +756,7 @@ describe("Scenario 14 (#4497): connect preserves registry so rebuild can recover // HOME — fine: the assertions below target the recovery markers that // are emitted BEFORE the recreate, proving rebuild crossed the // backup gate that previously blocked it. - NVIDIA_INFERENCE_API_KEY: "", + NVIDIA_API_KEY: "", NEMOCLAW_PROVIDER_KEY: "", }, }, diff --git a/test/helpers/onboard-final-flow-phases.ts b/test/helpers/onboard-final-flow-phases.ts index 864659b4a41..edf9892da0c 100644 --- a/test/helpers/onboard-final-flow-phases.ts +++ b/test/helpers/onboard-final-flow-phases.ts @@ -147,7 +147,7 @@ export function context( model: "nvidia/test", provider: "nim", endpointUrl: "https://example.test/v1", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", hermesAuthMethod: null, hermesToolGateways: ["local"], preferredInferenceApi: "chat", diff --git a/test/host-artifact-cleanup.test.ts b/test/host-artifact-cleanup.test.ts index 6aea1af6355..e1e8e1aa323 100644 --- a/test/host-artifact-cleanup.test.ts +++ b/test/host-artifact-cleanup.test.ts @@ -68,7 +68,7 @@ describe("cleanupStaleHostFiles (post-upgrade sweep, #3105)", () => { const credsDir = path.join(home, ".nemoclaw"); const legacyFile = path.join(credsDir, "credentials.json"); fs.mkdirSync(credsDir, { recursive: true }); - const payload = JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "nvapi-real" }); + const payload = JSON.stringify({ NVIDIA_API_KEY: "nvapi-real" }); fs.writeFileSync(legacyFile, payload, { mode: 0o600 }); vi.stubEnv("HOME", home); diff --git a/test/nemoclaw-start.test.ts b/test/nemoclaw-start.test.ts index c2a7a293152..bd0bd21be5f 100644 --- a/test/nemoclaw-start.test.ts +++ b/test/nemoclaw-start.test.ts @@ -4166,7 +4166,7 @@ describe("write_auth_profile (#1332)", () => { it("writes profile under the provider key from NEMOCLAW_PROVIDER_KEY", () => { const { home, authPath, status, stderr } = runWriteAuthProfile({ - NVIDIA_INFERENCE_API_KEY: "secret", + NVIDIA_API_KEY: "secret", NEMOCLAW_PROVIDER_KEY: "openai", }); try { @@ -4176,7 +4176,7 @@ describe("write_auth_profile (#1332)", () => { "openai:manual": { type: "api_key", provider: "openai", - keyRef: { source: "env", id: "NVIDIA_INFERENCE_API_KEY" }, + keyRef: { source: "env", id: "NVIDIA_API_KEY" }, profileId: "openai:manual", }, }); @@ -4187,7 +4187,7 @@ describe("write_auth_profile (#1332)", () => { it("falls back to 'inference' when NEMOCLAW_PROVIDER_KEY is unset", () => { const { home, authPath, status, stderr } = runWriteAuthProfile({ - NVIDIA_INFERENCE_API_KEY: "secret", + NVIDIA_API_KEY: "secret", }); try { expect(status, stderr).toBe(0); @@ -4202,7 +4202,7 @@ describe("write_auth_profile (#1332)", () => { it("does not use 'nvidia' as the default provider key", () => { const { home, authPath, status } = runWriteAuthProfile({ - NVIDIA_INFERENCE_API_KEY: "secret", + NVIDIA_API_KEY: "secret", }); try { expect(status).toBe(0); @@ -4219,7 +4219,7 @@ describe("write_auth_profile (#1332)", () => { // If the provider_key were interpolated into the heredoc instead of // passed as argv, $(...) inside the value would execute and replace it. const { home, authPath, status, stderr } = runWriteAuthProfile({ - NVIDIA_INFERENCE_API_KEY: "secret", + NVIDIA_API_KEY: "secret", NEMOCLAW_PROVIDER_KEY: "$(echo pwned)", }); try { @@ -4233,7 +4233,7 @@ describe("write_auth_profile (#1332)", () => { } }); - it("is a no-op when NVIDIA_INFERENCE_API_KEY is unset", () => { + it("is a no-op when NVIDIA_API_KEY is unset", () => { const { home, authPath, status } = runWriteAuthProfile({}); try { expect(status).toBe(0); @@ -4245,7 +4245,7 @@ describe("write_auth_profile (#1332)", () => { it("writes the auth profile with 0600 permissions", () => { const { home, authPath, status } = runWriteAuthProfile({ - NVIDIA_INFERENCE_API_KEY: "secret", + NVIDIA_API_KEY: "secret", NEMOCLAW_PROVIDER_KEY: "openai", }); try { diff --git a/test/no-direct-credential-env.test.ts b/test/no-direct-credential-env.test.ts index ce92749ada0..eea90f46ee7 100644 --- a/test/no-direct-credential-env.test.ts +++ b/test/no-direct-credential-env.test.ts @@ -19,13 +19,11 @@ import { findDirectCredentialEnvReads } from "../scripts/checks/direct-credentia describe("direct credential env guard", () => { it.each([ // Assignments (write context) — allowed - 'process.env.NVIDIA_INFERENCE_API_KEY = "test";', 'process.env.NVIDIA_API_KEY = "test";', "process.env.OPENAI_API_KEY = value;", "process.env[credentialEnv] = providerKey;", // Deletions (write context) — allowed - "delete process.env.NVIDIA_INFERENCE_API_KEY;", "delete process.env.NVIDIA_API_KEY;", "delete process.env.ANTHROPIC_API_KEY;", @@ -38,26 +36,25 @@ describe("direct credential env guard", () => { "const x = process.env.NEMOCLAW_PROVIDER_KEY;", // Correct patterns — allowed - 'const key = getCredential("NVIDIA_INFERENCE_API_KEY");', - 'const key = resolveProviderCredential("NVIDIA_INFERENCE_API_KEY");', + 'const key = getCredential("NVIDIA_API_KEY");', + 'const key = resolveProviderCredential("NVIDIA_API_KEY");', // Bracketed string-literal assignments — allowed - 'process.env["NVIDIA_INFERENCE_API_KEY"] = "test";', + 'process.env["NVIDIA_API_KEY"] = "test";', // Dynamic access with non-credential variable name — allowed "const x = process.env[someKey];", "const x = process.env[envName];", // Explicitly suppressed raw-env reads — allowed - "// check-direct-credential-env-ignore -- raw env check required\nconst key = process.env.NVIDIA_INFERENCE_API_KEY;", - "// no-direct-credential-env -- backward-compatible suppression\nconst key = process.env.NVIDIA_INFERENCE_API_KEY;", + "// check-direct-credential-env-ignore -- raw env check required\nconst key = process.env.NVIDIA_API_KEY;", + "// no-direct-credential-env -- backward-compatible suppression\nconst key = process.env.NVIDIA_API_KEY;", ])("allows %s", (code) => { expect(findDirectCredentialEnvReads(code)).toEqual([]); }); it.each([ // Static reads of known credential keys - ["const key = process.env.NVIDIA_INFERENCE_API_KEY;", "NVIDIA_INFERENCE_API_KEY"], ["const key = process.env.NVIDIA_API_KEY;", "NVIDIA_API_KEY"], ["const key = process.env.OPENAI_API_KEY;", "OPENAI_API_KEY"], ["const key = process.env.ANTHROPIC_API_KEY;", "ANTHROPIC_API_KEY"], @@ -66,11 +63,9 @@ describe("direct credential env guard", () => { ["const key = process.env.COMPATIBLE_ANTHROPIC_API_KEY;", "COMPATIBLE_ANTHROPIC_API_KEY"], // Conditional check (read context) - ["if (!process.env.NVIDIA_INFERENCE_API_KEY) {}", "NVIDIA_INFERENCE_API_KEY"], ["if (!process.env.NVIDIA_API_KEY) {}", "NVIDIA_API_KEY"], // Bracketed string-literal reads - ['const key = process.env["NVIDIA_INFERENCE_API_KEY"];', "NVIDIA_INFERENCE_API_KEY"], ['const key = process.env["NVIDIA_API_KEY"];', "NVIDIA_API_KEY"], ['if (!process.env["OPENAI_API_KEY"]) {}', "OPENAI_API_KEY"], @@ -80,8 +75,8 @@ describe("direct credential env guard", () => { // Suppression token inside non-comment text must not suppress. [ - "const marker = 'no-direct-credential-env';\nconst key = process.env.NVIDIA_INFERENCE_API_KEY;", - "NVIDIA_INFERENCE_API_KEY", + "const marker = 'no-direct-credential-env';\nconst key = process.env.NVIDIA_API_KEY;", + "NVIDIA_API_KEY", ], ])("flags %s", (code, key) => { expect(findDirectCredentialEnvReads(code)).toMatchObject([{ key }]); diff --git a/test/ollama-proxy-recovery.test.ts b/test/ollama-proxy-recovery.test.ts index 86764567db1..c28f2dd19a1 100644 --- a/test/ollama-proxy-recovery.test.ts +++ b/test/ollama-proxy-recovery.test.ts @@ -167,7 +167,7 @@ console.log(JSON.stringify({ proxySpawns, curlEnv })); ...process.env, HTTP_PROXY: "http://proxy.invalid:8888", HOME: tmpDir, - NVIDIA_INFERENCE_API_KEY: "must-not-leak", + NVIDIA_API_KEY: "must-not-leak", NO_PROXY: "", }, }); @@ -178,7 +178,7 @@ console.log(JSON.stringify({ proxySpawns, curlEnv })); proxySpawns: object[]; }>(result.stdout); assert.equal(payload.proxySpawns.length, 0); - assert.equal(payload.curlEnv.NVIDIA_INFERENCE_API_KEY, undefined); + assert.equal(payload.curlEnv.NVIDIA_API_KEY, undefined); assert.equal(payload.curlEnv.HTTP_PROXY, "http://proxy.invalid:8888"); assert.match(payload.curlEnv.NO_PROXY, /(^|,)127\.0\.0\.1(,|$)/); assert.match(payload.curlEnv.NO_PROXY, /(^|,)localhost(,|$)/); diff --git a/test/onboard-messaging.test.ts b/test/onboard-messaging.test.ts index c008c1b85d9..28ce5120bb9 100644 --- a/test/onboard-messaging.test.ts +++ b/test/onboard-messaging.test.ts @@ -263,9 +263,9 @@ const { createSandbox, setupMessagingChannels } = require(${onboardPath}); "TELEGRAM_BOT_TOKEN must not be in sandbox env", ); assert.equal( - createCommand.env.NVIDIA_INFERENCE_API_KEY, + createCommand.env.NVIDIA_API_KEY, undefined, - "NVIDIA_INFERENCE_API_KEY must not be in sandbox env", + "NVIDIA_API_KEY must not be in sandbox env", ); assert.equal(createCommand.env.KUBECONFIG, undefined, "KUBECONFIG must not be in sandbox env"); assert.equal( diff --git a/test/onboard-model-router.test.ts b/test/onboard-model-router.test.ts index 0702e011f30..75c5eee4ba8 100644 --- a/test/onboard-model-router.test.ts +++ b/test/onboard-model-router.test.ts @@ -163,7 +163,7 @@ runner.runCapture = (command) => { }; registry.updateSandbox = () => true; -process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-router-secret"; +process.env.NVIDIA_API_KEY = "nvapi-router-secret"; const { setupInference, getSandboxInferenceConfig } = require(${onboardPath}); @@ -173,7 +173,7 @@ const { setupInference, getSandboxInferenceConfig } = require(${onboardPath}); "nvidia-routed", "nvidia-router", "http://host.openshell.internal:" + routerPort + "/v1", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); console.log(JSON.stringify({ commands, @@ -207,13 +207,13 @@ const { setupInference, getSandboxInferenceConfig } = require(${onboardPath}); ); assert.ok(providerCommand, JSON.stringify(payload.commands)); assert.match(providerCommand.command, /--name nvidia-router/); - assert.match(providerCommand.command, /--credential NVIDIA_INFERENCE_API_KEY/); + assert.match(providerCommand.command, /--credential NVIDIA_API_KEY/); assert.match( providerCommand.command, new RegExp(`OPENAI_BASE_URL=http:\\/\\/host\\.openshell\\.internal:${routerPort}\\/v1`), ); assert.doesNotMatch(providerCommand.command, /nvapi-router-secret/); - assert.equal(providerCommand.env?.NVIDIA_INFERENCE_API_KEY, "nvapi-router-secret"); + assert.equal(providerCommand.env?.NVIDIA_API_KEY, "nvapi-router-secret"); const inferenceCommand = payload.commands.find((entry) => /inference set/.test(entry.command), @@ -409,7 +409,7 @@ runner.runCapture = (command) => { }; registry.updateSandbox = () => true; -process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-router-secret"; +process.env.NVIDIA_API_KEY = "nvapi-router-secret"; const { setupInference } = require(${onboardPath}); @@ -419,7 +419,7 @@ const { setupInference } = require(${onboardPath}); "nvidia-routed", "nvidia-router", "http://host.openshell.internal:" + routerPort + "/v1", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); console.log(JSON.stringify({ commands })); })().catch((error) => { @@ -599,7 +599,7 @@ runner.runCapture = (command) => { }; registry.updateSandbox = () => true; -process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-router-secret"; +process.env.NVIDIA_API_KEY = "nvapi-router-secret"; const { setupInference } = require(${onboardPath}); @@ -609,7 +609,7 @@ const { setupInference } = require(${onboardPath}); "nvidia-routed", "nvidia-router", "http://host.openshell.internal:" + routerPort + "/v1", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); console.log(JSON.stringify({ commands })); })().catch((error) => { @@ -825,7 +825,7 @@ runner.runCapture = (command) => { }; registry.updateSandbox = () => true; -process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-router-secret"; +process.env.NVIDIA_API_KEY = "nvapi-router-secret"; const { setupInference } = require(${onboardPath}); @@ -835,7 +835,7 @@ const { setupInference } = require(${onboardPath}); "nvidia-routed", "nvidia-router", "http://host.openshell.internal:" + routerPort + "/v1", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); console.log(JSON.stringify({ commands })); })().catch((error) => { @@ -1030,7 +1030,7 @@ runner.runCapture = (command) => { }; registry.updateSandbox = () => true; -process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-router-secret"; +process.env.NVIDIA_API_KEY = "nvapi-router-secret"; const { setupInference } = require(${onboardPath}); @@ -1040,7 +1040,7 @@ const { setupInference } = require(${onboardPath}); "nvidia-routed", "nvidia-router", "http://host.openshell.internal:" + routerPort + "/v1", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); const fpPath = path.join(${JSON.stringify(venvDir)}, ${JSON.stringify(MODEL_ROUTER_FINGERPRINT_FILE)}); const fpExists = fs.existsSync(fpPath); diff --git a/test/onboard-selection-vllm.test.ts b/test/onboard-selection-vllm.test.ts index 91837942b64..51ea68c2734 100644 --- a/test/onboard-selection-vllm.test.ts +++ b/test/onboard-selection-vllm.test.ts @@ -399,7 +399,7 @@ process.env.NEMOCLAW_PROVIDER = ""; process.env.NEMOCLAW_MODEL = ""; credentials.ensureApiKey = async () => { - process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-good"; + process.env.NVIDIA_API_KEY = "nvapi-good"; }; runner.runCapture = (command) => { const cmd = Array.isArray(command) ? command.join(" ") : command; @@ -423,7 +423,6 @@ async function runScenario(scenario) { }; process.env.NEMOCLAW_PROVIDER = ""; process.env.NEMOCLAW_MODEL = ""; - process.env.NVIDIA_INFERENCE_API_KEY = ""; process.env.NVIDIA_API_KEY = ""; delete require.cache[require.resolve(${onboardPath})]; const { setupNim } = require(${onboardPath}); diff --git a/test/onboard-selection.test.ts b/test/onboard-selection.test.ts index 8b422643c22..f23fd1ff4ce 100644 --- a/test/onboard-selection.test.ts +++ b/test/onboard-selection.test.ts @@ -183,7 +183,7 @@ const clearCredentialEnv = [ "COMPATIBLE_API_KEY", "COMPATIBLE_ANTHROPIC_API_KEY", "NOUS_API_KEY", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", "NGC_API_KEY", "NEMOCLAW_PROVIDER_KEY", ]; @@ -560,7 +560,7 @@ credentials.prompt = async (message) => { messages.push(message); return answers.shift() || ""; }; -credentials.ensureApiKey = async () => { process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-test"; }; +credentials.ensureApiKey = async () => { process.env.NVIDIA_API_KEY = "nvapi-test"; }; runner.runCapture = (command) => { const cmd = Array.isArray(command) ? command.join(" ") : command; if (cmd.includes("command -v ollama")) return ""; @@ -663,7 +663,7 @@ credentials.prompt = async (message) => { messages.push(message); return answers.shift() || ""; }; -credentials.ensureApiKey = async () => { process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-test"; }; +credentials.ensureApiKey = async () => { process.env.NVIDIA_API_KEY = "nvapi-test"; }; runner.runCapture = (command) => { // Normalize: onboard.ts still sends strings, local-inference.ts sends arrays. // Once onboard.ts is migrated to argv (#1889), these mocks can assert Array.isArray. @@ -761,7 +761,7 @@ credentials.prompt = async (message) => { messages.push(message); return answers.shift() || ""; }; -credentials.ensureApiKey = async () => { process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-test"; }; +credentials.ensureApiKey = async () => { process.env.NVIDIA_API_KEY = "nvapi-test"; }; runner.runCapture = (command) => { // Normalize: onboard.ts still sends strings, local-inference.ts sends arrays. // Once onboard.ts is migrated to argv (#1889), these mocks can assert Array.isArray. @@ -1986,7 +1986,7 @@ credentials.prompt = async (message) => { messages.push(message); return answers.shift() || ""; }; -credentials.ensureApiKey = async () => { process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-good"; }; +credentials.ensureApiKey = async () => { process.env.NVIDIA_API_KEY = "nvapi-good"; }; runner.run = () => ({ status: 0 }); runner.runCapture = (command) => { // Normalize: onboard.ts still sends strings, local-inference.ts sends arrays. @@ -3471,7 +3471,7 @@ credentials.prompt = async (message) => { messages.push(message); return answers.shift() || ""; }; -credentials.ensureApiKey = async () => { process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-good"; }; +credentials.ensureApiKey = async () => { process.env.NVIDIA_API_KEY = "nvapi-good"; }; runner.runCapture = () => ""; const { setupNim } = require(${onboardPath}); @@ -3543,7 +3543,7 @@ const clearCredentialEnv = [ "COMPATIBLE_API_KEY", "COMPATIBLE_ANTHROPIC_API_KEY", "NOUS_API_KEY", - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", "NGC_API_KEY", "NEMOCLAW_PROVIDER_KEY", ]; @@ -3678,7 +3678,7 @@ const { setupNim } = require(${onboardPath}); name: "Model Router", answers: ["back", ""], menuSelections: ["Model Router", "NVIDIA Endpoints"], - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", promptPattern: /Model Router API key: /, }, { @@ -3759,7 +3759,7 @@ credentials.prompt = async (message) => { messages.push(message); return answers.shift() || ""; }; -credentials.ensureApiKey = async () => { process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-good"; }; +credentials.ensureApiKey = async () => { process.env.NVIDIA_API_KEY = "nvapi-good"; }; runner.runCapture = () => ""; const { setupNim } = require(${onboardPath}); @@ -3873,7 +3873,7 @@ credentials.prompt = async (message) => { messages.push(message); return answers.shift() || ""; }; -credentials.ensureApiKey = async () => { process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-good"; }; +credentials.ensureApiKey = async () => { process.env.NVIDIA_API_KEY = "nvapi-good"; }; runner.runCapture = () => ""; const { setupNim } = require(${onboardPath}); @@ -3923,7 +3923,7 @@ const { setupNim } = require(${onboardPath}); assert.equal(payload.messages.filter((message: string) => /Choose \[/.test(message)).length, 2); }); - it("fails early in non-interactive mode when explicit cloud provider key is not nvapi-", () => { + it("fails early in non-interactive mode when NVIDIA_API_KEY is not an nvapi- key", () => { const repoRoot = path.join(import.meta.dirname, ".."); const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-onboard-build-noninteractive-")); const fakeBin = path.join(tmpDir, "bin"); @@ -3964,7 +3964,7 @@ onboardModule._compile(injected, onboardFile); const { setupNim, __setNonInteractive } = onboardModule.exports; (async () => { - process.env.NVIDIA_INFERENCE_API_KEY = "sk-test"; process.env.NEMOCLAW_PROVIDER = "cloud"; + process.env.NVIDIA_API_KEY = "sk-test"; __setNonInteractive(true); const originalLog = console.log; const originalError = console.error; @@ -4029,7 +4029,7 @@ const { setupNim, __setNonInteractive } = onboardModule.exports; ); }); - it("fails early in non-interactive mode with copy-paste recovery hints when no NVIDIA_INFERENCE_API_KEY is set", () => { + it("fails early in non-interactive mode with copy-paste recovery hints when no NVIDIA_API_KEY is set", () => { const repoRoot = path.join(import.meta.dirname, ".."); const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-onboard-build-missingkey-")); const fakeBin = path.join(tmpDir, "bin"); @@ -4076,7 +4076,7 @@ onboardModule._compile(injected, onboardFile); const { setupNim, __setNonInteractive } = onboardModule.exports; (async () => { - delete process.env.NVIDIA_INFERENCE_API_KEY; + delete process.env.NVIDIA_API_KEY; delete process.env.NEMOCLAW_PROVIDER_KEY; __setNonInteractive(true); const originalLog = console.log; @@ -4122,7 +4122,7 @@ const { setupNim, __setNonInteractive } = onboardModule.exports; ...process.env, HOME: tmpDir, PATH: `${fakeBin}:${process.env.PATH || ""}`, - NVIDIA_INFERENCE_API_KEY: "", + NVIDIA_API_KEY: "", NEMOCLAW_PROVIDER_KEY: "", }, }); @@ -4135,7 +4135,7 @@ const { setupNim, __setNonInteractive } = onboardModule.exports; assert.ok( payload.lines.some((line: string) => line.includes( - "NVIDIA_INFERENCE_API_KEY (or NEMOCLAW_PROVIDER_KEY) is required for NVIDIA Endpoints in non-interactive mode.", + "NVIDIA_API_KEY (or NEMOCLAW_PROVIDER_KEY) is required for NVIDIA Endpoints in non-interactive mode.", ), ), ); @@ -4143,7 +4143,7 @@ const { setupNim, __setNonInteractive } = onboardModule.exports; assert.ok(setWithIndex >= 0, "expected a standalone 'Set with:' line"); assert.equal( payload.lines[setWithIndex + 1].trim(), - "export NVIDIA_INFERENCE_API_KEY=nvapi-...", + "export NVIDIA_API_KEY=nvapi-...", "expected the export command on its own line so it can be copy-pasted", ); assert.ok( @@ -4216,7 +4216,7 @@ runner.runCapture = () => ""; const { setupNim } = require(${onboardPath}); (async () => { - process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-bad"; + process.env.NVIDIA_API_KEY = "nvapi-bad"; const originalLog = console.log; const originalError = console.error; const lines = []; @@ -4224,7 +4224,7 @@ const { setupNim } = require(${onboardPath}); console.error = (...args) => lines.push(args.join(" ")); try { const result = await setupNim(null); - originalLog(JSON.stringify({ result, messages, prompts, lines, key: process.env.NVIDIA_INFERENCE_API_KEY })); + originalLog(JSON.stringify({ result, messages, prompts, lines, key: process.env.NVIDIA_API_KEY })); } finally { console.log = originalLog; console.error = originalError; @@ -4302,7 +4302,7 @@ runner.runCapture = () => ""; const { setupNim } = require(${onboardPath}); (async () => { - process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-bad"; + process.env.NVIDIA_API_KEY = "nvapi-bad"; const originalLog = console.log; const originalError = console.error; const lines = []; @@ -4310,7 +4310,7 @@ const { setupNim } = require(${onboardPath}); console.error = (...args) => lines.push(args.join(" ")); try { const result = await setupNim(null); - originalLog(JSON.stringify({ result, messages, lines, key: process.env.NVIDIA_INFERENCE_API_KEY })); + originalLog(JSON.stringify({ result, messages, lines, key: process.env.NVIDIA_API_KEY })); } finally { console.log = originalLog; console.error = originalError; diff --git a/test/onboard.test.ts b/test/onboard.test.ts index f42d487329c..eb82f5f7913 100644 --- a/test/onboard.test.ts +++ b/test/onboard.test.ts @@ -741,13 +741,13 @@ runner.runCapture = (command) => { }; registry.updateSandbox = () => true; -process.env.NVIDIA_INFERENCE_API_KEY = "nvapi-secret-value"; +process.env.NVIDIA_API_KEY = "nvapi-secret-value"; const { setupInference } = require(${onboardPath}); (async () => { await setupInference("test-box", "nvidia/nemotron-3-super-120b-a12b", "nvidia-nim"); - console.log(JSON.stringify({ commands, nvidiaApiKey: process.env.NVIDIA_INFERENCE_API_KEY || null })); + console.log(JSON.stringify({ commands, nvidiaApiKey: process.env.NVIDIA_API_KEY || null })); })().catch((error) => { console.error(error); process.exit(1); @@ -773,7 +773,7 @@ const { setupInference } = require(${onboardPath}); assert.equal(commands.length, 4); assert.match(commands[0].command, /gateway select nemoclaw/); assert.match(commands[1].command, /provider get/); - assert.match(commands[2].command, /--credential NVIDIA_INFERENCE_API_KEY/); + assert.match(commands[2].command, /--credential NVIDIA_API_KEY/); assert.doesNotMatch(commands[2].command, /nvapi-secret-value/); assert.match(commands[2].command, /provider update/); assert.match(commands[3].command, /inference set/); @@ -2550,7 +2550,7 @@ const { createSandbox } = require(${onboardPath}); assert.match(createCommand.command, /nemoclaw-start/); assert.doesNotMatch(createCommand.command, /--upload/); assert.doesNotMatch(createCommand.command, /OPENCLAW_CONFIG_PATH/); - assert.doesNotMatch(createCommand.command, /NVIDIA_INFERENCE_API_KEY=/); + assert.doesNotMatch(createCommand.command, /NVIDIA_API_KEY=/); assert.doesNotMatch(createCommand.command, /DISCORD_BOT_TOKEN=/); assert.doesNotMatch(createCommand.command, /SLACK_BOT_TOKEN=/); assert.ok( diff --git a/test/rebuild-credential-hydration.test.ts b/test/rebuild-credential-hydration.test.ts index 7c8d05391f5..bb552e93fd2 100644 --- a/test/rebuild-credential-hydration.test.ts +++ b/test/rebuild-credential-hydration.test.ts @@ -108,16 +108,7 @@ process.stdout.write(JSON.stringify(payload)); describe("Issue #2273 Layer 1: credential hydration from legacy storage", () => { // Test each provider's credential env to ensure parametric coverage const providers = [ - { - name: "NVIDIA Endpoints", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", - value: "nvapi-test-hydrate", - }, - { - name: "NVIDIA Endpoints legacy alias", - credentialEnv: "NVIDIA_API_KEY", - value: "nvapi-test-hydrate", - }, + { name: "NVIDIA Endpoints", credentialEnv: "NVIDIA_API_KEY", value: "nvapi-test-hydrate" }, { name: "OpenAI", credentialEnv: "OPENAI_API_KEY", value: "sk-test-hydrate" }, { name: "Anthropic", credentialEnv: "ANTHROPIC_API_KEY", value: "sk-ant-test-hydrate" }, { name: "Google Gemini", credentialEnv: "GEMINI_API_KEY", value: "gemini-test-hydrate" }, diff --git a/test/rebuild-credential-preflight.test.ts b/test/rebuild-credential-preflight.test.ts index e5f97dbfecb..fff0e1c9c4c 100644 --- a/test/rebuild-credential-preflight.test.ts +++ b/test/rebuild-credential-preflight.test.ts @@ -84,7 +84,7 @@ function createFixture(opts: { const { sandboxName = "my-assistant", provider = "nvidia-prod", - credentialEnv = "NVIDIA_INFERENCE_API_KEY", + credentialEnv = "NVIDIA_API_KEY", savedCredential, providerSelectionStatus = "complete", agent = null, @@ -340,7 +340,7 @@ describe("Issue #2273: atomic rebuild", () => { // No credential in env or credentials.json AND no gateway-registered // provider — preflight must still abort so the sandbox is preserved. const f = createFixture({ - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", providerRegistered: false, // no savedCredential }); @@ -350,7 +350,7 @@ describe("Issue #2273: atomic rebuild", () => { // Should mention preflight failure expect(output).toContain("preflight failed"); - expect(output).toContain("NVIDIA_INFERENCE_API_KEY"); + expect(output).toContain("NVIDIA_API_KEY"); // Should say sandbox is untouched expect(output).toContain("untouched"); // Sandbox should still be in the registry (not destroyed) @@ -362,9 +362,9 @@ describe("Issue #2273: atomic rebuild", () => { }, () => { // Credential saved in credentials.json but NOT in process.env const f = createFixture({ - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", savedCredential: { - key: "NVIDIA_INFERENCE_API_KEY", + key: "NVIDIA_API_KEY", value: "nvapi-test-key-for-rebuild", }, }); @@ -384,9 +384,9 @@ describe("Issue #2273: atomic rebuild", () => { const f = createFixture({ agent: "hermes", messagingPlanChannels: ["discord"], - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", savedCredential: { - key: "NVIDIA_INFERENCE_API_KEY", + key: "NVIDIA_API_KEY", value: "nvapi-test-key-for-rebuild", }, }); @@ -409,9 +409,9 @@ describe("Issue #2273: atomic rebuild", () => { }, () => { const f = createFixture({ agent: "hermes", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", savedCredential: { - key: "NVIDIA_INFERENCE_API_KEY", + key: "NVIDIA_API_KEY", value: "nvapi-test-key-for-rebuild", }, dockerBuildExitCode: 23, @@ -541,24 +541,24 @@ describe("Issue #2273: atomic rebuild", () => { expect(output).toContain("Backing up sandbox state"); }); - it("uses the registered nvidia-prod provider in OpenShell instead of requiring NVIDIA_INFERENCE_API_KEY", { + it("uses the registered nvidia-prod provider in OpenShell instead of requiring NVIDIA_API_KEY", { timeout: 60_000, }, () => { // After `nemohermes channels add wechat` the rebuild preflight used to - // abort because NVIDIA_INFERENCE_API_KEY was not set in the environment, even + // abort because NVIDIA_API_KEY was not set in the environment, even // though `nvidia-prod` was already registered in the OpenShell // gateway. Reuse the gateway-stored credential instead. const f = createFixture({ provider: "nvidia-prod", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", providerRegistered: true, - // no savedCredential — host env has no NVIDIA_INFERENCE_API_KEY + // no savedCredential — host env has no NVIDIA_API_KEY }); const result = runRebuild(f); const output = (result.stderr || "") + (result.stdout || ""); - expect(output).not.toContain("Missing credential: NVIDIA_INFERENCE_API_KEY"); + expect(output).not.toContain("Missing credential: NVIDIA_API_KEY"); expect(output).not.toContain("provider credential not found"); expect(output).toContain("Backing up sandbox state"); }); @@ -571,7 +571,7 @@ describe("Issue #2273: atomic rebuild", () => { // empty, the preflight must still bail so the sandbox is preserved. const f = createFixture({ provider: "nvidia-prod", - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", providerRegistered: false, }); @@ -580,7 +580,7 @@ describe("Issue #2273: atomic rebuild", () => { expect(result.status).not.toBe(0); expect(output).toContain("preflight failed"); - expect(output).toContain("NVIDIA_INFERENCE_API_KEY"); + expect(output).toContain("NVIDIA_API_KEY"); expect(output).toContain("untouched"); expect(registryHasSandbox(f)).toBe(true); }); @@ -617,9 +617,9 @@ describe("Issue #2273: atomic rebuild", () => { // The key thing: rebuild should catch the failure and print // recovery instructions instead of silently exiting. const f = createFixture({ - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", savedCredential: { - key: "NVIDIA_INFERENCE_API_KEY", + key: "NVIDIA_API_KEY", value: "nvapi-test-key-for-rebuild", }, // Force provider_selection to re-run (not resume) so onboard @@ -649,7 +649,7 @@ describe("Issue #2273: atomic rebuild", () => { // observable CLI behavior — the preflight check fails and bail() // calls process.exit with a non-zero code. const f = createFixture({ - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", providerRegistered: false, // No credential — preflight will fail and exit non-zero }); diff --git a/test/rebuild-shields-auto-unlock.test.ts b/test/rebuild-shields-auto-unlock.test.ts index cb510657aae..13d68ec242d 100644 --- a/test/rebuild-shields-auto-unlock.test.ts +++ b/test/rebuild-shields-auto-unlock.test.ts @@ -98,7 +98,7 @@ function createFixture(opts: { shieldsLocked: boolean }) { fs.writeFileSync( path.join(nemoclawDir, "credentials.json"), - JSON.stringify({ NVIDIA_INFERENCE_API_KEY: "nvapi-test" }), + JSON.stringify({ NVIDIA_API_KEY: "nvapi-test" }), { mode: 0o600 }, ); @@ -120,7 +120,7 @@ function createFixture(opts: { shieldsLocked: boolean }) { provider: "nvidia-prod", model: "meta/llama-3.3-70b-instruct", endpointUrl: null, - credentialEnv: "NVIDIA_INFERENCE_API_KEY", + credentialEnv: "NVIDIA_API_KEY", preferredInferenceApi: null, nimContainer: null, webSearchConfig: null, diff --git a/test/rebuild-stale-recovery.test.ts b/test/rebuild-stale-recovery.test.ts index 945d6528dbf..0de4bbed974 100644 --- a/test/rebuild-stale-recovery.test.ts +++ b/test/rebuild-stale-recovery.test.ts @@ -62,7 +62,7 @@ function createStaleFixture( } = opts; const sandboxName = "my-assistant"; const provider = "nvidia-prod"; - const credentialEnv = "NVIDIA_INFERENCE_API_KEY"; + const credentialEnv = "NVIDIA_API_KEY"; const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-4497-")); tmpFixtures.push(tmpDir); diff --git a/test/regression-e2e-workflow.test.ts b/test/regression-e2e-workflow.test.ts index 87b8233402b..2019378cfbd 100644 --- a/test/regression-e2e-workflow.test.ts +++ b/test/regression-e2e-workflow.test.ts @@ -81,10 +81,7 @@ describe("Regression E2E workflow contract", () => { expect(setupNodeStep?.uses).toMatch(FULL_SHA_ACTION); expect(runVitestStep?.env?.NEMOCLAW_RUN_E2E_SCENARIOS).toBe("1"); for (const step of steps) { - expect( - step.env?.NVIDIA_INFERENCE_API_KEY, - step.name ?? step.uses ?? "", - ).toBeUndefined(); + expect(step.env?.NVIDIA_API_KEY, step.name ?? step.uses ?? "").toBeUndefined(); } expect(runText).toContain("test/e2e-scenario/live/openclaw-plugin-runtime-exdev.test.ts"); diff --git a/test/runner.test.ts b/test/runner.test.ts index 0c6888594ed..3d699e2e304 100644 --- a/test/runner.test.ts +++ b/test/runner.test.ts @@ -366,10 +366,8 @@ describe("redact", () => { it("masks key assignments in commands", () => { const { redact } = require(runnerPath); - expect(redact("export NVIDIA_INFERENCE_API_KEY=nvapi-realkey12345")).toContain("nvap"); - expect(redact("export NVIDIA_INFERENCE_API_KEY=nvapi-realkey12345")).not.toContain( - "realkey12345", - ); + expect(redact("export NVIDIA_API_KEY=nvapi-realkey12345")).toContain("nvap"); + expect(redact("export NVIDIA_API_KEY=nvapi-realkey12345")).not.toContain("realkey12345"); }); it("masks variables ending in _KEY", () => { @@ -634,7 +632,7 @@ describe("regression guards", () => { }); describe("credential exposure guards (#429)", () => { - it("walkthrough.sh does not embed NVIDIA_INFERENCE_API_KEY in tmux or sandbox commands", () => { + it("walkthrough.sh does not embed NVIDIA_API_KEY in tmux or sandbox commands", () => { const fs = require("fs"); const src = fs.readFileSync( path.join(import.meta.dirname, "..", "scripts", "walkthrough.sh"), @@ -650,7 +648,7 @@ describe("regression guards", () => { (l.includes("tmux") || l.includes("openshell sandbox connect")), ); for (const line of cmdLines) { - expect(line.includes("NVIDIA_INFERENCE_API_KEY")).toBe(false); + expect(line.includes("NVIDIA_API_KEY")).toBe(false); } }); diff --git a/test/secret-redaction.test.ts b/test/secret-redaction.test.ts index 775fd1f3555..54994db83f1 100644 --- a/test/secret-redaction.test.ts +++ b/test/secret-redaction.test.ts @@ -60,7 +60,7 @@ describe("secret redaction consistency (#1736)", () => { describe("redactor consistency (#2381)", () => { it("runner and debug redactors both mask shared token patterns", () => { - const text = "provider failed with NVIDIA_INFERENCE_API_KEY=nvapi-" + "a".repeat(30); + const text = "provider failed with NVIDIA_API_KEY=nvapi-" + "a".repeat(30); expect(runnerRedact(text)).not.toContain("nvapi-"); expect(debugRedact(text)).not.toContain("nvapi-"); }); @@ -73,7 +73,7 @@ describe("secret redaction consistency (#1736)", () => { mkdirSync(fakeBin); writeFileSync( join(fakeBin, "date"), - "#!/bin/sh\necho NVIDIA_INFERENCE_API_KEY=nvapi-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n", + "#!/bin/sh\necho NVIDIA_API_KEY=nvapi-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n", { mode: 0o755 }, ); try { @@ -92,7 +92,7 @@ describe("secret redaction consistency (#1736)", () => { }, ); expect(result.status).toBe(0); - expect(result.stdout).toContain("NVIDIA_INFERENCE_API_KEY="); + expect(result.stdout).toContain("NVIDIA_API_KEY="); expect(result.stdout).not.toContain("nvapi-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); } finally { rmSync(tmp, { recursive: true, force: true }); diff --git a/test/smoke-macos-install.test.ts b/test/smoke-macos-install.test.ts index 0a38a9ff295..0236c08055e 100644 --- a/test/smoke-macos-install.test.ts +++ b/test/smoke-macos-install.test.ts @@ -18,22 +18,22 @@ describe.skip("macOS smoke install script guardrails", () => { expect(result.stdout).toMatch(/Usage: \.\/scripts\/smoke-macos-install\.sh/); }); - it("requires NVIDIA_INFERENCE_API_KEY", () => { + it("requires NVIDIA_API_KEY", () => { const result = spawnSync("bash", [SMOKE_SCRIPT], { cwd: path.join(import.meta.dirname, ".."), encoding: "utf-8", - env: { ...process.env, NVIDIA_INFERENCE_API_KEY: "" }, + env: { ...process.env, NVIDIA_API_KEY: "" }, }); expect(result.status).not.toBe(0); - expect(`${result.stdout}${result.stderr}`).toMatch(/NVIDIA_INFERENCE_API_KEY must be set/); + expect(`${result.stdout}${result.stderr}`).toMatch(/NVIDIA_API_KEY must be set/); }); it("rejects invalid sandbox names", () => { const result = spawnSync("bash", [SMOKE_SCRIPT, "--sandbox-name", "Bad Name"], { cwd: path.join(import.meta.dirname, ".."), encoding: "utf-8", - env: { ...process.env, NVIDIA_INFERENCE_API_KEY: "nvapi-test" }, + env: { ...process.env, NVIDIA_API_KEY: "nvapi-test" }, }); expect(result.status).not.toBe(0); @@ -44,7 +44,7 @@ describe.skip("macOS smoke install script guardrails", () => { const result = spawnSync("bash", [SMOKE_SCRIPT, "--runtime", "lxc"], { cwd: path.join(import.meta.dirname, ".."), encoding: "utf-8", - env: { ...process.env, NVIDIA_INFERENCE_API_KEY: "nvapi-test" }, + env: { ...process.env, NVIDIA_API_KEY: "nvapi-test" }, }); expect(result.status).not.toBe(0); @@ -57,7 +57,7 @@ describe.skip("macOS smoke install script guardrails", () => { encoding: "utf-8", env: { ...process.env, - NVIDIA_INFERENCE_API_KEY: "nvapi-test", + NVIDIA_API_KEY: "nvapi-test", HOME: "/tmp/nemoclaw-smoke-no-runtime", }, }); @@ -72,7 +72,7 @@ describe.skip("macOS smoke install script guardrails", () => { encoding: "utf-8", env: { ...process.env, - NVIDIA_INFERENCE_API_KEY: "nvapi-test", + NVIDIA_API_KEY: "nvapi-test", HOME: "/tmp/nemoclaw-smoke-no-runtime", }, }); @@ -105,7 +105,7 @@ describe.skip("macOS smoke install script guardrails", () => { const result = spawnSync("bash", ["--noprofile", "--norc", "-c", script], { cwd: path.join(import.meta.dirname, ".."), encoding: "utf-8", - env: { ...process.env, NVIDIA_INFERENCE_API_KEY: "nvapi-test" }, + env: { ...process.env, NVIDIA_API_KEY: "nvapi-test" }, timeout: 10_000, }); diff --git a/test/validate-blueprint.test.ts b/test/validate-blueprint.test.ts index 76fbad0e1e2..d2b94405ffc 100644 --- a/test/validate-blueprint.test.ts +++ b/test/validate-blueprint.test.ts @@ -205,7 +205,7 @@ describe("blueprint.yaml", () => { describe("Model Router pool config", () => { const pool = loadYaml(ROUTER_POOL_CONFIG_PATH); - it("regression #3255: routes NVIDIA API keys to the public NVIDIA inference endpoint", () => { + it("regression #3255: routes NVIDIA API keys to the public NVIDIA Build endpoint", () => { const apiBases = new Set((pool.models ?? []).map((model) => model.api_base)); expect(apiBases).toEqual(new Set(["https://integrate.api.nvidia.com/v1"])); }); @@ -280,17 +280,18 @@ describe("base sandbox policy", () => { expect(violations).toEqual([]); }); - it("allows NVIDIA embeddings on the NVIDIA inference host", () => { + it("allows NVIDIA embeddings on both NVIDIA inference hosts", () => { const np = policy.network_policies ?? {}; const endpoints = np.nvidia?.endpoints; const missingHosts: string[] = []; - const host = "integrate.api.nvidia.com"; - const endpoint = endpoints?.find((entry) => entry.host === host); - const hasEmbeddingsRule = endpoint?.rules?.some( - (rule) => rule.allow?.method === "POST" && rule.allow?.path === "/v1/embeddings", - ); - if (!hasEmbeddingsRule) { - missingHosts.push(host); + for (const host of ["integrate.api.nvidia.com", "inference-api.nvidia.com"]) { + const endpoint = endpoints?.find((entry) => entry.host === host); + const hasEmbeddingsRule = endpoint?.rules?.some( + (rule) => rule.allow?.method === "POST" && rule.allow?.path === "/v1/embeddings", + ); + if (!hasEmbeddingsRule) { + missingHosts.push(host); + } } expect(missingHosts).toEqual([]); }); diff --git a/tools/e2e-scenarios/workflow-boundary.mts b/tools/e2e-scenarios/workflow-boundary.mts index 1afd0be5d25..69456dabd48 100644 --- a/tools/e2e-scenarios/workflow-boundary.mts +++ b/tools/e2e-scenarios/workflow-boundary.mts @@ -482,12 +482,7 @@ function validateOpenShellVersionPinVitestJob(errors: string[], jobs: WorkflowRe "openshell-version-pin-vitest job must write artifacts under e2e-artifacts/vitest/openshell-version-pin", ); } - requireEnvDoesNotExposeSecret( - errors, - "openshell-version-pin-vitest job", - jobEnv, - "NVIDIA_INFERENCE_API_KEY", - ); + requireEnvDoesNotExposeSecret(errors, "openshell-version-pin-vitest job", jobEnv, "NVIDIA_API_KEY"); const steps = asSteps(job.steps); requireNoDispatchInputInterpolation(errors, steps); @@ -496,7 +491,7 @@ function validateOpenShellVersionPinVitestJob(errors: string[], jobs: WorkflowRe errors, `openshell-version-pin-vitest step '${step.name ?? step.uses ?? ""}'`, asRecord(step.env), - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); } @@ -571,12 +566,7 @@ function validateSkillAgentVitestJob(errors: string[], jobs: WorkflowRecord): vo if (!stringValue(jobEnv.NEMOCLAW_CLI_BIN).includes("bin/nemoclaw.js")) { errors.push("skill-agent-vitest job must point NEMOCLAW_CLI_BIN at the repo CLI"); } - requireEnvDoesNotExposeSecret( - errors, - "skill-agent-vitest job", - jobEnv, - "NVIDIA_INFERENCE_API_KEY", - ); + requireEnvDoesNotExposeSecret(errors, "skill-agent-vitest job", jobEnv, "NVIDIA_API_KEY"); const steps = asSteps(job.steps); requireNoDispatchInputInterpolation(errors, steps); @@ -586,7 +576,7 @@ function validateSkillAgentVitestJob(errors: string[], jobs: WorkflowRecord): vo errors, `skill-agent-vitest step '${step.name ?? step.uses ?? ""}'`, asRecord(step.env), - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); } } @@ -618,8 +608,8 @@ function validateSkillAgentVitestJob(errors: string[], jobs: WorkflowRecord): vo const runVitest = requireJobStep(errors, jobName, steps, "Run skill-agent live test"); const runEnv = asRecord(runVitest?.env); - if (runEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { - errors.push("skill-agent-vitest run step must receive NVIDIA_INFERENCE_API_KEY from secrets"); + if (runEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + errors.push("skill-agent-vitest run step must receive NVIDIA_API_KEY from secrets"); } requireRunContains( errors, @@ -702,12 +692,7 @@ function validateNetworkPolicyVitestJob(errors: string[], jobs: WorkflowRecord): if (jobEnv.OPENSHELL_GATEWAY !== "nemoclaw") { errors.push("network-policy-vitest job must force OPENSHELL_GATEWAY=nemoclaw"); } - for (const secret of [ - "NVIDIA_INFERENCE_API_KEY", - "DOCKERHUB_USERNAME", - "DOCKERHUB_TOKEN", - "GITHUB_TOKEN", - ]) { + for (const secret of ["NVIDIA_API_KEY", "DOCKERHUB_USERNAME", "DOCKERHUB_TOKEN", "GITHUB_TOKEN"]) { requireEnvDoesNotExposeSecret(errors, "network-policy-vitest job", jobEnv, secret); } @@ -721,7 +706,7 @@ function validateNetworkPolicyVitestJob(errors: string[], jobs: WorkflowRecord): errors, `network-policy-vitest step '${stepName}'`, stepEnv, - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); } if (step.name !== "Authenticate to Docker Hub") { @@ -777,15 +762,13 @@ function validateNetworkPolicyVitestJob(errors: string[], jobs: WorkflowRecord): requireRunContains(errors, installOpenShell, "env -u DOCKER_CONFIG"); 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(errors, jobName, steps, "Run network-policy live test"); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { - errors.push( - "network-policy-vitest Vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets", - ); + if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + errors.push("network-policy-vitest Vitest step must receive NVIDIA_API_KEY from secrets"); } requireRunContains(errors, runVitest, "npx vitest run --project e2e-scenarios-live"); requireRunContains(errors, runVitest, "test/e2e-scenario/live/network-policy.test.ts"); @@ -977,12 +960,7 @@ function validateShieldsConfigVitestJob(errors: string[], jobs: WorkflowRecord): if (jobEnv.NEMOCLAW_SANDBOX_NAME !== "e2e-shields") { errors.push("shields-config-vitest job must set NEMOCLAW_SANDBOX_NAME=e2e-shields"); } - requireEnvDoesNotExposeSecret( - errors, - "shields-config-vitest job", - jobEnv, - "NVIDIA_INFERENCE_API_KEY", - ); + requireEnvDoesNotExposeSecret(errors, "shields-config-vitest job", jobEnv, "NVIDIA_API_KEY"); requireEnvDoesNotExposeSecret(errors, "shields-config-vitest job", jobEnv, "DOCKERHUB_USERNAME"); requireEnvDoesNotExposeSecret(errors, "shields-config-vitest job", jobEnv, "DOCKERHUB_TOKEN"); @@ -996,7 +974,7 @@ function validateShieldsConfigVitestJob(errors: string[], jobs: WorkflowRecord): errors, `shields-config-vitest step '${stepName}'`, stepEnv, - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); } if (step.name !== "Authenticate to Docker Hub") { @@ -1048,8 +1026,8 @@ function validateShieldsConfigVitestJob(errors: string[], jobs: WorkflowRecord): const runVitest = requireJobStep(errors, jobName, steps, "Run shields-config live test"); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { - errors.push("shields-config-vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets"); + if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + errors.push("shields-config-vitest step must receive NVIDIA_API_KEY from secrets"); } requireRunContains(errors, runVitest, "npx vitest run --project e2e-scenarios-live"); requireRunContains(errors, runVitest, "test/e2e-scenario/live/shields-config.test.ts"); @@ -1101,12 +1079,7 @@ function validateRebuildOpenClawVitestJob(errors: string[], jobs: WorkflowRecord if (!stringValue(jobEnv.NEMOCLAW_CLI_BIN).includes("bin/nemoclaw.js")) { errors.push("rebuild-openclaw-vitest job must point NEMOCLAW_CLI_BIN at the repo CLI"); } - requireEnvDoesNotExposeSecret( - errors, - "rebuild-openclaw-vitest job", - jobEnv, - "NVIDIA_INFERENCE_API_KEY", - ); + requireEnvDoesNotExposeSecret(errors, "rebuild-openclaw-vitest job", jobEnv, "NVIDIA_API_KEY"); const steps = asSteps(job.steps); requireNoDispatchInputInterpolation(errors, steps); @@ -1116,7 +1089,7 @@ function validateRebuildOpenClawVitestJob(errors: string[], jobs: WorkflowRecord errors, `rebuild-openclaw-vitest step '${step.name ?? step.uses ?? ""}'`, asRecord(step.env), - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); } } @@ -1168,13 +1141,13 @@ function validateRebuildOpenClawVitestJob(errors: string[], jobs: WorkflowRecord requireRunContains(errors, installOpenShell, "env -u DOCKER_CONFIG"); 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(errors, jobName, steps, "Run OpenClaw rebuild live test"); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { - errors.push("rebuild-openclaw-vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets"); + if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + errors.push("rebuild-openclaw-vitest step must receive NVIDIA_API_KEY from secrets"); } requireRunContains(errors, runVitest, "OPENSHELL_BIN"); requireRunContains(errors, runVitest, "npx vitest run --project e2e-scenarios-live"); @@ -1230,12 +1203,7 @@ function validateSandboxRebuildVitestJob(errors: string[], jobs: WorkflowRecord) if (jobEnv.OPENSHELL_GATEWAY !== "nemoclaw") { errors.push("sandbox-rebuild-vitest job must force OPENSHELL_GATEWAY=nemoclaw"); } - for (const secret of [ - "NVIDIA_INFERENCE_API_KEY", - "DOCKERHUB_USERNAME", - "DOCKERHUB_TOKEN", - "GITHUB_TOKEN", - ]) { + for (const secret of ["NVIDIA_API_KEY", "DOCKERHUB_USERNAME", "DOCKERHUB_TOKEN", "GITHUB_TOKEN"]) { requireEnvDoesNotExposeSecret(errors, "sandbox-rebuild-vitest job", jobEnv, secret); } @@ -1245,7 +1213,7 @@ function validateSandboxRebuildVitestJob(errors: string[], jobs: WorkflowRecord) const stepName = `sandbox-rebuild-vitest step '${step.name ?? step.uses ?? ""}'`; const stepEnv = asRecord(step.env); if (step.name !== "Run sandbox rebuild live test") { - requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_INFERENCE_API_KEY"); + requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_API_KEY"); } if (step.name !== "Authenticate to Docker Hub") { requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "DOCKERHUB_USERNAME"); @@ -1295,13 +1263,13 @@ function validateSandboxRebuildVitestJob(errors: string[], jobs: WorkflowRecord) requireRunContains(errors, installOpenShell, "env -u DOCKER_CONFIG"); 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(errors, jobName, steps, "Run sandbox rebuild live test"); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { - errors.push("sandbox-rebuild-vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets"); + if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + errors.push("sandbox-rebuild-vitest step must receive NVIDIA_API_KEY from secrets"); } requireRunContains(errors, runVitest, "OPENSHELL_BIN"); requireRunContains(errors, runVitest, "npx vitest run --project e2e-scenarios-live"); @@ -1495,12 +1463,7 @@ function validateTokenRotationVitestJob(errors: string[], jobs: WorkflowRecord): if (!stringValue(jobEnv.NEMOCLAW_CLI_BIN).includes("bin/nemoclaw.js")) { errors.push("token-rotation-vitest job must point NEMOCLAW_CLI_BIN at the repo CLI"); } - requireEnvDoesNotExposeSecret( - errors, - "token-rotation-vitest job", - jobEnv, - "NVIDIA_INFERENCE_API_KEY", - ); + requireEnvDoesNotExposeSecret(errors, "token-rotation-vitest job", jobEnv, "NVIDIA_API_KEY"); const steps = asSteps(job.steps); requireNoDispatchInputInterpolation(errors, steps); @@ -1510,7 +1473,7 @@ function validateTokenRotationVitestJob(errors: string[], jobs: WorkflowRecord): errors, `token-rotation-vitest step '${step.name ?? step.uses ?? ""}'`, asRecord(step.env), - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); } } @@ -1555,7 +1518,7 @@ function validateTokenRotationVitestJob(errors: string[], jobs: WorkflowRecord): errors, "token-rotation-vitest step", runVitestEnv, - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); if (runVitestEnv.GITHUB_TOKEN !== "${{ github.token }}") { errors.push("token-rotation-vitest step must receive GITHUB_TOKEN from github.token"); @@ -1810,12 +1773,7 @@ function validateOnboardNegativePathsVitestJob(errors: string[], jobs: WorkflowR "onboard-negative-paths-vitest job must write artifacts under e2e-artifacts/vitest/onboard-negative-paths", ); } - requireEnvDoesNotExposeSecret( - errors, - "onboard-negative-paths-vitest job", - jobEnv, - "NVIDIA_INFERENCE_API_KEY", - ); + requireEnvDoesNotExposeSecret(errors, "onboard-negative-paths-vitest job", jobEnv, "NVIDIA_API_KEY"); const steps = asSteps(job.steps); requireNoDispatchInputInterpolation(errors, steps); @@ -1824,7 +1782,7 @@ function validateOnboardNegativePathsVitestJob(errors: string[], jobs: WorkflowR errors, `onboard-negative-paths-vitest step '${step.name ?? step.uses ?? ""}'`, asRecord(step.env), - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); } @@ -2009,12 +1967,7 @@ function validateDoubleOnboardVitestJob(errors: string[], jobs: WorkflowRecord): "double-onboard-vitest job must write artifacts under e2e-artifacts/vitest/double-onboard", ); } - requireEnvDoesNotExposeSecret( - errors, - "double-onboard-vitest job", - jobEnv, - "NVIDIA_INFERENCE_API_KEY", - ); + requireEnvDoesNotExposeSecret(errors, "double-onboard-vitest job", jobEnv, "NVIDIA_API_KEY"); requireEnvDoesNotExposeSecret(errors, "double-onboard-vitest job", jobEnv, "DOCKERHUB_TOKEN"); const steps = asSteps(job.steps); @@ -2032,7 +1985,7 @@ function validateDoubleOnboardVitestJob(errors: string[], jobs: WorkflowRecord): errors, `double-onboard-vitest step '${step.name ?? step.uses ?? ""}'`, asRecord(step.env), - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); } @@ -2121,18 +2074,8 @@ function validateRuntimeOverridesVitestJob(errors: string[], jobs: WorkflowRecor "runtime-overrides-vitest job must write artifacts under e2e-artifacts/vitest/runtime-overrides", ); } - requireEnvDoesNotExposeSecret( - errors, - "runtime-overrides-vitest job", - jobEnv, - "NVIDIA_INFERENCE_API_KEY", - ); - requireEnvDoesNotExposeSecret( - errors, - "runtime-overrides-vitest job", - jobEnv, - "DOCKERHUB_USERNAME", - ); + requireEnvDoesNotExposeSecret(errors, "runtime-overrides-vitest job", jobEnv, "NVIDIA_API_KEY"); + requireEnvDoesNotExposeSecret(errors, "runtime-overrides-vitest job", jobEnv, "DOCKERHUB_USERNAME"); requireEnvDoesNotExposeSecret(errors, "runtime-overrides-vitest job", jobEnv, "DOCKERHUB_TOKEN"); const steps = asSteps(job.steps); @@ -2140,7 +2083,7 @@ function validateRuntimeOverridesVitestJob(errors: string[], jobs: WorkflowRecor for (const step of steps) { const stepName = `runtime-overrides-vitest step '${step.name ?? step.uses ?? ""}'`; const stepEnv = asRecord(step.env); - requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_INFERENCE_API_KEY"); + requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_API_KEY"); requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "DOCKERHUB_USERNAME"); requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "DOCKERHUB_TOKEN"); requireNoDockerHubAuthInRun(errors, stepName, stringValue(step.run)); @@ -2228,12 +2171,7 @@ function validateHermesE2EVitestJob(errors: string[], jobs: WorkflowRecord): voi if (jobEnv.NEMOCLAW_ONBOARD_VALIDATION_TIMEOUT_SECONDS !== "60") { errors.push("hermes-e2e-vitest job must give hosted endpoint validation a CI-safe timeout"); } - requireEnvDoesNotExposeSecret( - errors, - "hermes-e2e-vitest job", - jobEnv, - "NVIDIA_INFERENCE_API_KEY", - ); + requireEnvDoesNotExposeSecret(errors, "hermes-e2e-vitest job", jobEnv, "NVIDIA_API_KEY"); const steps = asSteps(job.steps); requireNoDispatchInputInterpolation(errors, steps); @@ -2243,7 +2181,7 @@ function validateHermesE2EVitestJob(errors: string[], jobs: WorkflowRecord): voi errors, `hermes-e2e-vitest step '${step.name ?? step.uses ?? ""}'`, asRecord(step.env), - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); } } @@ -2272,8 +2210,8 @@ function validateHermesE2EVitestJob(errors: string[], jobs: WorkflowRecord): voi const runVitest = requireJobStep(errors, jobName, steps, "Run Hermes live Vitest test"); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { - errors.push("hermes-e2e-vitest Vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets"); + if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + errors.push("hermes-e2e-vitest Vitest step must receive NVIDIA_API_KEY from secrets"); } requireRunContains(errors, runVitest, "npx vitest run --project e2e-scenarios-live"); requireRunContains(errors, runVitest, "test/e2e-scenario/live/hermes-e2e.test.ts"); @@ -2339,7 +2277,7 @@ function validateHermesRootEntrypointSmokeVitestJob(errors: string[], jobs: Work errors, "hermes-root-entrypoint-smoke-vitest job", jobEnv, - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); requireEnvDoesNotExposeSecret( errors, @@ -2363,7 +2301,7 @@ function validateHermesRootEntrypointSmokeVitestJob(errors: string[], jobs: Work errors, `hermes-root-entrypoint-smoke-vitest step '${stepName}'`, stepEnv, - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); requireEnvDoesNotExposeSecret( errors, @@ -2503,12 +2441,7 @@ function validateModelRouterProviderRoutedInferenceVitestJob( "model-router-provider-routed-inference-vitest job must force OPENSHELL_GATEWAY=nemoclaw", ); } - for (const secret of [ - "NVIDIA_INFERENCE_API_KEY", - "DOCKERHUB_USERNAME", - "DOCKERHUB_TOKEN", - "GITHUB_TOKEN", - ]) { + for (const secret of ["NVIDIA_API_KEY", "DOCKERHUB_USERNAME", "DOCKERHUB_TOKEN", "GITHUB_TOKEN"]) { requireEnvDoesNotExposeSecret( errors, "model-router-provider-routed-inference-vitest job", @@ -2523,7 +2456,7 @@ function validateModelRouterProviderRoutedInferenceVitestJob( const stepName = `model-router-provider-routed-inference-vitest step '${step.name ?? step.uses ?? ""}'`; const stepEnv = asRecord(step.env); if (step.name !== "Run Model Router provider-routed inference live test") { - requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_INFERENCE_API_KEY"); + requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "NVIDIA_API_KEY"); } if (step.name !== "Authenticate to Docker Hub") { requireEnvDoesNotExposeSecret(errors, stepName, stepEnv, "DOCKERHUB_USERNAME"); @@ -2603,9 +2536,9 @@ function validateModelRouterProviderRoutedInferenceVitestJob( "Run Model Router provider-routed inference live test", ); const runVitestEnv = asRecord(runVitest?.env); - if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { + if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { errors.push( - "model-router-provider-routed-inference-vitest Vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets", + "model-router-provider-routed-inference-vitest Vitest step must receive NVIDIA_API_KEY from secrets", ); } requireRunContains(errors, runVitest, "npx vitest run --project e2e-scenarios-live"); @@ -3361,7 +3294,7 @@ export function validateE2eVitestScenariosWorkflowBoundary( if (!stringValue(jobEnv.NEMOCLAW_CLI_BIN).includes("bin/nemoclaw.js")) { errors.push("live-scenarios job must point NEMOCLAW_CLI_BIN at the repo CLI"); } - requireEnvDoesNotExposeSecret(errors, "live-scenarios job", jobEnv, "NVIDIA_INFERENCE_API_KEY"); + requireEnvDoesNotExposeSecret(errors, "live-scenarios job", jobEnv, "NVIDIA_API_KEY"); const steps = asSteps(liveScenarios.steps); requireNoDispatchInputInterpolation(errors, steps); @@ -3371,7 +3304,7 @@ export function validateE2eVitestScenariosWorkflowBoundary( errors, `step '${step.name ?? step.uses ?? ""}'`, asRecord(step.env), - "NVIDIA_INFERENCE_API_KEY", + "NVIDIA_API_KEY", ); } } @@ -3395,8 +3328,8 @@ export function validateE2eVitestScenariosWorkflowBoundary( if (runVitestEnv.SCENARIO_ID !== "${{ matrix.id }}") { errors.push("Vitest step must pass matrix.id through SCENARIO_ID env"); } - if (runVitestEnv.NVIDIA_INFERENCE_API_KEY !== "${{ secrets.NVIDIA_INFERENCE_API_KEY }}") { - errors.push("Vitest step must receive NVIDIA_INFERENCE_API_KEY from secrets"); + if (runVitestEnv.NVIDIA_API_KEY !== "${{ secrets.NVIDIA_API_KEY }}") { + errors.push("Vitest step must receive NVIDIA_API_KEY from secrets"); } requireRunContains(errors, runVitest, "npx vitest run --project e2e-scenarios-live"); requireRunContains(errors, runVitest, "test/e2e-scenario/live/registry-scenarios.test.ts");