From 500d15e099dd34b79cdbd65ea1645eca4a70b74b Mon Sep 17 00:00:00 2001 From: Prekshi Vyas Date: Mon, 6 Jul 2026 14:55:34 -0700 Subject: [PATCH 1/4] test(e2e): register typed-source require hook for the e2e-live project MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The e2e-live Vitest project did not load the typed-source require hook (test/helpers/onboard-script-mocks.cjs), unlike the cli and integration projects. When a live suite imports a source module whose graph resolves a sibling via a runtime require of an extensionless .ts file — e.g. src/lib/inference/ollama-runtime-context.ts's require("../runner"), reached transitively from the hermes-inference-switch helpers importing src/lib/inference/config.ts — Node's native CJS resolver cannot find the module and the suite fails at collection ("Cannot find module '../runner'", 0 tests). Register the hook via setupFiles rather than NODE_OPTIONS so it stays in-process and never leaks --require into the real CLI subprocesses the live tests spawn. Mirrors the cli project. Verified with `NEMOCLAW_RUN_LIVE_E2E=1 npx vitest list --project e2e-live`: the switch suite now collects and all e2e-live suites report 0 collection errors. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Prekshi Vyas --- vitest.config.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vitest.config.ts b/vitest.config.ts index 89a564153f..5cbe8c26a6 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -140,6 +140,13 @@ export default defineConfig({ test: { name: "e2e-live", alias: canonicalOpenShellPolicyAlias, + // Register the typed-source require hook in the worker so live suites + // can import source modules that resolve siblings via a runtime + // `require("../module")` (e.g. inference/ollama-runtime-context.ts). + // Use setupFiles rather than NODE_OPTIONS so the hook stays in-process + // and never leaks `--require` into the real CLI subprocesses under + // test. Mirrors the `cli` project. + setupFiles: ["test/helpers/onboard-script-mocks.cjs"], testTimeout: testTimeout(LIVE_E2E_PROJECT_TIMEOUT_MS), // Live targets mutate host, Docker, gateway, and sandbox state. A // whole-test retry reuses that state and can hide the first failure From adb79d5f52774528d8c8d1903582f6e1da54f985 Mon Sep 17 00:00:00 2001 From: Prekshi Vyas Date: Mon, 6 Jul 2026 15:36:07 -0700 Subject: [PATCH 2/4] test(e2e): surface dcode identity output when cloud-onboard check fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cloud-experimental check-04 (fresh DCode re-onboard) captures `dcode identity` stdout+stderr into a shell variable via command substitution, but the `|| fail` handler prints only a generic message and discards the captured output. When `dcode identity` exits non-zero the real reason is lost — CI logs and result.json show stdout "" — which is why the current cloud-onboard failure on main (introduced with this check in #6332) cannot be diagnosed. Print the captured output to stdout (so it lands in result.json) before failing, on both the initial and post-re-onboard identity reads. No behavior change to the check's pass/fail logic; this only makes the existing failure observable so the root cause in the managed DCode onboarding flow can be found. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Prekshi Vyas --- .../checks/04-deepagents-code-fresh-reonboard.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/e2e/e2e-cloud-experimental/checks/04-deepagents-code-fresh-reonboard.sh b/test/e2e/e2e-cloud-experimental/checks/04-deepagents-code-fresh-reonboard.sh index 4e5de37a30..a948b1fbb1 100755 --- a/test/e2e/e2e-cloud-experimental/checks/04-deepagents-code-fresh-reonboard.sh +++ b/test/e2e/e2e-cloud-experimental/checks/04-deepagents-code-fresh-reonboard.sh @@ -139,7 +139,13 @@ PY [ -n "${COMPATIBLE_API_KEY:-}" ] || fail "COMPATIBLE_API_KEY is required" [ -x "$CLI" ] || fail "NemoClaw CLI is not executable at $CLI" -identity_before="$(dcode_identity)" || fail "could not read initial dcode identity" +if ! identity_before="$(dcode_identity)"; then + # Surface the captured stdout+stderr (dcode_identity redirects 2>&1) before + # failing. Without this the real reason `dcode identity` exits non-zero is + # discarded and CI/result.json only show the generic message with stdout "". + printf '%s: diagnostic: initial dcode identity output:\n%s\n' "$PREFIX" "${identity_before:-}" + fail "could not read initial dcode identity" +fi model_a="$(identity_field "$identity_before" Model)" model_a="${model_a#openai:}" [ -n "$model_a" ] || fail "initial dcode identity did not report a model" @@ -184,7 +190,10 @@ 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" printf '%s\n' "$sandbox_list" | awk -v name="$SANDBOX_NAME" '$1 == name && /Ready/ { found = 1 } END { exit(found ? 0 : 1) }' || fail "same-name sandbox is not Ready after re-onboard" -identity_after="$(dcode_identity)" || fail "could not read dcode identity after re-onboard" +if ! identity_after="$(dcode_identity)"; then + printf '%s: diagnostic: dcode identity output after re-onboard:\n%s\n' "$PREFIX" "${identity_after:-}" + fail "could not read dcode identity after re-onboard" +fi assert_identity "$identity_after" "$model_b" "fresh" printf '%s\n' "$identity_after" | grep -Fq "$model_a" && fail "fresh identity still contains model A" pass "live dcode identity reports model B" From f427494d3f9ebf277deb16381beeeb30529326b5 Mon Sep 17 00:00:00 2001 From: Prekshi Vyas Date: Mon, 6 Jul 2026 16:00:04 -0700 Subject: [PATCH 3/4] fix(test): invoke dcode by absolute path in the cloud-onboard reonboard check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit check-04 read the live identity with `openshell sandbox exec -- dcode identity`. That runs without a login shell, so /usr/local/bin is not on PATH and `dcode` resolves to "command not found" — the real reason cloud-onboard has failed on main since #6332 added this check (surfaced by the preceding observability commit). The image installs the launcher at /usr/local/bin/dcode, so invoke it by absolute path. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Prekshi Vyas --- .../checks/04-deepagents-code-fresh-reonboard.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/e2e/e2e-cloud-experimental/checks/04-deepagents-code-fresh-reonboard.sh b/test/e2e/e2e-cloud-experimental/checks/04-deepagents-code-fresh-reonboard.sh index a948b1fbb1..da2068e1d9 100755 --- a/test/e2e/e2e-cloud-experimental/checks/04-deepagents-code-fresh-reonboard.sh +++ b/test/e2e/e2e-cloud-experimental/checks/04-deepagents-code-fresh-reonboard.sh @@ -33,7 +33,11 @@ sandbox_exec() { } dcode_identity() { - openshell sandbox exec --name "$SANDBOX_NAME" -- dcode identity 2>&1 + # Invoke dcode by absolute path: `openshell sandbox exec -- dcode ...` runs + # without a login shell, so /usr/local/bin is not on PATH and a bare `dcode` + # resolves to "command not found". The image installs the launcher at + # /usr/local/bin/dcode (see agents/langchain-deepagents-code/Dockerfile). + openshell sandbox exec --name "$SANDBOX_NAME" -- /usr/local/bin/dcode identity 2>&1 } identity_field() { From 2bccc3640ae430b7f6081a8057bf26d9232d289b Mon Sep 17 00:00:00 2001 From: Prekshi Vyas Date: Mon, 6 Jul 2026 16:00:24 -0700 Subject: [PATCH 4/4] fix(test): strip ANSI before matching compatible-anthropic provider Type The anthropic variant of the inference-switch suite asserts that `openshell provider get compatible-anthropic-endpoint` reports `Type: openai` with an anchored regex. That command wraps field labels in ANSI escapes (`\e[2mType:\e[0m openai`), so the anchored match failed even though the provider is correctly registered as Type: openai. Strip ANSI first. The check only runs in the anthropic variant, which is why the hosted variant passed. This failure was masked on main by the collection error the e2e-live require hook fixed; with the suite now collecting, the assertion is reachable. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Prekshi Vyas --- test/e2e/live/hermes-inference-switch.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/e2e/live/hermes-inference-switch.test.ts b/test/e2e/live/hermes-inference-switch.test.ts index 394df58e22..c1d64525c3 100644 --- a/test/e2e/live/hermes-inference-switch.test.ts +++ b/test/e2e/live/hermes-inference-switch.test.ts @@ -48,6 +48,7 @@ import { registerPublicNvidiaSwitchProvider, requirePublicNvidiaSwitchKey, } from "./public-nvidia-switch-provider.ts"; +import { stripAnsi } from "./json-envelope.ts"; const TIMEOUT_MS = 45 * 60_000; const MOCK_BASELINE_API_KEY = "hermes-inference-switch-baseline-credential"; @@ -70,7 +71,10 @@ async function expectCompatibleAnthropicOpenAiProvider( }, ); expect(provider.exitCode, resultText(provider)).toBe(0); - expect(resultText(provider)).toMatch(/^\s*Type:\s*openai\s*$/imu); + // `openshell provider get` wraps field labels in ANSI escapes (e.g. + // `\e[2mType:\e[0m openai`), which breaks the anchored regex. Strip ANSI + // first — the provider is correctly registered as Type: openai. + expect(stripAnsi(resultText(provider))).toMatch(/^\s*Type:\s*openai\s*$/imu); expect(resultText(provider)).toContain("COMPATIBLE_ANTHROPIC_API_KEY"); expect(resultText(provider)).toContain("OPENAI_BASE_URL"); }