Skip to content
Merged
2 changes: 1 addition & 1 deletion ci/test-file-size-budget.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"test/generate-openclaw-config.test.ts": 1907,
"test/install-preflight.test.ts": 3025,
"test/nemoclaw-start.test.ts": 4671,
"test/onboard-messaging.test.ts": 2033,
"test/onboard-messaging.test.ts": 2028,
"test/onboard-selection.test.ts": 4177
}
}
43 changes: 0 additions & 43 deletions src/lib/onboard/created-sandbox-finalization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { afterEach, describe, expect, it, vi } from "vitest";
import type { SandboxEntry } from "../state/registry";
import * as sandboxState from "../state/sandbox";
import {
completeOrdinaryOnboardSandboxCreation,
createCreatedSandboxCompletionActions,
createOnboardCreatedSandboxCompletion,
finalizeCreatedSandbox,
Expand All @@ -23,48 +22,6 @@ import type { CreatedSandboxRegistrationInput } from "./sandbox-registration";

const fixtures: string[] = [];

describe("ordinary sandbox completion", () => {
it("republishes attached provider state after Docker recreation without credential flags", () => {
const runOpenshell = vi.fn(
(_args: string[], _options: { ignoreError: true; suppressOutput: true }) => ({
status: 0,
stdout: "",
stderr: "",
}),
);
const setDefault = vi.fn();

expect(
completeOrdinaryOnboardSandboxCreation(
{
sandboxName: "alpha",
sandboxWasLiveDefault: false,
runtimeFields: { openshellDriver: "docker" } as SandboxEntry,
messagingProviders: ["alpha-slack", "alpha-slack"],
inferenceProvider: "compatible-endpoint",
liveExists: true,
},
{
setDefault,
runFile: vi.fn(),
scriptsDir: "/tmp/scripts",
gatewayName: "nemoclaw",
providerExistsInGateway: () => true,
runOpenshell,
armCancelRollback: vi.fn(),
dockerInfoFormat: vi.fn(() => "true"),
runCapture: vi.fn(() => ""),
},
),
).toBe("alpha");
expect(runOpenshell.mock.calls.map(([args]) => args)).toEqual([
["provider", "update", "-g", "nemoclaw", "compatible-endpoint"],
["provider", "update", "-g", "nemoclaw", "alpha-slack"],
]);
expect(runOpenshell.mock.calls.flat(2)).not.toContain("--credential");
});
});

afterEach(() => {
delete process.env.NEMOCLAW_OPENSHELL_BIN;
for (const fixture of fixtures.splice(0)) fs.rmSync(fixture, { recursive: true, force: true });
Expand Down
31 changes: 0 additions & 31 deletions src/lib/onboard/created-sandbox-finalization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ export function completeOrdinaryOnboardSandboxCreation(
readonly sandboxWasLiveDefault: boolean;
readonly runtimeFields: RegistrationSeed["runtimeFields"];
readonly messagingProviders: readonly string[];
readonly inferenceProvider: string | null;
readonly liveExists: boolean;
},
deps: {
Expand All @@ -230,14 +229,6 @@ export function completeOrdinaryOnboardSandboxCreation(
readonly scriptsDir: string;
readonly gatewayName: string;
readonly providerExistsInGateway: (providerName: string) => boolean;
readonly runOpenshell: (
args: string[],
options: { ignoreError: true; suppressOutput: true },
) => {
status: number | null;
stdout?: string | Buffer | null;
stderr?: string | Buffer | null;
};
readonly armCancelRollback: (sandboxName: string) => void;
readonly dockerInfoFormat: Parameters<typeof warnIfLandlockUnsupported>[0]["dockerInfoFormat"];
readonly runCapture: Parameters<typeof warnIfLandlockUnsupported>[0]["runCapture"];
Expand All @@ -253,28 +244,6 @@ export function completeOrdinaryOnboardSandboxCreation(
);
}
applyOnboardVmDnsMonkeypatch(input.sandboxName, input.runtimeFields);
if (input.runtimeFields.openshellDriver === "docker") {
const attachedProviders = new Set(
[input.inferenceProvider, ...input.messagingProviders].filter(
(provider): provider is string => Boolean(provider),
),
);
for (const provider of attachedProviders) {
if (!deps.providerExistsInGateway(provider)) continue;
const refreshed = deps.runOpenshell(
["provider", "update", "-g", deps.gatewayName, provider],
{
ignoreError: true,
suppressOutput: true,
},
);
if (refreshed.status !== 0) {
throw new Error(
`OpenShell did not republish attached provider '${provider}' after Docker sandbox recreation.`,
);
}
}
}
for (const provider of input.messagingProviders) {
if (!deps.providerExistsInGateway(provider)) printMessagingProviderMissing(provider);
}
Expand Down
64 changes: 62 additions & 2 deletions src/lib/onboard/sandbox-create/orchestration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,51 @@ export async function completeHermesPortableSandboxRegistration(input: {
return registered;
}

function publishAttachedProvidersBeforeDockerSandboxCreation(
input: {
readonly openshellDriver: SandboxEntry["openshellDriver"];
readonly inferenceProvider: string | null;
readonly messagingProviders: readonly string[];
readonly extraProviders: readonly string[];
readonly gatewayName: string;
},
deps: Pick<SandboxCreateOrchestrationRuntime, "providerExistsInGateway" | "runOpenshell"> & {
readonly cleanupCreateSources: () => void;
},
): void {
if (input.openshellDriver === "docker") {
const providersRequiringExistenceProbe = new Set(
[input.inferenceProvider, ...input.messagingProviders].filter(
(provider): provider is string => Boolean(provider),
),
);
const attachedProviders = new Set([
...providersRequiringExistenceProbe,
...input.extraProviders,
]);
for (const attachedProvider of attachedProviders) {
if (
providersRequiringExistenceProbe.has(attachedProvider) &&
!deps.providerExistsInGateway(attachedProvider)
)
continue;
const refreshed = deps.runOpenshell(
["provider", "update", "-g", input.gatewayName, attachedProvider],
{
ignoreError: true,
suppressOutput: true,
},
);
if (refreshed.status !== 0) {
deps.cleanupCreateSources();
throw new Error(
`OpenShell did not publish attached provider '${attachedProvider}' before Docker sandbox creation.`,
);
}
}
}
}

type ApplyRecreatePolicyCarryForward = (
sandboxName: string,
nonInteractive: boolean,
Expand Down Expand Up @@ -1238,6 +1283,23 @@ export function createSandboxWithBaseImageResolution(runtime: SandboxCreateOrche
});
cleanupBuildContext();
} else {
publishAttachedProvidersBeforeDockerSandboxCreation(
{
openshellDriver: sandboxRuntimeFields.openshellDriver,
inferenceProvider: resolvedCreateIntent.inferenceProvider,
messagingProviders,
extraProviders: resolvedCreateIntent.extraProviders,
gatewayName: GATEWAY_NAME,
},
{
providerExistsInGateway,
runOpenshell,
cleanupCreateSources: () => {
cleanupInitialCreateSource();
cleanupBuildContext();
},
},
);
const created = await runCreateFlow(createArgv);
cleanupInitialCreateSource();
await completeCreatedSandboxRegistration(created, null);
Expand All @@ -1251,7 +1313,6 @@ export function createSandboxWithBaseImageResolution(runtime: SandboxCreateOrche
sandboxWasLiveDefault,
runtimeFields: sandboxRuntimeFields,
messagingProviders,
inferenceProvider: provider,
liveExists,
},
{
Expand All @@ -1260,7 +1321,6 @@ export function createSandboxWithBaseImageResolution(runtime: SandboxCreateOrche
scriptsDir: SCRIPTS,
gatewayName: GATEWAY_NAME,
providerExistsInGateway,
runOpenshell,
armCancelRollback: sandboxCancelRollback.arm,
dockerInfoFormat,
runCapture,
Expand Down
Loading
Loading