[fix]: Fix live runtime settings refresh#27
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes three live runtime configuration refresh issues: restored local agent sessions are now lazy-loaded (no premature Agent creation when reopening interrupted conversations), the local permission mode hot-reloads into the active connector/session (auto-approving pending host-access requests when switching to Full Access), and AI provider settings changes are broadcast so the chat composer and settings list refresh without an app restart.
Changes:
- Lazy-load the local KWWK
Agentby removingensureLocalAgent()fromLocalAgentSession.setup()and addingrefreshRuntimeConfiguration()to update model/system prompt of an already-instantiated agent. - Hot-apply local permission mode via new
LocalRuntimeConnector.applyPermissionModeChangeplus arespondsToPermissionModeflag onPendingConfirmationto auto-approve host-access prompts (excluding ComputerUse start) when switching to Full Access; clear grants when reverting to Default. - Add
aiProviderSettingsDidChangenotification posted byAIProviderDetailViewafter every save/sign-in/reset;AIProvidersSettingsViewandChatEditorViewModelsubscribe to reload providers/models, andBridgeAIProviderRegistry.selectedModel(settings:)now falls back to the default model when the selected provider is disabled.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| macos/OpenBridge/Notifications/NotificationNames.swift | Adds aiProviderSettingsDidChange notification name. |
| macos/OpenBridge/Interface/Settings/AIProviders/AIProvidersSettingsView.swift | Reloads provider list on the new notification. |
| macos/OpenBridge/Interface/Settings/AIProviders/AIProviderDetailView.swift | Posts the notification and reloads provider configuration after save/sign-in/reset. |
| macos/OpenBridge/Interface/Chat/ChatEditorViewModel+ComposerEditing.swift | Calls applyLocalEnvironmentPermissionModeChange when the composer toggles permission mode. |
| macos/OpenBridge/Interface/Chat/ChatEditorViewModel.swift | Subscribes to provider-settings notifications to refresh selected model. |
| macos/OpenBridge/Agent/LocalRuntime/OpenBridgeSystemPromptBuilder.swift | Injects mode-specific permission instructions into the system prompt. |
| macos/OpenBridge/Agent/LocalRuntime/LocalRuntimeConnector.swift | Adds permission-mode hot-apply and per-pending respondsToPermissionMode flag. |
| macos/OpenBridge/Agent/LocalRuntime/LocalAgentSession.swift | Removes eager ensureLocalAgent() from setup and adds refreshRuntimeConfiguration plus extracted system-prompt builder. |
| macos/OpenBridge/Agent/BridgeAIProviderRegistry.swift | Adds selectedModel(settings:) that falls back to default if the selected provider is disabled. |
| macos/OpenBridge/Agent/AgentSessionManager.swift | Reworks refreshConnectorConfiguration to ensure runtime; adds applyLocalEnvironmentPermissionModeChange and reloadAIProviderConfiguration. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func applyPermissionModeChange(_ mode: LocalEnvironmentPermissionMode) { | ||
| guard environmentKind == .localMacOS else { return } | ||
|
|
||
| switch mode { | ||
| case .default: | ||
| clearAllGrantedPermissions() | ||
| case .fullAccess: | ||
| approvePendingHostAccessPermissions() | ||
| } | ||
| } |
| func refreshConnectorConfiguration() { | ||
| isVMReady = true | ||
| Task { [weak self] in | ||
| guard let self else { return } | ||
| do { | ||
| _ = try await ensureRuntimeReady() | ||
| await refreshLoadedSessionRuntimeConfiguration() | ||
| } catch { | ||
| vmLoadError = error | ||
| logger.warning("Failed to refresh local connector configuration: \(error.localizedDescription)") | ||
| } | ||
| } | ||
| } |
| guard let localAgent else { return } | ||
| localAgent.state.model = await BridgeAIProviderRegistry.selectedModel() | ||
| localAgent.state.systemPrompt = await makeLocalAgentSystemPrompt() |
| static func selectedModel(settings: BridgeAIProviderSettings) -> Model { | ||
| let selected = runtimeModel( | ||
| provider: settings.selectedModelProvider, | ||
| id: settings.selectedModelID, | ||
| settings: settings | ||
| ) ?? defaultModel(settings: settings) | ||
| ) | ||
| .flatMap { model in | ||
| BridgeAIProvider.provider(for: model).flatMap { provider in | ||
| settings[provider].isEnabled ? model : nil | ||
| } | ||
| } | ||
| return selected ?? defaultModel(settings: settings) | ||
| } |
| @@ -59,6 +60,24 @@ enum OpenBridgeSystemPromptBuilder { | |||
| """ | |||
| } | |||
|
|
|||
| private static func localPermissionModeInstruction() -> String { | |||
| switch SettingsManager.shared.localEnvironmentPermissionMode { | |||
| case .default: | |||
| "- Current local permission mode: Default. Host writes, host commands, and sensitive host paths require request_permission before use." | |||
| case .fullAccess: | |||
| "- Current local permission mode: Full Access. Host writes, host commands, and sensitive host paths are already approved for this app session; do not call request_permission solely for local permission, but still prefer sandbox unless local access is required." | |||
| } | |||
| } | |||
|
|
|||
| private static func localPermissionRequestInstruction() -> String { | |||
| switch SettingsManager.shared.localEnvironmentPermissionMode { | |||
| case .default: | |||
| "- Before using bash, write, or edit in environment=\"local\", call request_permission(environment=\"local\", description=\"...\") with a clear, specific description of what you plan to do so the user can make an informed decision." | |||
| case .fullAccess: | |||
| "- Before using bash, write, or edit in environment=\"local\", confirm local access is truly required; request_permission is not needed while Full Access is active." | |||
| } | |||
| } | |||
| private func applyProviderConfigurationChange() async { | ||
| await AgentSessionManager.shared.reloadAIProviderConfiguration() | ||
| await MainActor.run { | ||
| NotificationCenter.default.post(name: .aiProviderSettingsDidChange, object: nil) | ||
| } | ||
| } |
f006b29 to
2463712
Compare
|
Addressed Copilot review comments in
Validation after the follow-up:
|
Summary
Validation
swiftformaton modified Swift filesswiftlint linton modified Swift filesgit diff --checkBUILD_CONFIGURATION=UnsignedDebug bash DevKit/Scripts/workspace_build_debug.sh(BUILD SUCCEEDED)GPT-5 (OpenAI)selector without restarting