Files
clawdbot/apps/macos/Sources/Clawdis/OnboardingView+Monitoring.swift
2025-12-24 19:29:27 +01:00

136 lines
4.6 KiB
Swift

import ClawdisIPC
import Foundation
extension OnboardingView {
@MainActor
func refreshPerms() async {
await self.permissionMonitor.refreshNow()
}
@MainActor
func request(_ cap: Capability) async {
guard !self.isRequesting else { return }
self.isRequesting = true
defer { isRequesting = false }
_ = await PermissionManager.ensure([cap], interactive: true)
await self.refreshPerms()
}
func updatePermissionMonitoring(for pageIndex: Int) {
let shouldMonitor = pageIndex == self.permissionsPageIndex
if shouldMonitor, !self.monitoringPermissions {
self.monitoringPermissions = true
PermissionMonitor.shared.register()
} else if !shouldMonitor, self.monitoringPermissions {
self.monitoringPermissions = false
PermissionMonitor.shared.unregister()
}
}
func updateDiscoveryMonitoring(for pageIndex: Int) {
let isConnectionPage = pageIndex == self.connectionPageIndex
let shouldMonitor = isConnectionPage
if shouldMonitor, !self.monitoringDiscovery {
self.monitoringDiscovery = true
Task { @MainActor in
try? await Task.sleep(nanoseconds: 550_000_000)
guard self.monitoringDiscovery else { return }
self.gatewayDiscovery.start()
await self.refreshLocalGatewayProbe()
}
} else if !shouldMonitor, self.monitoringDiscovery {
self.monitoringDiscovery = false
self.gatewayDiscovery.stop()
}
}
func updateMonitoring(for pageIndex: Int) {
self.updatePermissionMonitoring(for: pageIndex)
self.updateDiscoveryMonitoring(for: pageIndex)
self.updateAuthMonitoring(for: pageIndex)
self.maybeKickoffOnboardingChat(for: pageIndex)
}
func stopPermissionMonitoring() {
guard self.monitoringPermissions else { return }
self.monitoringPermissions = false
PermissionMonitor.shared.unregister()
}
func stopDiscovery() {
guard self.monitoringDiscovery else { return }
self.monitoringDiscovery = false
self.gatewayDiscovery.stop()
}
func updateAuthMonitoring(for pageIndex: Int) {
let shouldMonitor = pageIndex == self.anthropicAuthPageIndex && self.state.connectionMode == .local
if shouldMonitor, !self.monitoringAuth {
self.monitoringAuth = true
self.startAuthMonitoring()
} else if !shouldMonitor, self.monitoringAuth {
self.stopAuthMonitoring()
}
}
func startAuthMonitoring() {
self.refreshAnthropicOAuthStatus()
self.authMonitorTask?.cancel()
self.authMonitorTask = Task {
while !Task.isCancelled {
await MainActor.run { self.refreshAnthropicOAuthStatus() }
try? await Task.sleep(nanoseconds: 1_000_000_000)
}
}
}
func stopAuthMonitoring() {
self.monitoringAuth = false
self.authMonitorTask?.cancel()
self.authMonitorTask = nil
}
func installCLI() async {
guard !self.installingCLI else { return }
self.installingCLI = true
defer { installingCLI = false }
await CLIInstaller.install { message in
await MainActor.run { self.cliStatus = message }
}
self.refreshCLIStatus()
}
func refreshCLIStatus() {
let installLocation = CLIInstaller.installedLocation()
self.cliInstallLocation = installLocation
self.cliInstalled = installLocation != nil
}
func refreshLocalGatewayProbe() async {
let port = GatewayEnvironment.gatewayPort()
let desc = await PortGuardian.shared.describe(port: port)
await MainActor.run {
guard let desc else {
self.localGatewayProbe = nil
return
}
let command = desc.command.trimmingCharacters(in: .whitespacesAndNewlines)
let expectedTokens = ["node", "clawdis", "tsx", "pnpm", "bun"]
let lower = command.lowercased()
let expected = expectedTokens.contains { lower.contains($0) }
self.localGatewayProbe = LocalGatewayProbe(
port: port,
pid: desc.pid,
command: command,
expected: expected)
}
}
func refreshAnthropicOAuthStatus() {
_ = ClawdisOAuthStore.importLegacyAnthropicOAuthIfNeeded()
let status = ClawdisOAuthStore.anthropicOAuthStatus()
self.anthropicAuthDetectedStatus = status
self.anthropicAuthConnected = status.isConnected
}
}