Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
49c18e4
test(e2e): add interactive onboard policy-preset step-ordering test (…
wakqasahmed Aug 8, 2026
6b2fe72
fix(e2e): use the shared docker fixture instead of an inline Docker c…
wakqasahmed Aug 8, 2026
9ce0eda
fix(e2e): redact the generated API key from onboard test assertion me…
wakqasahmed Aug 8, 2026
a79fdb7
Merge branch 'main' into test/onboard-policy-preset-sequencing-6042
cv Aug 8, 2026
4b0ea3d
Merge branch 'main' into test/onboard-policy-preset-sequencing-6042
cv Aug 9, 2026
eb5cfb4
fix(e2e): address maintainer review on the onboard PTY regression
wakqasahmed Aug 9, 2026
abe9231
merge(main): refresh PR #8618
apurvvkumaria Aug 11, 2026
b237902
merge(main): refresh PR #8618
apurvvkumaria Aug 11, 2026
6aa218c
merge(main): refresh PR #8618
apurvvkumaria Aug 11, 2026
38b5d26
test(e2e): complete onboard PTY review coverage
apurvvkumaria Aug 11, 2026
006518e
merge: refresh onboard policy sequencing base
apurvvkumaria Aug 11, 2026
7868381
test(e2e): terminate the PTY child session
prekshivyas Aug 11, 2026
b19cbeb
merge(main): refresh PR #8618
apurvvkumaria Aug 11, 2026
a27049e
Merge branch 'main' into test/onboard-policy-preset-sequencing-6042
cv Aug 11, 2026
ffaecff
Merge branch 'main' into test/onboard-policy-preset-sequencing-6042
cv Aug 11, 2026
20df452
Merge branch 'main' into test/onboard-policy-preset-sequencing-6042
cv Aug 12, 2026
747579b
merge(e2e): update #8618 with main
apurvvkumaria Aug 13, 2026
df8299c
Merge branch 'main' into test/onboard-policy-preset-sequencing-6042
cv Aug 13, 2026
b8cface
merge(main): refresh PR #8618
cv Aug 13, 2026
c4b5e05
ci(e2e): incorporate current main checks
cv Aug 13, 2026
9172a61
ci(e2e): incorporate current main checks
cv Aug 13, 2026
9bf0d0b
merge(e2e): retain formatted current-main checks
cv Aug 13, 2026
3895ca5
merge(main): resolve PR #8618 conflict
cv Aug 13, 2026
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
188 changes: 93 additions & 95 deletions src/lib/onboard/inference-selection-validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,67 +269,66 @@ describe("inference selection validation", () => {
expectedEndpointUrl: "https://anthropic.corp.example/v1",
expectedProbeOptions: { calibrateTimeouts: true, skipResponsesProbe: true },
},
])("probes an exactly allowlisted private Anthropic endpoint on its $runtimeSurface surface (#7037)", async ({
intendedApi,
expectedEndpointUrl,
expectedProbeOptions,
}) => {
vi.stubEnv("NEMOCLAW_TRUSTED_PRIVATE_INFERENCE_HOSTS", "anthropic.corp.example");
vi.stubEnv("NEMOCLAW_REASONING", "false");
const probeEndpoint = vi.fn(() => ({
ok: true,
api: intendedApi,
label: "Compatible API",
}));
const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
const log = vi.spyOn(console, "log").mockImplementation(() => {});
const helpers = createInferenceSelectionValidationHelpers({
isNonInteractive: () => false,
agentProductName: () => "NemoClaw agent",
getCredential: () => "test-key",
probeAnthropicEndpoint: probeEndpoint,
probeOpenAiLikeEndpoint: probeEndpoint,
promptValidationRecovery: vi.fn(async () => "selection" as const),
resolveEndpointHost: async () => [{ address: "10.0.0.8", family: 4 }],
});

try {
const result = await helpers.validateCustomAnthropicSelection(
"Custom Anthropic endpoint",
"https://anthropic.corp.example",
"model-a",
"COMPATIBLE_ANTHROPIC_API_KEY",
null,
{ intendedApi },
);

expect(result).toMatchObject({
])(
"probes an exactly allowlisted private Anthropic endpoint on its $runtimeSurface surface (#7037)",
async ({ intendedApi, expectedEndpointUrl, expectedProbeOptions }) => {
vi.stubEnv("NEMOCLAW_TRUSTED_PRIVATE_INFERENCE_HOSTS", "anthropic.corp.example");
vi.stubEnv("NEMOCLAW_REASONING", "false");
const probeEndpoint = vi.fn(() => ({
ok: true,
api: intendedApi,
pinnedAddresses: ["10.0.0.8"],
trustedPrivateCapability: {
host: "anthropic.corp.example",
addresses: ["10.0.0.8"],
},
label: "Compatible API",
}));
const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
const log = vi.spyOn(console, "log").mockImplementation(() => {});
const helpers = createInferenceSelectionValidationHelpers({
isNonInteractive: () => false,
agentProductName: () => "NemoClaw agent",
getCredential: () => "test-key",
probeAnthropicEndpoint: probeEndpoint,
probeOpenAiLikeEndpoint: probeEndpoint,
promptValidationRecovery: vi.fn(async () => "selection" as const),
resolveEndpointHost: async () => [{ address: "10.0.0.8", family: 4 }],
});
expect(probeEndpoint).toHaveBeenCalledOnce();
expect(probeEndpoint).toHaveBeenCalledWith(
expectedEndpointUrl,
"model-a",
"test-key",
expect.objectContaining({
...expectedProbeOptions,

try {
const result = await helpers.validateCustomAnthropicSelection(
"Custom Anthropic endpoint",
"https://anthropic.corp.example",
"model-a",
"COMPATIBLE_ANTHROPIC_API_KEY",
null,
{ intendedApi },
);

expect(result).toMatchObject({
ok: true,
api: intendedApi,
pinnedAddresses: ["10.0.0.8"],
trustedPrivateCapability: expect.objectContaining({ addresses: ["10.0.0.8"] }),
}),
);
expect(warn).toHaveBeenCalledWith(expect.stringContaining("operator-trusted private"));
} finally {
log.mockRestore();
warn.mockRestore();
vi.unstubAllEnvs();
}
});
trustedPrivateCapability: {
host: "anthropic.corp.example",
addresses: ["10.0.0.8"],
},
});
expect(probeEndpoint).toHaveBeenCalledOnce();
expect(probeEndpoint).toHaveBeenCalledWith(
expectedEndpointUrl,
"model-a",
"test-key",
expect.objectContaining({
...expectedProbeOptions,
pinnedAddresses: ["10.0.0.8"],
trustedPrivateCapability: expect.objectContaining({ addresses: ["10.0.0.8"] }),
}),
);
expect(warn).toHaveBeenCalledWith(expect.stringContaining("operator-trusted private"));
} finally {
log.mockRestore();
warn.mockRestore();
vi.unstubAllEnvs();
}
},
);

it("honors an exactly allowlisted private endpoint during non-interactive validation (#6861)", async () => {
vi.stubEnv("NEMOCLAW_TRUSTED_PRIVATE_INFERENCE_HOSTS", "llm.corp.example");
Expand Down Expand Up @@ -403,47 +402,46 @@ describe("inference selection validation", () => {
}
});

it.each([
"http://127.0.0.1:8000/v1",
"https://inference.local/v1",
"https://93.184.216.34/v1",
])("carries the approved no-pin capability to probes for %s (#6293)", async (endpointUrl) => {
const probeOpenAiLikeEndpoint = vi.fn(() => ({ ok: true, api: "openai-completions" }));
const resolveEndpointHost = vi.fn(async () => [{ address: "10.0.0.8", family: 4 }]);
const log = vi.spyOn(console, "log").mockImplementation(() => {});
const helpers = createInferenceSelectionValidationHelpers({
isNonInteractive: () => false,
agentProductName: () => "OpenClaw",
getCredential: () => "test-key",
probeOpenAiLikeEndpoint,
promptValidationRecovery: vi.fn(async () => "selection" as const),
resolveEndpointHost,
});
it.each(["http://127.0.0.1:8000/v1", "https://inference.local/v1", "https://93.184.216.34/v1"])(
"carries the approved no-pin capability to probes for %s (#6293)",
async (endpointUrl) => {
const probeOpenAiLikeEndpoint = vi.fn(() => ({ ok: true, api: "openai-completions" }));
const resolveEndpointHost = vi.fn(async () => [{ address: "10.0.0.8", family: 4 }]);
const log = vi.spyOn(console, "log").mockImplementation(() => {});
const helpers = createInferenceSelectionValidationHelpers({
isNonInteractive: () => false,
agentProductName: () => "OpenClaw",
getCredential: () => "test-key",
probeOpenAiLikeEndpoint,
promptValidationRecovery: vi.fn(async () => "selection" as const),
resolveEndpointHost,
});

try {
await expect(
helpers.validateCustomOpenAiLikeSelection(
"Custom endpoint",
try {
await expect(
helpers.validateCustomOpenAiLikeSelection(
"Custom endpoint",
endpointUrl,
"model-a",
"COMPATIBLE_API_KEY",
),
).resolves.toEqual({
ok: true,
api: "openai-completions",
pinnedAddresses: [],
});
expect(probeOpenAiLikeEndpoint).toHaveBeenCalledWith(
endpointUrl,
"model-a",
"COMPATIBLE_API_KEY",
),
).resolves.toEqual({
ok: true,
api: "openai-completions",
pinnedAddresses: [],
});
expect(probeOpenAiLikeEndpoint).toHaveBeenCalledWith(
endpointUrl,
"model-a",
"test-key",
expect.objectContaining({ pinnedAddresses: [] }),
);
expect(resolveEndpointHost).not.toHaveBeenCalled();
} finally {
log.mockRestore();
}
});
"test-key",
expect.objectContaining({ pinnedAddresses: [] }),
);
expect(resolveEndpointHost).not.toHaveBeenCalled();
} finally {
log.mockRestore();
}
},
);

it("exits non-interactively when a custom Anthropic endpoint resolves to link-local metadata, without probing (#6293)", async () => {
const originalExitCode = process.exitCode;
Expand Down
Loading
Loading