Skip to content
Closed
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
5 changes: 3 additions & 2 deletions src/OpenClaw.SetupEngine.UI/Pages/ProgressPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ public sealed partial class ProgressPage : Page
private static readonly (string GroupId, string DisplayName, string[] StepIds)[] StepGroups =
[
("preflight", "Check system and Local AI compatibility", ["validate-distro-path", "preflight-os", "preflight-local-ai-hardware", "preflight-wsl", "preflight-windows-tailscale"]),
("wsl-platform", "Prepare and verify WSL platform", ["ensure-wsl-platform"]),
("local-ai-engine", "Install verified llama-server", ["acquire-local-ai-runtime"]),
("local-ai-model", "Download verified model from Hugging Face", ["acquire-local-ai-model"]),
("local-ai-verify", "Verify Local AI before WSL setup", ["persist-local-ai-manifest", "start-local-ai-runtime", "capture-local-ai-gpu-baseline", "verify-local-ai-inference", "verify-local-ai-gpu-load"]),
("wsl-platform", "Prepare WSL platform", ["ensure-wsl-platform", "configure-local-ai-wsl-networking"]),
("local-ai-verify", "Verify Local AI", ["persist-local-ai-manifest", "start-local-ai-runtime", "capture-local-ai-gpu-baseline", "verify-local-ai-inference", "verify-local-ai-gpu-load"]),
("wsl-networking", "Configure WSL access to Local AI", ["configure-local-ai-wsl-networking"]),
("cleanup", "Removing existing gateway", ["cleanup-distro", "cleanup-gateway"]),
("port", "Checking gateway port", ["preflight-port"]),
("wsl-create", "Installing clean WSL gateway", ["wsl-create"]),
Expand Down
7 changes: 5 additions & 2 deletions src/OpenClaw.SetupEngine/PreflightWslStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public static async Task<WslViabilityResult> InspectAsync(
return new(
WslViabilityKind.Installable,
"WSL is not installed yet.",
"Setup can request administrator approval to install it after Local AI is verified.");
"Setup can request administrator approval to install and verify it before downloading Local AI.");
}

if (LooksTooOldForVersionCommand(versionResult))
Expand Down Expand Up @@ -254,7 +254,10 @@ internal static async Task<StepResult> InstallWslPlatformAsync(SetupContext ctx,
}
}

/// <summary>Performs the first WSL mutation, after native Local AI verification.</summary>
/// <summary>
/// Performs the first WSL mutation after read-only hardware and WSL inspection,
/// before Local AI downloads begin.
/// </summary>
public sealed class EnsureWslPlatformStep : SetupStep
{
private readonly Func<SetupContext, CancellationToken, Task<StepResult>> _installer;
Expand Down
2 changes: 1 addition & 1 deletion src/OpenClaw.SetupEngine/SetupPipeline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public static List<SetupStep> BuildDefaultSteps()
new PreflightLocalAiHardwareStep(),
new PreflightWslStep(),
new PreflightWindowsTailscaleStep(),
new EnsureWslPlatformStep(),
new ReconcileLocalAiInstallationStep(),
new AcquireLocalAiRuntimeStep(),
new AcquireLocalAiModelStep(),
Expand All @@ -65,7 +66,6 @@ public static List<SetupStep> BuildDefaultSteps()
new CaptureLocalAiGpuBaselineStep(),
new VerifyLocalAiInferenceStep(),
new VerifyLocalAiGpuLoadStep(),
new EnsureWslPlatformStep(),
new ConfigureLocalAiWslNetworkingStep(),
new CleanupStaleDistroStep(),
new CleanupStaleGatewayStep(),
Expand Down
24 changes: 15 additions & 9 deletions tests/OpenClaw.SetupEngine.Tests/SetupPipelineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ public void BuildDefaultSteps_IncludesCurrentSetupFlow()
Assert.IsType<PreflightLocalAiHardwareStep>(steps[2]);
Assert.IsType<PreflightWslStep>(steps[3]);
Assert.IsType<PreflightWindowsTailscaleStep>(steps[4]);
Assert.IsType<ReconcileLocalAiInstallationStep>(steps[5]);
Assert.IsType<AcquireLocalAiRuntimeStep>(steps[6]);
Assert.IsType<AcquireLocalAiModelStep>(steps[7]);
Assert.IsType<PersistLocalAiManifestStep>(steps[8]);
Assert.IsType<StartLocalAiRuntimeStep>(steps[9]);
Assert.IsType<CaptureLocalAiGpuBaselineStep>(steps[10]);
Assert.IsType<VerifyLocalAiInferenceStep>(steps[11]);
Assert.IsType<VerifyLocalAiGpuLoadStep>(steps[12]);
Assert.IsType<EnsureWslPlatformStep>(steps[13]);
Assert.IsType<EnsureWslPlatformStep>(steps[5]);
Assert.IsType<ReconcileLocalAiInstallationStep>(steps[6]);
Assert.IsType<AcquireLocalAiRuntimeStep>(steps[7]);
Assert.IsType<AcquireLocalAiModelStep>(steps[8]);
Assert.IsType<PersistLocalAiManifestStep>(steps[9]);
Assert.IsType<StartLocalAiRuntimeStep>(steps[10]);
Assert.IsType<CaptureLocalAiGpuBaselineStep>(steps[11]);
Assert.IsType<VerifyLocalAiInferenceStep>(steps[12]);
Assert.IsType<VerifyLocalAiGpuLoadStep>(steps[13]);
Assert.IsType<ConfigureLocalAiWslNetworkingStep>(steps[14]);
Assert.IsType<CleanupStaleDistroStep>(steps[15]);
Assert.IsType<CleanupStaleGatewayStep>(steps[16]);
Expand All @@ -114,6 +114,12 @@ public void BuildDefaultSteps_IncludesCurrentSetupFlow()
var wizardIndex = steps.FindIndex(s => s is RunGatewayWizardStep);
Assert.IsType<WindowsNodeBootstrapContextStep>(steps[wizardIndex + 1]);
Assert.IsType<StartKeepaliveStep>(steps[^1]);

var ensureWslIndex = steps.FindIndex(step => step is EnsureWslPlatformStep);
var runtimeDownloadIndex = steps.FindIndex(step => step is AcquireLocalAiRuntimeStep);
var modelDownloadIndex = steps.FindIndex(step => step is AcquireLocalAiModelStep);
Assert.True(ensureWslIndex < runtimeDownloadIndex);
Assert.True(ensureWslIndex < modelDownloadIndex);
}

[Fact]
Expand Down
2 changes: 1 addition & 1 deletion tests/OpenClaw.SetupEngine.Tests/SetupStepsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1238,7 +1238,7 @@ args is ["--version"]

Assert.Equal(StepOutcome.Success, result.Outcome);
Assert.Equal(WslViabilityKind.Installable, ctx.WslViability?.Kind);
Assert.Contains("after Local AI is verified", result.Message);
Assert.Contains("before downloading Local AI", result.Message);
Assert.DoesNotContain(commands.Calls, call => call.Arguments.Contains("--install"));
Assert.Single(commands.Calls);
}
Expand Down
17 changes: 17 additions & 0 deletions tests/OpenClaw.Tray.Tests/AppRefactorContractTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,23 @@ public void GatewayInstalledMilestone_ShowsInlineStatusIfWizardCannotStart()
Assert.DoesNotContain("NavigateToWizard();", onBoard);
}

[Fact]
public void SetupProgress_PreparesWslBeforeLocalAiDownloads()
{
var root = TestRepositoryPaths.GetRepositoryRoot();
var code = File.ReadAllText(Path.Combine(root, "src", "OpenClaw.SetupEngine.UI", "Pages", "ProgressPage.xaml.cs"));

AssertInOrder(
code,
"(\"wsl-platform\", \"Prepare and verify WSL platform\", [\"ensure-wsl-platform\"])",
"(\"local-ai-engine\", \"Install verified llama-server\"",
"(\"local-ai-model\", \"Download verified model from Hugging Face\"");
Assert.Contains(
"(\"wsl-networking\", \"Configure WSL access to Local AI\", [\"configure-local-ai-wsl-networking\"])",
code);
Assert.DoesNotContain("Verify Local AI before WSL setup", code);
}

[Fact]
public void SetupCompletion_PersistsStartupChoiceBeforeRestart()
{
Expand Down