Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
41 changes: 38 additions & 3 deletions test/e2e/live/device-auth-health.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/

import { buildAvailabilityProbeEnv } from "../fixtures/availability-env.ts";
import { resultText } from "../fixtures/clients/index.ts";
import { resultText, shellQuote } from "../fixtures/clients/index.ts";
import { trustedSandboxShellScript } from "../fixtures/clients/sandbox.ts";
import { expect, test } from "../fixtures/e2e-test.ts";
import { startFakeOpenAiCompatibleServer } from "../fixtures/fake-openai-compatible.ts";
Expand Down Expand Up @@ -74,7 +74,7 @@ test("device auth health probes treat 401 as live instead of offline (#2342)", {
dashboardPort: DASHBOARD_PORT,
contracts: [
"onboard succeeds with device auth enabled",
"onboard authenticates to the fixture inference endpoint",
"the onboarded inference route authenticates to the fixture endpoint",
"/health is reachable from inside the sandbox",
"the authenticated dashboard root may return 401 without being treated as offline",
"nemoclaw status reports the gateway as live, not Health Offline",
Expand Down Expand Up @@ -107,9 +107,44 @@ test("device auth health probes treat 401 as live instead of offline (#2342)", {
progress.phase("onboard device-auth OpenClaw sandbox");
const install = await installDeviceAuthSandbox(host, inferenceConfig, installLog);
expect(install.exitCode, resultText(install)).toBe(0);
expect(inference.requests()).toContainEqual(

// Ignore incidental onboarding traffic. The fixture appends its ledger row
// before responding, so this awaited POST is the publication barrier for the
// requests sliced from this offset.
const authenticatedRequestOffset = inference.requests().length;
const authenticatedProbe = await sandbox.execShell(
SANDBOX_NAME,
trustedSandboxShellScript(
`curl -fsS --max-time 60 https://inference.local/v1/chat/completions -H 'Content-Type: application/json' --data ${shellQuote(
JSON.stringify({
model: INFERENCE_MODEL,
messages: [{ role: "user", content: "reply with OK" }],
max_tokens: 8,
}),
)} >/dev/null`,
),
{
artifactName: "phase-1-explicit-authenticated-inference-post",
env: commandEnv(),
timeoutMs: 90_000,
},
);
const authenticatedRequests = inference.requests().slice(authenticatedRequestOffset);
await artifacts.writeJson("phase-1-explicit-authenticated-inference-requests.json", {
phase: "onboard device-auth OpenClaw sandbox",
requests: authenticatedRequests,
});
expect(
authenticatedProbe.exitCode,
`explicit authenticated inference failed during the onboard verification phase; observed requests=${JSON.stringify(authenticatedRequests)}; ${resultText(authenticatedProbe)}`,
).toBe(0);
expect(
authenticatedRequests,
`the explicit onboard verification probe did not reach the authenticated fixture; observed requests=${JSON.stringify(authenticatedRequests)}`,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
).toContainEqual(
expect.objectContaining({
auth: "ok",
method: "POST",
model: INFERENCE_MODEL,
path: "/v1/chat/completions",
}),
Expand Down
49 changes: 43 additions & 6 deletions test/e2e/live/openclaw-inference-switch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,53 @@ interface MockAnthropicProvider {
close(): Promise<void>;
}

function expectMockBaselineAuthentication(
async function proveMockBaselineAuthentication(
baseline: Pick<FakeOpenAiCompatibleServer, "requests"> | undefined,
): void {
sandbox: SandboxClient,
home: string,
artifacts: { writeJson(path: string, value: unknown): Promise<string> },
): Promise<void> {
if (!baseline) {
expect(baseline).toBeUndefined();
return;
}
// Ignore incidental onboarding traffic. The fixture appends its ledger row
// before responding, so this awaited POST is the publication barrier for the
// requests sliced from this offset.
const requestOffset = baseline.requests().length;
const payload = {
model: MOCK_BASELINE_MODEL,
messages: [{ role: "user", content: "reply with OK" }],
max_tokens: 8,
};
const probe = await sandboxShell(
sandbox,
home,
`curl -fsS --max-time 60 https://inference.local/v1/chat/completions -H 'Content-Type: application/json' --data ${shellQuote(JSON.stringify(payload))} >/dev/null`,
{
artifactName: "baseline-explicit-authenticated-inference-post",
timeoutMs: 90_000,
},
);
const requests = baseline.requests().slice(requestOffset);
await artifacts.writeJson("baseline-explicit-authenticated-inference-requests.json", {
phase: "install and onboard baseline OpenClaw",
requests,
});
expect(
probe.exitCode,
`explicit baseline inference failed during the install verification phase; observed requests=${JSON.stringify(requests)}; ${resultText(probe)}`,
).toBe(0);
const expectedRequest = expect.objectContaining({
auth: "ok",
method: "POST",
model: MOCK_BASELINE_MODEL,
path: "/v1/chat/completions",
});
baseline
? expect(baseline.requests()).toContainEqual(expectedRequest)
: expect(baseline).toBeUndefined();
expect(
requests,
`the explicit baseline verification probe did not reach the authenticated fixture; observed requests=${JSON.stringify(requests)}`,
).toContainEqual(expectedRequest);
}

function stripAnsi(value: string): string {
Expand Down Expand Up @@ -895,6 +931,7 @@ test("openclaw-inference-switch: switches route and preserves live OpenClaw beha
contracts: [
"Docker is running and an authenticated compatible baseline endpoint is staged",
"install.sh --non-interactive onboards an OpenClaw sandbox",
"when selected, the mock baseline route completes one explicit authenticated fixture request",
"nemoclaw inference set switches the running sandbox route",
"OpenClaw gateway is supervisor-restarted only when the inference API family changes",
"OpenShell route points at the switched provider/model",
Expand Down Expand Up @@ -1008,7 +1045,7 @@ test("openclaw-inference-switch: switches route and preserves live OpenClaw beha
skip("NVIDIA endpoint validation was unavailable/rate-limited during onboarding");
}
expect(install.exitCode, installText).toBe(0);
expectMockBaselineAuthentication(baselineProvider);
await proveMockBaselineAuthentication(baselineProvider, sandbox, home, artifacts);

progress.phase("prepare the switched provider and endpoint");
const publicProvider = publicApiKey
Expand Down
Loading