Files
openclaw/apps/macos/Sources/OpenClaw/OnboardingView+Actions.swift
T
Peter Steinberger 2bc50d0656 feat: verify AI access during macOS onboarding before the first chat (#100288)
* feat(crestodian): add live-tested structured inference setup (detect/activate gateway RPCs)

* feat(macos): redesign onboarding around a verified Connect-your-AI step

* docs: describe the verified AI onboarding step and gemini setup ladder entry

* chore(macos): drop replaced OnboardingView+CrestodianSetup source

* fix(macos): keep the AI-detect error card from pairing with an unproven empty-state claim

* chore(protocol): regenerate Swift gateway models for crestodian.setup methods

* test(crestodian): give setup-inference mocks explicit params for test-types lane

* chore(i18n): sync native app string inventory for onboarding redesign

* chore(i18n): sync native app string inventory for onboarding redesign
2026-07-05 06:59:30 -07:00

84 lines
2.7 KiB
Swift

import AppKit
import Foundation
import OpenClawDiscovery
import OpenClawIPC
import SwiftUI
extension OnboardingView {
func selectLocalGateway() {
self.defaultsToLocalGateway = false
self.state.connectionMode = .local
self.preferredGatewayID = nil
self.showAdvancedConnection = false
self.showRemoteChoices = false
GatewayDiscoveryPreferences.setPreferredStableID(nil)
}
func selectUnconfiguredGateway() {
self.defaultsToLocalGateway = false
self.state.connectionMode = .unconfigured
self.preferredGatewayID = nil
self.showAdvancedConnection = false
self.showRemoteChoices = false
GatewayDiscoveryPreferences.setPreferredStableID(nil)
}
func selectRemoteGateway(_ gateway: GatewayDiscoveryModel.DiscoveredGateway) {
self.defaultsToLocalGateway = false
self.preferredGatewayID = gateway.stableID
GatewayDiscoveryPreferences.setPreferredStableID(gateway.stableID)
GatewayDiscoverySelectionSupport.applyRemoteSelection(gateway: gateway, state: self.state)
self.state.connectionMode = .remote
MacNodeModeCoordinator.shared.setPreferredGatewayStableID(gateway.stableID)
}
func openSettings(tab: SettingsTab) {
AppNavigationActions.openSettings(tab: tab)
}
func handleBack() {
withAnimation {
self.currentPage = max(0, self.currentPage - 1)
}
}
func handleNext() {
// All callers (Next button, chat handoff) honor the same page gates.
guard self.canAdvance else { return }
self.commitRecommendedConnectionIfNeeded(for: self.activePageIndex)
if self.currentPage < self.pageCount - 1 {
withAnimation { self.currentPage += 1 }
} else {
self.finish()
}
}
func commitRecommendedConnectionIfNeeded(for pageIndex: Int) {
if pageIndex == self.connectionPageIndex,
self.defaultsToLocalGateway,
self.state.connectionMode == .unconfigured
{
self.selectLocalGateway()
}
}
func finish() {
OnboardingController.markComplete()
OnboardingController.shared.close()
// Land people in the real conversation, not on an empty desktop: the
// agent chat is the product, and it is verified working by now.
if self.state.connectionMode != .unconfigured {
AppNavigationActions.openChat()
}
}
func copyToPasteboard(_ text: String) {
let pb = NSPasteboard.general
pb.clearContents()
pb.setString(text, forType: .string)
self.copied = true
DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) { self.copied = false }
}
}