nvrsion: Add: Advanced Setting VM to Virtual Machines settings, including “Always open VM guest display” option, in Panels, Settings, and Project.

Nucleic-Promote: 1
Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
2026-07-08 00:13:59 -07:00
co-authored by nucleic
parent f75259261e
commit efab9d4b5e
3 changed files with 48 additions and 0 deletions
@@ -68,6 +68,9 @@ struct PaneledChatView: View {
// selection when the chat changes so the Editor never shows another
// worktree's file.
.onChange(of: session?.id) { _, _ in fileSelection.clear() }
// With "Always open VM guest display" on, surface the guest-screen monitor as soon as the
// open chat has a booted macOS VM regardless of how the VM was launched.
.task(id: session?.id) { await watchGuestDisplay() }
.alert("Save Layout", isPresented: $savingLayout) {
TextField("Layout name", text: $layoutNameDraft)
Button("Cancel", role: .cancel) {}
@@ -176,6 +179,25 @@ struct PaneledChatView: View {
onDrop: { panels.drop($0, into: slot) })
}
// MARK: - Guest display
/// While a chat is open, watch its macOS VM and when the user has enabled "Always open VM guest
/// display" reveal the VM monitor as soon as the guest boots, whatever launched it (`mac_vm_exec`,
/// `mac_vm_computer`, or provisioning). `revealVMMonitor()` is idempotent (a no-op once a monitor is
/// placed, and the panel re-roots onto the open chat), so polling and re-revealing is safe; the loop
/// re-reads the setting each tick so flipping it on takes effect without reopening the chat.
private func watchGuestDisplay() async {
guard store.macVMSupported, let session else { return }
let vmName = MacVMManager.vmName(for: session.id)
while !Task.isCancelled {
if MacVMSettings.alwaysOpenGuestDisplay,
await store.runningMacVMs().contains(where: { $0.name == vmName }) {
panels.revealVMMonitor()
}
try? await Task.sleep(for: .seconds(2))
}
}
// MARK: - Sizing
private func widthRange(_ container: CGSize) -> ClosedRange<CGFloat> {
+13
View File
@@ -460,6 +460,7 @@ private struct MacVMSettingsTab: View {
@AppStorage(MacVMSettings.exposeByDefaultKey) private var exposeByDefault = true
@AppStorage(MacVMSettings.computerUseByDefaultKey) private var computerUseByDefault = true
@AppStorage(MacVMSettings.axAgentEnabledKey) private var axAgentEnabled = false
@AppStorage(MacVMSettings.alwaysOpenGuestDisplayKey) private var alwaysOpenGuestDisplay = false
@AppStorage(MacVMSettings.basePrebuiltPathKey) private var basePrebuiltPath = ""
@AppStorage(MacVMSettings.restoreImagePathKey) private var restoreImagePath = ""
@AppStorage(MacVMSettings.restoreImageURLKey) private var restoreImageURL = ""
@@ -483,6 +484,8 @@ private struct MacVMSettingsTab: View {
/// Whether the "Advanced" restore-source overrides are expanded. Driven open by picking the
/// "Custom" base-version option (or by finding a manual override already stored on appearance).
@State private var advancedExpanded = false
/// Whether the "Advanced" power-user toggles under the service section are expanded.
@State private var serviceAdvancedExpanded = false
private var supported: Bool { store.macVMSupported }
@@ -524,6 +527,16 @@ private struct MacVMSettingsTab: View {
LearnMoreLink("Set up AX-based computer use", url: SupportURL.macVMAXAgent)
}
}
DisclosureGroup("Advanced", isExpanded: $serviceAdvancedExpanded) {
Toggle("Always open VM guest display", isOn: $alwaysOpenGuestDisplay)
.disabled(!serviceEnabled || !supported)
Text("Automatically opens the live guest-screen monitor for every macOS VM the "
+ "instant it boots — whatever launched it. Normally the monitor is opened on "
+ "demand (the Control panel's \"Observe\"); this forces it always-on. Useful "
+ "for Nucleic developers, or anyone diagnosing a VM that won't behave.")
.settingsCaption()
}
}
Section("Base image") {
+13
View File
@@ -546,6 +546,13 @@ public enum MacVMSettings {
/// virtual IO, which needs neither the agent nor those grants. Only meaningful while the service is on.
public static let axAgentEnabledKey = "nucleic.macvm.axAgentEnabled"
/// Advanced/diagnostic: when on, the guest-screen **monitor** is opened automatically for every
/// per-session macOS VM the instant it boots no matter what launched it (`mac_vm_exec`,
/// `mac_vm_computer`, or provisioning). Normally the monitor is opened on demand (the Control
/// panel's "Observe"); this forces it always-on, which is handy for Nucleic developers or anyone
/// diagnosing a VM that won't behave. OFF by default. Only meaningful while the service is on.
public static let alwaysOpenGuestDisplayKey = "nucleic.macvm.alwaysOpenGuestDisplay"
/// Optional path to a **prebuilt** golden base VM bundle the user produced out-of-band. When set
/// and present, the engine clones it directly and skips the install+provision path entirely. Empty
/// the engine builds its own golden base under the storage root (install from the restore image,
@@ -613,6 +620,12 @@ public enum MacVMSettings {
serviceEnabled && defaults.bool(forKey: axAgentEnabledKey)
}
/// Whether the guest-screen monitor should auto-open for every session VM as it boots (see
/// ``alwaysOpenGuestDisplayKey``). Only meaningful while the service is on.
public static var alwaysOpenGuestDisplay: Bool {
serviceEnabled && defaults.bool(forKey: alwaysOpenGuestDisplayKey)
}
/// Configured prebuilt-base path, or `nil`/empty when unset.
public static var basePrebuiltPath: String? {
let v = (defaults.string(forKey: basePrebuiltPathKey) ?? "")