diff --git a/apps/macos/Sources/Clawdis/ConfigStore.swift b/apps/macos/Sources/Clawdis/ConfigStore.swift index 19802f906..533ee6825 100644 --- a/apps/macos/Sources/Clawdis/ConfigStore.swift +++ b/apps/macos/Sources/Clawdis/ConfigStore.swift @@ -3,10 +3,10 @@ import Foundation enum ConfigStore { struct Overrides: Sendable { var isRemoteMode: (@Sendable () async -> Bool)? - var loadLocal: (@Sendable () -> [String: Any])? - var saveLocal: (@Sendable ([String: Any]) -> Void)? - var loadRemote: (@Sendable () async -> [String: Any])? - var saveRemote: (@Sendable ([String: Any]) async throws -> Void)? + var loadLocal: (@MainActor @Sendable () -> [String: Any])? + var saveLocal: (@MainActor @Sendable ([String: Any]) -> Void)? + var loadRemote: (@MainActor @Sendable () async -> [String: Any])? + var saveRemote: (@MainActor @Sendable ([String: Any]) async throws -> Void)? } private actor OverrideStore { @@ -24,9 +24,10 @@ enum ConfigStore { if let override = overrides.isRemoteMode { return await override() } - await MainActor.run { AppStateStore.shared.connectionMode == .remote } + return await MainActor.run { AppStateStore.shared.connectionMode == .remote } } + @MainActor static func load() async -> [String: Any] { let overrides = await self.overrideStore.overrides if await self.isRemoteMode() { @@ -41,6 +42,7 @@ enum ConfigStore { return ClawdisConfigFile.loadDict() } + @MainActor static func save(_ root: [String: Any]) async throws { let overrides = await self.overrideStore.overrides if await self.isRemoteMode() { @@ -58,6 +60,7 @@ enum ConfigStore { } } + @MainActor private static func loadFromGateway() async -> [String: Any] { do { let snap: ConfigSnapshot = try await GatewayConnection.shared.requestDecoded( @@ -70,6 +73,7 @@ enum ConfigStore { } } + @MainActor private static func saveToGateway(_ root: [String: Any]) async throws { let data = try JSONSerialization.data(withJSONObject: root, options: [.prettyPrinted, .sortedKeys]) guard let raw = String(data: data, encoding: .utf8) else { diff --git a/apps/macos/Sources/Clawdis/OnboardingView+Workspace.swift b/apps/macos/Sources/Clawdis/OnboardingView+Workspace.swift index d733659a9..8f02adc38 100644 --- a/apps/macos/Sources/Clawdis/OnboardingView+Workspace.swift +++ b/apps/macos/Sources/Clawdis/OnboardingView+Workspace.swift @@ -73,6 +73,7 @@ extension OnboardingView { return agent?["workspace"] as? String } + @discardableResult func saveAgentWorkspace(_ workspace: String?) async -> Bool { var root = await ConfigStore.load() var agent = root["agent"] as? [String: Any] ?? [:] diff --git a/apps/macos/Sources/Clawdis/SettingsRootView.swift b/apps/macos/Sources/Clawdis/SettingsRootView.swift index 203ef2202..d6d553d1c 100644 --- a/apps/macos/Sources/Clawdis/SettingsRootView.swift +++ b/apps/macos/Sources/Clawdis/SettingsRootView.swift @@ -6,6 +6,7 @@ struct SettingsRootView: View { private let permissionMonitor = PermissionMonitor.shared @State private var monitoringPermissions = false @State private var selectedTab: SettingsTab = .general + @State private var snapshotPaths: (configPath: String?, stateDir: String?) = (nil, nil) let updater: UpdaterProviding? private let isPreview = ProcessInfo.processInfo.isPreview private let isNixMode = ProcessInfo.processInfo.isNixMode @@ -102,13 +103,16 @@ struct SettingsRootView: View { guard !self.isPreview else { return } await self.refreshPerms() } + .task(id: self.state.connectionMode) { + guard !self.isPreview else { return } + await self.refreshSnapshotPaths() + } } private var nixManagedBanner: some View { // Prefer gateway-resolved paths; fall back to local env defaults if disconnected. - let snapshotPaths = GatewayConnection.shared.snapshotPaths() - let configPath = snapshotPaths.configPath ?? ClawdisPaths.configURL.path - let stateDir = snapshotPaths.stateDir ?? ClawdisPaths.stateDirURL.path + let configPath = self.snapshotPaths.configPath ?? ClawdisPaths.configURL.path + let stateDir = self.snapshotPaths.stateDir ?? ClawdisPaths.stateDirURL.path return VStack(alignment: .leading, spacing: 6) { HStack(spacing: 8) { @@ -140,6 +144,12 @@ struct SettingsRootView: View { return requested } + @MainActor + private func refreshSnapshotPaths() async { + let paths = await GatewayConnection.shared.snapshotPaths() + self.snapshotPaths = paths + } + @MainActor private func refreshPerms() async { guard !self.isPreview else { return } diff --git a/src/canvas-host/a2ui/.bundle.hash b/src/canvas-host/a2ui/.bundle.hash index 20b11f47c..fd929f88d 100644 --- a/src/canvas-host/a2ui/.bundle.hash +++ b/src/canvas-host/a2ui/.bundle.hash @@ -1 +1 @@ -700c6959d0a4aa855933f5e9c0d4894a07e2cfd4fa4b4aca181a078d61104704 +13cc362f2bc44e2a05a6da5e5ba66ea602755f18ed82b18cf244c8044aa84c36