Skip to content
Merged
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 @@ -77,8 +77,130 @@ sandbox_dcode_wrapper_contract() {
sandbox_exec 'dcode_path="$(command -v dcode 2>/dev/null || true)"; [ "$dcode_path" = /usr/local/bin/dcode ] && [ -x /usr/local/lib/nemoclaw/dcode-launcher.sh ] && [ -x /usr/local/lib/nemoclaw/dcode-managed-exec ] && [ -x /usr/local/lib/nemoclaw/dcode-wrapper.sh ] && cmp -s /usr/local/bin/dcode /usr/local/lib/nemoclaw/dcode-launcher.sh && cmp -s /usr/local/lib/nemoclaw/dcode-managed-exec /usr/local/lib/nemoclaw/dcode-launcher.sh && python3 -c '\''import importlib.util,sys; sys.exit(0 if importlib.util.find_spec("deepagents_code") else 1)'\'' && printf "%s\\n" NEMOCLAW_DCODE_WRAPPER_CHAIN_OK'
}

write_openshell_target_shim() {
local shim_path="$1"

cat >"$shim_path" <<'SHIM'
#!/bin/bash
set -euo pipefail

real_openshell="${OPENSHELL_NEMOCLAW_REAL_BIN:?}"
trace_file="${OPENSHELL_NEMOCLAW_TARGET_TRACE:?}"
original_args=("$@")

if [ "${1:-}" = "sandbox" ] && [ "${2:-}" = "exec" ]; then
shift 2
while [ "$#" -gt 0 ]; do
case "$1" in
-n | --name)
[ "$#" -ge 2 ] || exit 64
printf '%s\n' "$2" >>"$trace_file"
break
;;
--name=*)
printf '%s\n' "${1#--name=}" >>"$trace_file"
break
;;
--)
break
;;
esac
shift
done
fi

unset OPENSHELL_NEMOCLAW_REAL_BIN OPENSHELL_NEMOCLAW_TARGET_TRACE
exec "$real_openshell" "${original_args[@]}"
SHIM
chmod 0700 "$shim_path"
}

validate_connect_target_trace() {
local trace_file="$1"
local observed=0
local target

if [ ! -s "$trace_file" ]; then
printf '%s\n' "NEMOCLAW_DCODE_CONNECT_TARGET_FAIL:missing"
return 1
fi

while IFS= read -r target || [ -n "$target" ]; do
observed=$((observed + 1))
if [ "$target" != "$SANDBOX_NAME" ]; then
printf '%s\n' "NEMOCLAW_DCODE_CONNECT_TARGET_FAIL:mismatch"
return 1
fi
done <"$trace_file"

if [ "$observed" -eq 0 ]; then
printf '%s\n' "NEMOCLAW_DCODE_CONNECT_TARGET_FAIL:missing"
return 1
fi
}

nemoclaw_connect_probe() {
"${NEMOCLAW_CLI_BIN:-${REPO:-.}/bin/nemoclaw.js}" "$SANDBOX_NAME" connect --probe-only 2>&1
local real_openshell
local trace_dir
local trace_file
local shim_path
local connect_output
local connect_status
local trace_result

real_openshell="$(command -v openshell 2>/dev/null || true)"
case "$real_openshell" in
/*) ;;
*)
printf '%s\n' "NEMOCLAW_DCODE_CONNECT_TARGET_FAIL:openshell"
return 1
;;
esac
if [ ! -x "$real_openshell" ]; then
printf '%s\n' "NEMOCLAW_DCODE_CONNECT_TARGET_FAIL:openshell"
return 1
fi

if ! trace_dir="$(mktemp -d "${TMPDIR:-/tmp}/nemoclaw-dcode-connect.XXXXXX")"; then
printf '%s\n' "NEMOCLAW_DCODE_CONNECT_TARGET_FAIL:shim"
return 1
fi
trace_file="$trace_dir/targets"
shim_path="$trace_dir/openshell"
if ! : >"$trace_file" || ! write_openshell_target_shim "$shim_path"; then
rm -rf -- "$trace_dir"
printf '%s\n' "NEMOCLAW_DCODE_CONNECT_TARGET_FAIL:shim"
return 1
fi

# Exercise the public bare-connect route with every sandbox-name alias
# removed. The test-only OpenShell shim records the actual post-routing exec
# targets and then exact-execs the real absolute OpenShell binary.
if connect_output="$(
unset SANDBOX_NAME NEMOCLAW_SANDBOX_NAME NEMOCLAW_SANDBOX
env \
OPENSHELL_NEMOCLAW_REAL_BIN="$real_openshell" \
OPENSHELL_NEMOCLAW_TARGET_TRACE="$trace_file" \
NEMOCLAW_OPENSHELL_BIN="$shim_path" \
"${NEMOCLAW_CLI_BIN:-${REPO:-.}/bin/nemoclaw.js}" connect --probe-only 2>&1
)"; then
connect_status=0
else
connect_status=$?
fi

if trace_result="$(validate_connect_target_trace "$trace_file")"; then
rm -rf -- "$trace_dir"
printf '%s\n' "$connect_output"
return "$connect_status"
else
connect_status=$?
fi

rm -rf -- "$trace_dir"
printf '%s\n' "$connect_output"
printf '%s\n' "$trace_result"
return "$connect_status"
}

dcode_connect_fail_closed_contract() (
Expand Down Expand Up @@ -462,13 +584,21 @@ DCODE_EXIT:${direct_exit}"
fail_test "direct-exec dcode -n did not exit 0 with PONG (${direct_classification}, exit ${direct_exit})"
fi

# 7. The user-facing connect readiness path accepts the same managed route.
# 7. The user-facing bare-connect readiness path must route every observed
# sandbox exec to the same sandbox used by the preceding lifecycle evidence.
connect_output=""
if connect_output="$(nemoclaw_connect_probe)"; then
connect_exit=0
pass "bare connect targeted the Deep Agents Code sandbox"
pass "nemoclaw connect --probe-only accepted the managed inference route (direct DNS/hosts ${direct_dns_state})"
else
connect_exit=$?
fail_test "nemoclaw connect --probe-only rejected the managed inference route (exit ${connect_exit})"
connect_target_reason="$(printf '%s\n' "$connect_output" | sed -n 's/^NEMOCLAW_DCODE_CONNECT_TARGET_FAIL:\([a-z-]*\)$/\1/p' | tail -n1)"
if [ -n "$connect_target_reason" ]; then
fail_test "bare connect did not target the expected sandbox (${connect_target_reason})"
else
fail_test "nemoclaw connect --probe-only rejected the managed inference route (exit ${connect_exit})"
fi
fi

# 8. Untrusted evidence from the image-installed helper must fail closed
Expand Down
132 changes: 132 additions & 0 deletions test/langchain-deepagents-code-headless-runtime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,138 @@ import {
} from "./helpers/langchain-deepagents-code-headless.ts";

describe("LangChain Deep Agents Code headless runtime contracts", () => {
it("binds bare connect to every observed OpenShell sandbox exec target (#7034)", () => {
const fixtureDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-dcode-connect-target-"));
const cliFixture = path.join(fixtureDir, "nemoclaw");
const openshellFixture = path.join(fixtureDir, "openshell");
const cliCallLog = path.join(fixtureDir, "cli-calls.log");
const openshellCallLog = path.join(fixtureDir, "openshell-calls.log");

try {
fs.writeFileSync(
cliFixture,
[
"#!/bin/bash",
"set -euo pipefail",
'[ "${SANDBOX_NAME+x}" != x ]',
'[ "${NEMOCLAW_SANDBOX_NAME+x}" != x ]',
'[ "${NEMOCLAW_SANDBOX+x}" != x ]',
'printf "%s\\n" "$*" >>"$TEST_CLI_CALL_LOG"',
'[ "$#" -eq 2 ] && [ "$1" = connect ] && [ "$2" = --probe-only ]',
"for target in $TEST_CONNECT_TARGETS; do",
' "$NEMOCLAW_OPENSHELL_BIN" sandbox exec -n "$target" -- true',
"done",
'printf "%s\\n" NEMOCLAW_DCODE_CONNECT_OK',
'exit "$TEST_CONNECT_EXIT"',
"",
].join("\n"),
"utf8",
);
fs.writeFileSync(
openshellFixture,
[
"#!/bin/bash",
"set -euo pipefail",
'printf "%s\\n" "$*" >>"$TEST_OPENSHELL_CALL_LOG"',
"",
].join("\n"),
"utf8",
);
fs.chmodSync(cliFixture, 0o755);
fs.chmodSync(openshellFixture, 0o755);

const runCommandProbe = (targets: string, connectExit = 0) => {
fs.writeFileSync(cliCallLog, "", "utf8");
fs.writeFileSync(openshellCallLog, "", "utf8");
const output = runHeadlessCheckSnippet(
[
'if output="$(nemoclaw_connect_probe 2>&1)"; then',
' printf "pass:%s" "$output"',
"else",
" status=$?",
' printf "fail:%s:%s" "$status" "$output"',
"fi",
].join("\n"),
{
NEMOCLAW_CLI_BIN: cliFixture,
NEMOCLAW_SANDBOX: "legacy-environment-shortcut",
NEMOCLAW_SANDBOX_NAME: "environment-shortcut",
PATH: `${fixtureDir}:/usr/bin:/bin`,
SANDBOX_NAME: "dcode-managed",
TEST_CLI_CALL_LOG: cliCallLog,
TEST_CONNECT_EXIT: String(connectExit),
TEST_CONNECT_TARGETS: targets,
TEST_OPENSHELL_CALL_LOG: openshellCallLog,
TMPDIR: fixtureDir,
},
);
const readCalls = (file: string) => {
const text = fs.readFileSync(file, "utf8").trim();
return text ? text.split("\n") : [];
};
expect(
fs.readdirSync(fixtureDir).filter((entry) => entry.startsWith("nemoclaw-dcode-connect.")),
).toEqual([]);
return {
cliCalls: readCalls(cliCallLog),
openshellCalls: readCalls(openshellCallLog),
output,
};
};

const matchingTarget = runCommandProbe("dcode-managed");
expect(matchingTarget).toEqual({
cliCalls: ["connect --probe-only"],
openshellCalls: ["sandbox exec -n dcode-managed -- true"],
output: "pass:NEMOCLAW_DCODE_CONNECT_OK",
});
const repeatedMatchingTarget = runCommandProbe("dcode-managed dcode-managed");
expect(repeatedMatchingTarget).toEqual({
cliCalls: ["connect --probe-only"],
openshellCalls: [
"sandbox exec -n dcode-managed -- true",
"sandbox exec -n dcode-managed -- true",
],
output: "pass:NEMOCLAW_DCODE_CONNECT_OK",
});
const wrongTarget = runCommandProbe("another-sandbox");
expect(wrongTarget).toEqual({
cliCalls: ["connect --probe-only"],
openshellCalls: ["sandbox exec -n another-sandbox -- true"],
output: "fail:1:NEMOCLAW_DCODE_CONNECT_OK\nNEMOCLAW_DCODE_CONNECT_TARGET_FAIL:mismatch",
});
const missingTarget = runCommandProbe("");
expect(missingTarget).toEqual({
cliCalls: ["connect --probe-only"],
openshellCalls: [],
output: "fail:1:NEMOCLAW_DCODE_CONNECT_OK\nNEMOCLAW_DCODE_CONNECT_TARGET_FAIL:missing",
});
const mixedTargets = runCommandProbe("dcode-managed another-sandbox");
expect(mixedTargets).toEqual({
cliCalls: ["connect --probe-only"],
openshellCalls: [
"sandbox exec -n dcode-managed -- true",
"sandbox exec -n another-sandbox -- true",
],
output: "fail:1:NEMOCLAW_DCODE_CONNECT_OK\nNEMOCLAW_DCODE_CONNECT_TARGET_FAIL:mismatch",
});
const failedConnect = runCommandProbe("dcode-managed", 72);
expect(failedConnect).toEqual({
cliCalls: ["connect --probe-only"],
openshellCalls: ["sandbox exec -n dcode-managed -- true"],
output: "fail:72:NEMOCLAW_DCODE_CONNECT_OK",
});
const failedConnectToWrongTarget = runCommandProbe("another-sandbox", 72);
expect(failedConnectToWrongTarget).toEqual({
cliCalls: ["connect --probe-only"],
openshellCalls: ["sandbox exec -n another-sandbox -- true"],
output: "fail:1:NEMOCLAW_DCODE_CONNECT_OK\nNEMOCLAW_DCODE_CONNECT_TARGET_FAIL:mismatch",
});
} finally {
fs.rmSync(fixtureDir, { force: true, recursive: true });
}
});

it("requires exit zero and PONG from Deep Agents Code headless inference (#6191)", () => {
const classify = (exitCode: string, output: string) =>
runHeadlessCheckHelper("classify-output", {
Expand Down
30 changes: 30 additions & 0 deletions test/langchain-deepagents-code-image.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,16 @@ describe("LangChain Deep Agents Code image contracts", () => {
"NEMOCLAW_DCODE_EMPTY_EXIT",
"login-shell dcode rejects an empty non-interactive prompt with exit 2",
"direct-exec dcode rejects an empty non-interactive prompt with exit 2",
"write_openshell_target_shim",
"OPENSHELL_NEMOCLAW_REAL_BIN",
"OPENSHELL_NEMOCLAW_TARGET_TRACE",
"validate_connect_target_trace",
"NEMOCLAW_DCODE_CONNECT_TARGET_FAIL:missing",
"NEMOCLAW_DCODE_CONNECT_TARGET_FAIL:mismatch",
"nemoclaw_connect_probe",
"unset SANDBOX_NAME NEMOCLAW_SANDBOX_NAME NEMOCLAW_SANDBOX",
'"${NEMOCLAW_CLI_BIN:-${REPO:-.}/bin/nemoclaw.js}" connect --probe-only 2>&1',
"bare connect targeted the Deep Agents Code sandbox",
"${NEMOCLAW_CLI_BIN:-${REPO:-.}/bin/nemoclaw.js}",
"connect --probe-only 2>&1",
"dcode_connect_fail_closed_contract",
Expand Down Expand Up @@ -836,6 +845,27 @@ describe("LangChain Deep Agents Code image contracts", () => {
]) {
expect(headlessCheck).toContain(expected);
}
expect(headlessCheck).not.toContain(
'"${NEMOCLAW_CLI_BIN:-${REPO:-.}/bin/nemoclaw.js}" "$SANDBOX_NAME" connect --probe-only',
);
const connectProbe = headlessCheck.slice(
headlessCheck.indexOf("nemoclaw_connect_probe() {"),
headlessCheck.indexOf("sandbox_login_proxy_contract() {"),
);
const shimWriteIndex = connectProbe.indexOf('write_openshell_target_shim "$shim_path"');
const aliasUnsetIndex = connectProbe.indexOf(
"unset SANDBOX_NAME NEMOCLAW_SANDBOX_NAME NEMOCLAW_SANDBOX",
);
const connectCommandIndex = connectProbe.indexOf(
'"${NEMOCLAW_CLI_BIN:-${REPO:-.}/bin/nemoclaw.js}" connect --probe-only',
);
const traceValidationIndex = connectProbe.indexOf(
'validate_connect_target_trace "$trace_file"',
);
expect(shimWriteIndex).toBeGreaterThan(-1);
expect(aliasUnsetIndex).toBeGreaterThan(shimWriteIndex);
expect(connectCommandIndex).toBeGreaterThan(aliasUnsetIndex);
expect(traceValidationIndex).toBeGreaterThan(connectCommandIndex);
expect(headlessCheck).not.toContain('sandbox_login_exec ". /tmp/nemoclaw-proxy-env.sh');
expect(headlessCheck).not.toContain("config_output:0:200");
expect(headlessCheck).toMatch(/headless_output=.*sandbox_login_exec.*\|\| true\)"/);
Expand Down
Loading