Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,19 @@ CLI="${NEMOCLAW_CLI_BIN:-${REPO}/bin/nemoclaw.js}"
PREFIX="04-deepagents-code-fresh-reonboard"
PRIMARY_TARGET_MODEL="openai/openai/gpt-5.5"
FALLBACK_TARGET_MODEL="nvidia/nvidia/nemotron-3-ultra"
HOSTED_ENDPOINT="${NEMOCLAW_ENDPOINT_URL:-https://inference-api.nvidia.com/v1}"
CREDENTIAL_CANARY="nemoclaw-dcode-config-get-canary"

# shellcheck source=test/e2e/lib/hermetic-compatible-inference.sh
. "$REPO/test/e2e/lib/hermetic-compatible-inference.sh"

cleanup() {
local status=$?
nemoclaw_e2e_stop_hermetic_compatible_inference
return "$status"
}

trap cleanup EXIT

fail() {
printf '%s: FAIL: %s\n' "$PREFIX" "$1" >&2
exit 1
Expand Down Expand Up @@ -150,7 +160,6 @@ if ! sandbox_exec "test -d /sandbox/.deepagents && command -v dcode >/dev/null 2
exit 0
fi

[ -n "${COMPATIBLE_API_KEY:-}" ] || fail "COMPATIBLE_API_KEY is required"
[ -x "$CLI" ] || fail "NemoClaw CLI is not executable at $CLI"

if ! identity_before="$(dcode_identity)"; then
Expand All @@ -173,6 +182,12 @@ fi
[ "$model_a" != "$model_b" ] || fail "model A and model B must differ"
pass "initial live identity reports model A"

export NEMOCLAW_E2E_COMPATIBLE_MODEL="$model_b"
if ! nemoclaw_e2e_start_hermetic_compatible_inference; then
fail "could not start hermetic compatible inference"
fi
pass "started hermetic compatible inference for re-onboard"

seed_source="$(seed_config_source | encode_source)"
seed_command="printf '%s' ${seed_source@Q} | base64 -d | /opt/venv/bin/python3 -I - ${model_a@Q} ${CREDENTIAL_CANARY@Q}"
seed_output="$(sandbox_exec "$seed_command")" || fail "could not seed stale DCode config"
Expand Down Expand Up @@ -224,8 +239,7 @@ if ! reonboard_output="$(
NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \
NEMOCLAW_AGENT=langchain-deepagents-code \
NEMOCLAW_COMPAT_MODEL="$model_b" \
NEMOCLAW_E2E_USE_HOSTED_INFERENCE=1 \
NEMOCLAW_ENDPOINT_URL="$HOSTED_ENDPOINT" \
NEMOCLAW_ENDPOINT_URL="$NEMOCLAW_ENDPOINT_URL" \
NEMOCLAW_MODEL="$model_b" \
NEMOCLAW_NON_INTERACTIVE=1 \
NEMOCLAW_PREFERRED_API=openai-completions \
Expand All @@ -239,6 +253,7 @@ if ! reonboard_output="$(
fi
printf '%s\n' "$reonboard_output" | grep -Fq "Backing up workspace state before recreating sandbox..." || fail "re-onboard did not take the pre-recreate backup path"
printf '%s\n' "$reonboard_output" | grep -Fq "Restoring workspace state from pre-recreate backup..." || fail "re-onboard did not take the restore path"
nemoclaw_e2e_assert_hermetic_compatible_endpoint_consulted || fail "re-onboard did not consult the hermetic compatible endpoint"
pass "same-name --fresh re-onboard crossed backup and restore boundaries"

sandbox_list="$(openshell sandbox list 2>&1)" || fail "could not list sandbox after re-onboard"
Expand Down Expand Up @@ -284,4 +299,4 @@ verify_output="$(sandbox_exec "$verify_command")" || fail "live DCode config doe
printf '%s\n' "$verify_output" | grep -Fq "NEMOCLAW_DCODE_FRESH_CONFIG_VERIFIED" || fail "fresh config verification marker is missing"
pass "config keeps model B and only the allowlisted preferences"

printf '%s: 11 passed, 0 failed\n' "$PREFIX"
printf '%s: 12 passed, 0 failed\n' "$PREFIX"
24 changes: 24 additions & 0 deletions test/e2e/lib/hermetic-compatible-inference.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ nemoclaw_e2e_start_hermetic_compatible_inference() {
export FAKE_OPENAI_API_KEY="$fake_key"
export FAKE_OPENAI_REQUIRE_AUTH=1
export NEMOCLAW_FAKE_OPENAI_REQUESTS_FILE="$FAKE_OPENAI_REQUESTS_FILE"
export NEMOCLAW_FAKE_OPENAI_REQUIRE_AUTH_MODELS=1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n 'FAKE_OPENAI_REQUESTS_FILE' test/e2e --type sh --type ts
rg -n 'nemoclaw_e2e_assert_hermetic_compatible_inference_used|nemoclaw_e2e_assert_hermetic_compatible_endpoint_consulted' test/e2e/e2e-cloud-experimental/checks/04-deepagents-code-fresh-reonboard.sh -A2 -B2

Repository: NVIDIA/NemoClaw

Length of output: 1364


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## hermetic-compatible-inference.sh\n'
cat -n test/e2e/lib/hermetic-compatible-inference.sh | sed -n '1,220p'

printf '\n## openai-compatible-api-proof.sh\n'
cat -n test/e2e/lib/openai-compatible-api-proof.sh | sed -n '1,220p'

printf '\n## 04-deepagents-code-fresh-reonboard.sh relevant section\n'
cat -n test/e2e/e2e-cloud-experimental/checks/04-deepagents-code-fresh-reonboard.sh | sed -n '230,320p'

Repository: NVIDIA/NemoClaw

Length of output: 13242


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## fake-openai-compatible.ts outline\n'
ast-grep outline test/e2e/fixtures/fake-openai-compatible.ts --view expanded

printf '\n## auth/request logging references\n'
rg -n 'auth|requestsFile|REQUESTS_FILE|require_auth_models|requireAuthModels|models' test/e2e/fixtures/fake-openai-compatible.ts -n -A3 -B3

printf '\n## request log write path\n'
cat -n test/e2e/fixtures/fake-openai-compatible.ts | sed -n '1,260p'

Repository: NVIDIA/NemoClaw

Length of output: 11824


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## server script outline\n'
ast-grep outline test/e2e/lib/fake-openai-compatible-api.mts --view expanded

printf '\n## logging and readiness references\n'
rg -n 'requestsFile|auth:|authorizationSent|requireAuthModels|/v1/models|writeFileSync|appendFileSync|readiness' test/e2e/lib/fake-openai-compatible-api.mts -A4 -B4

printf '\n## relevant server body\n'
cat -n test/e2e/lib/fake-openai-compatible-api.mts | sed -n '1,260p'

Repository: NVIDIA/NemoClaw

Length of output: 15843


Exclude the readiness probe from the request-log auth check. NEMOCLAW_FAKE_OPENAI_REQUIRE_AUTH_MODELS=1 makes the unauthenticated /v1/models readiness request record auth: "missing" in the shared requests file, and nemoclaw_e2e_assert_hermetic_compatible_inference_used fails on any missing-auth entry. Filter that probe out or clear the log after startup.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/lib/hermetic-compatible-inference.sh` at line 27, The readiness
probe request to /v1/models is being counted in the shared request log with
auth: "missing", which causes the hermetic inference auth assertion to fail.
Update the startup/test flow around NEMOCLAW_FAKE_OPENAI_REQUIRE_AUTH_MODELS=1
so the readiness probe is excluded from the request-log auth check, either by
filtering that probe in nemoclaw_e2e_assert_hermetic_compatible_inference_used
or by clearing the log after startup. Use the existing readiness probe and
request log handling in hermetic-compatible-inference.sh to locate the fix.


if ! start_fake_openai_compatible_api; then
return 1
Expand All @@ -42,6 +43,29 @@ nemoclaw_e2e_stop_hermetic_compatible_inference() {
stop_fake_openai_compatible_api
}

nemoclaw_e2e_assert_hermetic_compatible_endpoint_consulted() {
node - "${FAKE_OPENAI_REQUESTS_FILE:-}" <<'NODE'
const fs = require("fs");
const requestsFile = process.argv[2];
if (!requestsFile || !fs.existsSync(requestsFile)) {
throw new Error(`request log missing: ${requestsFile || "<unset>"}`);
}
const entries = fs.readFileSync(requestsFile, "utf8")
.split(/\n+/)
.filter(Boolean)
.map((line) => JSON.parse(line));
const consultations = entries.filter((entry) =>
entry.method === "GET" &&
["/v1/models", "/models"].includes(entry.path) &&
entry.authorizationSent === true &&
entry.auth === "ok"
);
if (consultations.length === 0) {
throw new Error(`expected an authenticated fake endpoint models consultation, got ${JSON.stringify(entries)}`);
}
NODE
}

nemoclaw_e2e_assert_hermetic_compatible_inference_used() {
node - "${FAKE_OPENAI_REQUESTS_FILE:-}" <<'NODE'
const fs = require("fs");
Expand Down
7 changes: 5 additions & 2 deletions test/e2e/lib/openai-compatible-api-proof.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: Apache-2.0

start_fake_openai_compatible_api() {
local script_dir server_script port_file ready_host public_host
local script_dir server_script port_file ready_host public_host readiness_status
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
server_script="${script_dir}/fake-openai-compatible-api.mts"
port_file="${FAKE_OPENAI_PORT_FILE:-$(mktemp)}"
Expand Down Expand Up @@ -32,7 +32,10 @@ start_fake_openai_compatible_api() {
for _ in $(seq 1 "${FAKE_OPENAI_READY_ATTEMPTS:-30}"); do
if [ -s "$port_file" ]; then
FAKE_OPENAI_PORT="$(cat "$port_file")"
if curl -sf "http://${ready_host}:${FAKE_OPENAI_PORT}/v1/models" >/dev/null 2>&1; then
readiness_status="$(curl -sS -o /dev/null -w '%{http_code}' "http://${ready_host}:${FAKE_OPENAI_PORT}/v1/models" 2>/dev/null || true)"
# A 401 still proves the server is listening when the fixture deliberately
# requires credentials on /v1/models.
if [ "$readiness_status" = "200" ] || [ "$readiness_status" = "401" ]; then
public_host="${FAKE_OPENAI_PUBLIC_HOST:-$FAKE_OPENAI_HOST}"
if [ "$public_host" = "0.0.0.0" ]; then
public_host="127.0.0.1"
Expand Down
9 changes: 7 additions & 2 deletions test/e2e/live/cloud-experimental-checks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ export function buildCloudExperimentalCommandEnv(
};
}

export function cloudExperimentalApiKeyForCheck(scriptPath: string, apiKey: string): string {
return scriptPath === DEEPAGENTS_FRESH_REONBOARD_CHECK ? "" : apiKey;
}

export function assertRequiredCloudExperimentalResult(
scriptPath: string,
result: ShellProbeResult,
Expand Down Expand Up @@ -137,11 +141,12 @@ export async function runE2eCloudExperimentalChecks(
checkScripts.length > 0 ? assertDeepAgentsRuntimeObserved(sandboxName, context) : undefined,
);
for (const scriptPath of checkScripts) {
const scriptApiKey = cloudExperimentalApiKeyForCheck(scriptPath, apiKey);
const result = await context.host.command("bash", [path.join(REPO_ROOT, scriptPath)], {
artifactName: `cloud-experimental-${path.basename(scriptPath, ".sh")}`,
cwd: REPO_ROOT,
env: buildCloudExperimentalCommandEnv(sandboxName, apiKey),
redactionValues: [apiKey],
env: buildCloudExperimentalCommandEnv(sandboxName, scriptApiKey),
redactionValues: scriptApiKey ? [scriptApiKey] : [],
timeoutMs: cloudExperimentalCheckTimeoutMs(scriptPath),
});
assertRequiredCloudExperimentalResult(scriptPath, result);
Expand Down
208 changes: 203 additions & 5 deletions test/e2e/support/platform-parity-cloud-experimental.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,28 @@ vi.mock("../../../src/lib/actions/sandbox/exec", () => ({

import SandboxExecCommand from "../../../src/commands/sandbox/exec.ts";
import type { ShellProbeResult } from "../fixtures/shell-probe.ts";
import { DEEPAGENTS_CLOUD_EXPERIMENTAL_CHECKS } from "../live/cloud-experimental-check-list.ts";
import {
DEEPAGENTS_CLOUD_EXPERIMENTAL_CHECKS,
DEEPAGENTS_FRESH_REONBOARD_CHECK,
} from "../live/cloud-experimental-check-list.ts";
import {
assertRequiredCloudExperimentalResult,
buildCloudExperimentalChecksEvidence,
buildCloudExperimentalCommandEnv,
cloudExperimentalApiKeyForCheck,
cloudExperimentalCheckTimeoutMs,
} from "../live/cloud-experimental-checks.ts";

const dcodeTavilyCheck = path.join(
process.cwd(),
"test/e2e/e2e-cloud-experimental/checks/09-deepagents-code-tavily-opt-in.sh",
);
const dcodeFreshReonboardCheck = path.join(
process.cwd(),
"test/e2e/e2e-cloud-experimental/checks/04-deepagents-code-fresh-reonboard.sh",
);
const dcodeFreshReonboardCheck = path.join(process.cwd(), DEEPAGENTS_FRESH_REONBOARD_CHECK);
const freshReonboardTimeoutMs = 30_000;

function writeExecutable(filePath: string, lines: string[]): void {
fs.writeFileSync(filePath, `${lines.join("\n")}\n`, { mode: 0o755 });
}

function shellResult(exitCode: number, stdout: string, stderr = ""): ShellProbeResult {
return {
Expand Down Expand Up @@ -82,6 +88,186 @@ describe("P0-E cloud-experimental parity guardrails", () => {
expect(script).toContain("re-onboard with the new selection");
});

it(
"runs fresh re-onboard against a fake endpoint without hosted inference secrets (#5747)",
() => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-fresh-reonboard-"));
try {
const binDir = path.join(tmp, "bin");
const homeDir = path.join(tmp, "home");
fs.mkdirSync(binDir);
fs.mkdirSync(homeDir);
const marker = path.join(tmp, "reonboard-done");
const requestsFile = path.join(tmp, "requests.jsonl");
const openshell = path.join(binDir, "openshell");
const cli = path.join(binDir, "nemoclaw");

writeExecutable(openshell, [
"#!/usr/bin/env bash",
"set -euo pipefail",
'if [ "$1" = "sandbox" ] && [ "$2" = "exec" ]; then',
" shift 2",
' [ "$1" = "--name" ] || { echo "missing --name" >&2; exit 2; }',
" shift 2",
' [ "$1" = "--" ] || { echo "missing command boundary" >&2; exit 2; }',
" shift",
' if [ "$1" = "bash" ] && [ "$2" = "-c" ]; then',
' case "$3" in',
' *"test -d /sandbox/.deepagents"*) exit 0 ;;',
' *"sha256sum /sandbox/.deepagents/config.toml"*)',
" printf '%s\\n' 0000000000000000000000000000000000000000000000000000000000000000",
" exit 0",
" ;;",
" *)",
' if [ -f "$FAKE_REONBOARD_DONE" ]; then',
' printf "%s\\n" "NEMOCLAW_DCODE_FRESH_CONFIG_VERIFIED"',
" else",
' printf "%s\\n" "NEMOCLAW_DCODE_STALE_CONFIG_SEEDED"',
" fi",
" exit 0",
" ;;",
" esac",
" fi",
' if [ "$1" = "/usr/local/bin/dcode" ] && [ "$2" = "identity" ]; then',
' if [ -f "$FAKE_REONBOARD_DONE" ]; then',
' model="openai/openai/gpt-5.5"',
" else",
' model="nvidia/nvidia/nemotron-3-ultra"',
" fi",
' printf "Route: inference\\nProvider: compatible-endpoint\\nModel: openai:%s\\nEndpoint: https://inference.local/v1\\n" "$model"',
" exit 0",
" fi",
"fi",
'if [ "$1" = "sandbox" ] && [ "$2" = "list" ]; then',
' printf "%s\\n" "deepagents-sandbox Ready"',
" exit 0",
"fi",
'printf "unexpected openshell args: %s\\n" "$*" >&2',
"exit 2",
]);

writeExecutable(cli, [
"#!/usr/bin/env bash",
"set -euo pipefail",
"fail() { printf 'fake nemoclaw: %s\\n' \"$1\" >&2; exit 2; }",
'if [ "$1" = "onboard" ]; then',
' if printenv NVIDIA_INFERENCE_API_KEY >/dev/null; then fail "NVIDIA_INFERENCE_API_KEY leaked"; fi',
' if [ "$(printenv NEMOCLAW_E2E_USE_HOSTED_INFERENCE 2>/dev/null || true)" = "1" ]; then fail "hosted inference flag leaked"; fi',
' [ "$(printenv COMPATIBLE_API_KEY)" = "e2e-compatible-key" ] || fail "missing fake compatible key"',
' [ "$(printenv NEMOCLAW_PROVIDER)" = "custom" ] || fail "missing custom provider"',
' [ "$(printenv NEMOCLAW_MODEL)" = "openai/openai/gpt-5.5" ] || fail "wrong target model"',
' case "$(printenv NEMOCLAW_ENDPOINT_URL)" in',
" http://127.0.0.1:*/v1) ;;",
' *) fail "unexpected compatible endpoint" ;;',
" esac",
" node --input-type=module <<'NODE'",
'const response = await fetch(process.env.NEMOCLAW_ENDPOINT_URL + "/models", {',
" headers: {",
' authorization: "Bearer " + process.env.COMPATIBLE_API_KEY',
" },",
"});",
"if (!response.ok) {",
" console.error(await response.text());",
" process.exit(1);",
"}",
"NODE",
' mkdir -p "$HOME/.nemoclaw"',
' printf \'%s\\n\' \'{"sandboxes":{"deepagents-sandbox":{"agent":"langchain-deepagents-code","model":"openai/openai/gpt-5.5","provider":"compatible-endpoint","credentialEnv":"COMPATIBLE_API_KEY"}}}\' > "$HOME/.nemoclaw/sandboxes.json"',
' touch "$FAKE_REONBOARD_DONE"',
' printf "%s\\n" "Backing up workspace state before recreating sandbox..."',
' printf "%s\\n" "Restoring workspace state from pre-recreate backup..."',
" exit 0",
"fi",
'if [ "$1" = "deepagents-sandbox" ] && [ "$2" = "config" ] && [ "$3" = "get" ]; then',
' if [ -f "$FAKE_REONBOARD_DONE" ]; then',
' model="openai/openai/gpt-5.5"',
" else",
' model="nvidia/nvidia/nemotron-3-ultra"',
" fi",
' if [ "$#" -eq 3 ]; then',
' MODEL="$model" node -e \'console.log(JSON.stringify({models:{default:"openai:" + process.env.MODEL},headers:{authorization:"[STRIPPED_BY_MIGRATION]"}}))\'',
' elif [ "$4" = "--key" ] && [ "$5" = "models.default" ]; then',
' printf \'"openai:%s"\\n\' "$model"',
' elif [ "$4" = "--format" ] && [ "$5" = "yaml" ]; then',
' printf \'models:\\n default: openai:%s\\nheaders:\\n authorization: "[STRIPPED_BY_MIGRATION]"\\n\' "$model"',
" else",
' fail "unexpected config get args"',
" fi",
" exit 0",
"fi",
'if [ "$1" = "deepagents-sandbox" ] && [ "$2" = "config" ] && [ "$3" = "set" ]; then',
' printf "%s\\n" "config is baked into the sandbox image at build time" >&2',
' printf "%s\\n" "re-onboard with the new selection using --fresh" >&2',
" exit 1",
"fi",
'if [ "$1" = "deepagents-sandbox" ] && [ "$2" = "status" ] && [ "$3" = "--json" ]; then',
' printf \'%s\\n\' \'{"name":"deepagents-sandbox","model":"openai/openai/gpt-5.5","provider":"compatible-endpoint"}\'',
" exit 0",
"fi",
'printf "unexpected nemoclaw args: %s\\n" "$*" >&2',
"exit 2",
]);

const result = spawnSync("bash", [dcodeFreshReonboardCheck], {
encoding: "utf8",
timeout: freshReonboardTimeoutMs,
env: {
COMPATIBLE_API_KEY: "hosted-compatible-secret-should-not-be-used",
FAKE_OPENAI_PUBLIC_HOST: "127.0.0.1",
FAKE_OPENAI_REQUESTS_FILE: requestsFile,
FAKE_REONBOARD_DONE: marker,
HOME: homeDir,
NEMOCLAW_CLI_BIN: cli,
NEMOCLAW_E2E_USE_HOSTED_INFERENCE: "1",
NEMOCLAW_ENDPOINT_URL: "https://inference-api.nvidia.com/v1",
NVIDIA_INFERENCE_API_KEY: "hosted-nvidia-secret-should-not-be-used",
PATH: binDir + ":" + (process.env.PATH ?? "/usr/bin:/bin"),
REPO: process.cwd(),
SANDBOX_NAME: "deepagents-sandbox",
},
});

expect(result.status, result.stdout + "\n" + result.stderr).toBe(0);
expect(result.stdout).toContain(
"04-deepagents-code-fresh-reonboard: OK (started hermetic compatible inference for re-onboard)",
);
expect(result.stdout).toContain("04-deepagents-code-fresh-reonboard: 12 passed, 0 failed");
expect(result.stdout + result.stderr).not.toContain(
"hosted-nvidia-secret-should-not-be-used",
);
expect(result.stdout + result.stderr).not.toContain(
"hosted-compatible-secret-should-not-be-used",
);
const endpointRequests = fs
.readFileSync(requestsFile, "utf8")
.trim()
.split("\n")
.map(
(line) =>
JSON.parse(line) as {
auth?: string;
authorizationSent?: boolean;
method: string;
path: string;
},
);
expect(
endpointRequests.some(
(request) =>
request.method === "GET" &&
request.path === "/v1/models" &&
request.authorizationSent === true &&
request.auth === "ok",
),
).toBe(true);
expect(endpointRequests.some((request) => request.method === "POST")).toBe(false);
} finally {
fs.rmSync(tmp, { force: true, recursive: true });
}
},
freshReonboardTimeoutMs,
);

it("preserves the repeated env-unset pairs from the failed observability invocation", async () => {
await SandboxExecCommand.run(
[
Expand Down Expand Up @@ -479,6 +665,18 @@ describe("P0-E cloud-experimental parity guardrails", () => {
).toBe(35 * 60_000);
});

it("withholds the hosted inference key from the hermetic re-onboard check (#5747)", () => {
expect(cloudExperimentalApiKeyForCheck(DEEPAGENTS_FRESH_REONBOARD_CHECK, "secret-key")).toBe(
"",
);
expect(
cloudExperimentalApiKeyForCheck(
"test/e2e/e2e-cloud-experimental/checks/07-deepagents-code-headless-inference.sh",
"secret-key",
),
).toBe("secret-key");
});

it("documents Deep Agents check scripts in generated launch/QA evidence", () => {
const evidence = buildCloudExperimentalChecksEvidence(
"cloud-langchain-deepagents-code",
Expand Down
Loading