mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 20:35:39 -06:00
fix(macos): surface unsaved gateway settings during onboarding (#129959)
This commit is contained in:
committed by
GitHub
parent
144e4d5aeb
commit
d2360e4a1c
@@ -13,7 +13,9 @@ extension OnboardingAISetupModel {
|
||||
return issue
|
||||
}
|
||||
|
||||
func showConfiguredGatewayProbeUnavailable() {
|
||||
func showConfiguredGatewayProbeUnavailable(
|
||||
summary: String = "The Gateway did not answer the inference check. Nothing was changed.")
|
||||
{
|
||||
guard !self.ownsInferenceTransition ||
|
||||
self.configuredGatewayBlocker != nil ||
|
||||
self.waitingForPendingActivationDeadline
|
||||
@@ -24,9 +26,7 @@ extension OnboardingAISetupModel {
|
||||
self.updateConfiguredGatewayBlockerState(
|
||||
.unavailable,
|
||||
phase: .ready,
|
||||
detectError: Failure(
|
||||
summary: "The Gateway did not answer the inference check. Nothing was changed.",
|
||||
detail: nil))
|
||||
detectError: Failure(summary: summary, detail: nil))
|
||||
}
|
||||
|
||||
func showConfiguredGatewayAuthIssue(_ issue: RemoteGatewayAuthIssue) {
|
||||
|
||||
@@ -155,7 +155,11 @@ extension OnboardingView {
|
||||
guard !configuredGatewayProbe.isSuppressedForTemporaryConnectionCheck else { return nil }
|
||||
// Persist the latest selection before GatewayEndpointStore resolves the
|
||||
// route, so an immediate probe cannot attach to the previous endpoint.
|
||||
guard gatewaySelectionPersister() else { return nil }
|
||||
guard gatewaySelectionPersister() else {
|
||||
self.aiSetup.showConfiguredGatewayProbeUnavailable(
|
||||
summary: "Could not save Gateway settings. Check your connection settings and try again.")
|
||||
return nil
|
||||
}
|
||||
let expectedMode = state.connectionMode
|
||||
let expectedRouteIdentity = self.aiSetupRouteIdentityProvider()
|
||||
let expectedPendingState = OnboardingSystemAgentResumeStore.pendingState(
|
||||
|
||||
@@ -750,7 +750,8 @@ private func rejectedSetupVerificationResponse(id: String) -> Data {
|
||||
|
||||
private func unconfiguredSetupVerificationResponse(id: String) -> Data {
|
||||
Data(
|
||||
#"{"type":"res","id":"\#(id)","ok":true,"payload":{"ok":false,"status":"unavailable","error":"No agent model is configured."}}"#.utf8)
|
||||
#"{"type":"res","id":"\#(id)","ok":true,"payload":{"ok":false,"status":"unavailable","error":"No agent model is configured."}}"#
|
||||
.utf8)
|
||||
}
|
||||
|
||||
private func unavailableGatewayResponse(id: String) -> Data {
|
||||
@@ -2243,21 +2244,30 @@ struct OnboardingAISetupTests {
|
||||
#expect(harness.session.latestTask()?.snapshotSendCount() == 1)
|
||||
}
|
||||
|
||||
@Test func `configured gateway probe refuses an unpersisted endpoint selection`() async throws {
|
||||
@Test(arguments: [false, true])
|
||||
func `configured gateway probe refuses an unpersisted endpoint selection`(remote: Bool) async throws {
|
||||
let url = try #require(URL(string: "ws://localhost:18789"))
|
||||
let harness = AISetupHarness(url: url) { _, request, _ in configuredModelResponse(id: request.id) }
|
||||
let harness = AISetupHarness(url: url) { _, request, _ in
|
||||
switch request.method {
|
||||
case "agents.list": missingConfiguredModelResponse(id: request.id)
|
||||
case "openclaw.setup.detect": detectedSetupResponse(id: request.id)
|
||||
default: nil
|
||||
}
|
||||
}
|
||||
let appState = AppState(preview: true)
|
||||
appState.connectionMode = .remote
|
||||
appState.remoteTransport = .direct
|
||||
appState.remoteUrl = "wss://replacement.example.test"
|
||||
appState.connectionMode = remote ? .remote : .local
|
||||
if remote {
|
||||
appState.remoteTransport = .direct
|
||||
appState.remoteUrl = "wss://replacement.example.test"
|
||||
}
|
||||
var persistAttempts = 0
|
||||
let view = makeAISetupView(
|
||||
state: appState,
|
||||
gateway: harness.gateway,
|
||||
routeIdentityProvider: { "remote:direct:replacement.example.test" },
|
||||
routeIdentityProvider: { remote ? "remote:direct:replacement.example.test" : "local" },
|
||||
gatewaySelectionPersister: {
|
||||
persistAttempts += 1
|
||||
return false
|
||||
return persistAttempts > 2
|
||||
})
|
||||
view.onboardingVisible = true
|
||||
|
||||
@@ -2268,6 +2278,27 @@ struct OnboardingAISetupTests {
|
||||
#expect(persistAttempts == 1)
|
||||
#expect(harness.session.snapshotMakeCount() == 0)
|
||||
#expect(!view.aiSetup.connected)
|
||||
#expect(view.aiSetup.phase == .ready)
|
||||
#expect(view.aiSetup.configuredGatewayProbeUnavailable)
|
||||
#expect(view.aiSetup.detectError?.summary ==
|
||||
"Could not save Gateway settings. Check your connection settings and try again.")
|
||||
|
||||
#expect(view.retryConfiguredGatewayProbe() == nil)
|
||||
#expect(persistAttempts == 2)
|
||||
#expect(harness.session.snapshotMakeCount() == 0)
|
||||
#expect(view.aiSetup.phase == .ready)
|
||||
#expect(view.aiSetup.configuredGatewayProbeUnavailable)
|
||||
|
||||
let retry = try #require(view.retryConfiguredGatewayProbe())
|
||||
await retry.value
|
||||
let requests = await waitForAISetupRequests(harness.recorder, count: 2)
|
||||
await settleQueuedAISetupTasks()
|
||||
|
||||
#expect(persistAttempts == 3)
|
||||
#expect(requests.methods == ["agents.list", "openclaw.setup.detect"])
|
||||
#expect(view.aiSetup.phase == .ready)
|
||||
#expect(!view.aiSetup.configuredGatewayProbeUnavailable)
|
||||
#expect(!view.aiSetup.candidates.isEmpty)
|
||||
}
|
||||
|
||||
@Test func `read only configured gateway retry does not own inference transition`() {
|
||||
@@ -3072,16 +3103,16 @@ struct OnboardingAISetupTests {
|
||||
let harness = AISetupHarness(url: url) { _, request, _ in
|
||||
switch request.method {
|
||||
case "openclaw.setup.detect":
|
||||
return selectableCandidatesDetectedSetupResponse(id: request.id)
|
||||
selectableCandidatesDetectedSetupResponse(id: request.id)
|
||||
case "openclaw.setup.activate" where attempts.claim() < 2:
|
||||
return failedActivationResponse(id: request.id)
|
||||
failedActivationResponse(id: request.id)
|
||||
case "openclaw.setup.activate":
|
||||
return successfulActivationResponse(
|
||||
successfulActivationResponse(
|
||||
id: request.id,
|
||||
modelRef: "openai/gpt-5.5",
|
||||
latencyMs: 120)
|
||||
default:
|
||||
return nil
|
||||
nil
|
||||
}
|
||||
}
|
||||
let model = harness.model(defaults: defaults)
|
||||
|
||||
Reference in New Issue
Block a user