-
Notifications
You must be signed in to change notification settings - Fork 2.1k
[codex] Improve desktop startup warmup performance #8013
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ccad92a
5a66372
44629ad
1b5a1e1
20b21f1
e09295c
a0e1010
fa57828
21315cf
55ced61
c66e378
ef64317
bf42950
5ce00cd
e988d73
8a56107
0e59a9e
b689487
fab16b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,10 @@ struct DesktopHomeView: View { | |
| @State private var previousIndexBeforeSettings: Int = 0 | ||
| @State private var logoPulse = false | ||
| @State private var lastActivationRefresh = Date.distantPast | ||
| @State private var didScheduleAgentVMProvisioning = false | ||
| @State private var proactiveMonitoringStartGate = RetryableDelayedStartGate() | ||
| @State private var didScheduleConversationWarmup = false | ||
| @State private var initialFileIndexingBackfill = DelayedFileIndexingBackfillState() | ||
| // Dismiss state for the Neo "no desktop access" banner (resets each launch). | ||
| @State private var neoDesktopBannerDismissed = false | ||
|
|
||
|
|
@@ -145,11 +149,7 @@ struct DesktopHomeView: View { | |
|
|
||
| // For existing users who haven't indexed files yet, run a background scan | ||
| if !UserDefaults.standard.bool(forKey: "hasCompletedFileIndexing") { | ||
| UserDefaults.standard.set(true, forKey: "hasCompletedFileIndexing") | ||
| Task { | ||
| log("DesktopHomeView: Running background file scan for existing user") | ||
| await FileIndexerService.shared.backgroundRescan() | ||
| } | ||
| scheduleInitialFileIndexing() | ||
| } | ||
|
|
||
| let settings = AssistantSettings.shared | ||
|
|
@@ -162,6 +162,7 @@ struct DesktopHomeView: View { | |
| appState.startTranscription() | ||
| } else { | ||
| log("DesktopHomeView: Deferring transcription — API keys not yet loaded") | ||
| Task { await APIKeyService.shared.waitForKeys() } | ||
| } | ||
| } else if !settings.transcriptionEnabled { | ||
| log("DesktopHomeView: Transcription disabled in settings, skipping auto-start") | ||
|
|
@@ -188,15 +189,7 @@ struct DesktopHomeView: View { | |
| // If API keys aren't loaded yet, this may fail — onChange below retries. | ||
| if settings.screenAnalysisEnabled { | ||
| if APIKeyService.keysAvailable { | ||
| ProactiveAssistantsPlugin.shared.startMonitoring { success, error in | ||
| if success { | ||
| log("DesktopHomeView: Screen analysis started") | ||
| } else { | ||
| log( | ||
| "DesktopHomeView: Screen analysis failed to start: \(error ?? "unknown") — setting remains enabled for next launch" | ||
| ) | ||
| } | ||
| } | ||
| scheduleProactiveMonitoringStart(reason: "launch") | ||
| } else { | ||
| log( | ||
| "DesktopHomeView: Deferring screen analysis — API keys not yet loaded" | ||
|
|
@@ -207,7 +200,7 @@ struct DesktopHomeView: View { | |
| } | ||
|
|
||
| // Start Crisp chat in background for notifications | ||
| CrispManager.shared.start() | ||
| CrispManager.shared.start(initialPollDelay: StartupWarmupPolicy.crispInitialPollDelay) | ||
|
|
||
| // Set up floating control bar (only show if user hasn't disabled it) | ||
| FloatingControlBarManager.shared.setup( | ||
|
|
@@ -223,14 +216,9 @@ struct DesktopHomeView: View { | |
| } | ||
| .task { | ||
| // Trigger eager data loading when main content appears | ||
| // Load conversations/folders in parallel with other data | ||
| async let vmLoad: Void = viewModelContainer.loadAllData() | ||
| async let conversations: Void = appState.loadConversations() | ||
| async let folders: Void = appState.loadFolders() | ||
| _ = await (vmLoad, conversations, folders) | ||
|
|
||
| // Backend-based check: ensure user has a cloud agent VM | ||
| await AgentVMService.shared.ensureProvisioned() | ||
| await viewModelContainer.loadAllData() | ||
| scheduleConversationWarmup() | ||
| scheduleAgentVMProvisioning() | ||
| } | ||
| // Refresh conversations when app becomes active (e.g. switching back from another app) | ||
| .onReceive( | ||
|
|
@@ -249,8 +237,8 @@ struct DesktopHomeView: View { | |
| if AssistantSettings.shared.screenAnalysisEnabled && !plugin.isMonitoring { | ||
| plugin.refreshScreenRecordingPermission() | ||
| if plugin.hasScreenRecordingPermission { | ||
| log("DesktopHomeView: Permission available on app active — starting monitoring") | ||
| plugin.startMonitoring { _, _ in } | ||
| log("DesktopHomeView: Permission available on app active — scheduling monitoring") | ||
| scheduleProactiveMonitoringStart(reason: "app active") | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -265,15 +253,7 @@ struct DesktopHomeView: View { | |
| // Retry screen analysis | ||
| let plugin = ProactiveAssistantsPlugin.shared | ||
| if AssistantSettings.shared.screenAnalysisEnabled && !plugin.isMonitoring { | ||
| plugin.startMonitoring { success, error in | ||
| if success { | ||
| log("DesktopHomeView: Screen analysis started (after key load)") | ||
| } else { | ||
| log( | ||
| "DesktopHomeView: Screen analysis retry failed: \(error ?? "unknown")" | ||
| ) | ||
| } | ||
| } | ||
| scheduleProactiveMonitoringStart(reason: "key load") | ||
| } | ||
| } | ||
| // Cmd+R: refresh all data (conversations, chat, tasks, memories) | ||
|
|
@@ -289,6 +269,18 @@ struct DesktopHomeView: View { | |
| log( | ||
| "DesktopHomeView: userDidSignOut — resetting hasCompletedOnboarding and stopping transcription" | ||
| ) | ||
| viewModelContainer.resetStartupState() | ||
| didScheduleConversationWarmup = false | ||
| didScheduleAgentVMProvisioning = false | ||
| appState.conversations = [] | ||
| appState.folders = [] | ||
| appState.selectedFolderId = nil | ||
| appState.selectedDateFilter = nil | ||
| appState.showStarredOnly = false | ||
| appState.totalConversationsCount = nil | ||
| appState.conversationsError = nil | ||
| appState.isLoadingConversations = false | ||
| appState.isLoadingFolders = false | ||
| appState.hasCompletedOnboarding = false | ||
| appState.stopTranscription() | ||
| } | ||
|
|
@@ -565,7 +557,7 @@ struct DesktopHomeView: View { | |
| updatedAt: ISO8601DateFormatter().string(from: Date()) | ||
| ) | ||
|
|
||
| Task { | ||
| Task { @MainActor in | ||
| await DesktopAutomationStateStore.shared.update(snapshot) | ||
| } | ||
| } | ||
|
|
@@ -653,6 +645,139 @@ struct DesktopHomeView: View { | |
| } | ||
| } | ||
|
|
||
| private func scheduleAgentVMProvisioning() { | ||
| guard !didScheduleAgentVMProvisioning else { return } | ||
| didScheduleAgentVMProvisioning = true | ||
|
|
||
| Task { @MainActor in | ||
| try? await Task.sleep( | ||
| nanoseconds: UInt64(StartupWarmupPolicy.agentVMProvisioningDelay * 1_000_000_000) | ||
| ) | ||
| guard !Task.isCancelled else { | ||
| didScheduleAgentVMProvisioning = false | ||
| return | ||
| } | ||
| guard await AuthState.shared.isSignedIn else { | ||
| didScheduleAgentVMProvisioning = false | ||
| return | ||
| } | ||
| await AgentVMService.shared.ensureProvisioned() | ||
| } | ||
| } | ||
|
|
||
| private func scheduleConversationWarmup() { | ||
| guard !didScheduleConversationWarmup else { return } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
After a successful startup this flag stays true, while the sign-out handler below does not clear Useful? React with 👍 / 👎. |
||
| didScheduleConversationWarmup = true | ||
|
|
||
| Task { @MainActor in | ||
| try? await Task.sleep( | ||
| nanoseconds: UInt64(StartupWarmupPolicy.conversationWarmupDelay * 1_000_000_000) | ||
| ) | ||
| guard !Task.isCancelled else { | ||
| didScheduleConversationWarmup = false | ||
| return | ||
| } | ||
| guard await AuthState.shared.isSignedIn else { | ||
| didScheduleConversationWarmup = false | ||
| return | ||
| } | ||
|
|
||
| async let conversations: Void = loadConversationsIfNeeded() | ||
| async let folders: Void = loadFoldersIfNeeded() | ||
| _ = await (conversations, folders) | ||
| } | ||
| } | ||
|
|
||
| private func loadConversationsIfNeeded() async { | ||
| guard appState.conversations.isEmpty else { return } | ||
| await appState.loadConversations() | ||
| } | ||
|
|
||
| private func loadFoldersIfNeeded() async { | ||
| guard appState.folders.isEmpty else { return } | ||
| await appState.loadFolders() | ||
| } | ||
|
|
||
| private func scheduleInitialFileIndexing() { | ||
| guard | ||
| initialFileIndexingBackfill.reserveIfNeeded( | ||
| hasCompletedBackfill: UserDefaults.standard.bool(forKey: "hasCompletedFileIndexing")) | ||
| else { return } | ||
|
|
||
| Task { @MainActor in | ||
| try? await Task.sleep( | ||
| nanoseconds: UInt64(StartupWarmupPolicy.initialFileIndexingDelay * 1_000_000_000) | ||
| ) | ||
| guard !Task.isCancelled else { | ||
| initialFileIndexingBackfill.releaseReservation() | ||
| return | ||
| } | ||
| guard await AuthState.shared.isSignedIn else { | ||
| initialFileIndexingBackfill.releaseReservation() | ||
| return | ||
| } | ||
| log("DesktopHomeView: Running delayed background file scan for existing user") | ||
| await FileIndexerService.shared.backgroundRescan() | ||
| guard !Task.isCancelled else { | ||
| initialFileIndexingBackfill.releaseReservation() | ||
| return | ||
| } | ||
| guard await AuthState.shared.isSignedIn else { | ||
| initialFileIndexingBackfill.releaseReservation() | ||
| return | ||
| } | ||
| initialFileIndexingBackfill.markScanCompleted() | ||
| if initialFileIndexingBackfill.shouldMarkComplete { | ||
| UserDefaults.standard.set(true, forKey: "hasCompletedFileIndexing") | ||
| log( | ||
| "DesktopHomeView: Marked existing-user file indexing backfill complete after background scan returned" | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private func scheduleProactiveMonitoringStart(reason: String) { | ||
| guard proactiveMonitoringStartGate.reserve() else { return } | ||
|
|
||
| Task { @MainActor in | ||
| try? await Task.sleep( | ||
| nanoseconds: UInt64(StartupWarmupPolicy.proactiveAssistantsStartDelay * 1_000_000_000) | ||
| ) | ||
| guard !Task.isCancelled else { | ||
| proactiveMonitoringStartGate.finishAttempt() | ||
| return | ||
| } | ||
| guard await AuthState.shared.isSignedIn else { | ||
| proactiveMonitoringStartGate.finishAttempt() | ||
| return | ||
| } | ||
|
|
||
| let plugin = ProactiveAssistantsPlugin.shared | ||
| guard AssistantSettings.shared.screenAnalysisEnabled, !plugin.isMonitoring else { | ||
| proactiveMonitoringStartGate.finishAttempt() | ||
| return | ||
| } | ||
| guard APIKeyService.keysAvailable else { | ||
| proactiveMonitoringStartGate.finishAttempt() | ||
| log("DesktopHomeView: Screen analysis still deferred after \(reason) — API keys not yet loaded") | ||
| return | ||
| } | ||
|
|
||
| plugin.startMonitoring { success, error in | ||
| Task { @MainActor in | ||
| proactiveMonitoringStartGate.finishAttempt() | ||
| if success { | ||
| log("DesktopHomeView: Screen analysis started (\(reason), delayed)") | ||
| } else { | ||
| log( | ||
| "DesktopHomeView: Screen analysis failed to start (\(reason)): \(error ?? "unknown") — setting remains enabled for next launch" | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private func updateStoreActivity(for index: Int) { | ||
| viewModelContainer.tasksStore.isActive = | ||
| index == SidebarNavItem.dashboard.rawValue || index == SidebarNavItem.tasks.rawValue | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.