openclaw/apps/macos/Sources/Clawdbot/DockIconManager.swift
Jon Shapiro 92697edb7c fix(venice): add compat settings to prevent HTTP 400 errors
Venice's API doesn't support certain OpenAI-compatible parameters that
Clawdbot sends by default:

- `store`: Venice returns HTTP 400 with no body when this is present
- `developer` role: Not supported by Venice's API

This adds VENICE_COMPAT settings (supportsStore: false,
supportsDeveloperRole: false) to all Venice model definitions, both
from the static catalog and dynamically discovered models.

Fixes issues reported in PR #1666 where users experienced silent
failures (HTTP 400, no body) when using Venice models.

Co-authored-by: jonisjongithub <jonisjongithub@users.noreply.github.com>
Co-authored-by: Clawdbot <bot@clawd.bot>
2026-01-26 17:56:01 -08:00

117 lines
3.9 KiB
Swift

import AppKit
/// Central manager for Dock icon visibility.
/// Shows the Dock icon while any windows are visible, regardless of user preference.
final class DockIconManager: NSObject, @unchecked Sendable {
static let shared = DockIconManager()
private var windowsObservation: NSKeyValueObservation?
private let logger = Logger(subsystem: "com.clawdbot", category: "DockIconManager")
override private init() {
super.init()
self.setupObservers()
Task { @MainActor in
self.updateDockVisibility()
}
}
deinit {
self.windowsObservation?.invalidate()
NotificationCenter.default.removeObserver(self)
}
func updateDockVisibility() {
Task { @MainActor in
guard NSApp != nil else {
self.logger.warning("NSApp not ready, skipping Dock visibility update")
return
}
let userWantsDockHidden = !UserDefaults.standard.bool(forKey: showDockIconKey)
let visibleWindows = NSApp?.windows.filter { window in
window.isVisible &&
window.frame.width > 1 &&
window.frame.height > 1 &&
!window.isKind(of: NSPanel.self) &&
"\(type(of: window))" != "NSPopupMenuWindow" &&
window.contentViewController != nil
} ?? []
let hasVisibleWindows = !visibleWindows.isEmpty
if !userWantsDockHidden || hasVisibleWindows {
NSApp?.setActivationPolicy(.regular)
} else {
NSApp?.setActivationPolicy(.accessory)
}
}
}
func temporarilyShowDock() {
Task { @MainActor in
guard NSApp != nil else {
self.logger.warning("NSApp not ready, cannot show Dock icon")
return
}
NSApp.setActivationPolicy(.regular)
}
}
private func setupObservers() {
Task { @MainActor in
guard let app = NSApp else {
self.logger.warning("NSApp not ready, delaying Dock observers")
try? await Task.sleep(for: .milliseconds(200))
self.setupObservers()
return
}
self.windowsObservation = app.observe(\.windows, options: [.new]) { [weak self] _, _ in
Task { @MainActor in
try? await Task.sleep(for: .milliseconds(50))
self?.updateDockVisibility()
}
}
NotificationCenter.default.addObserver(
self,
selector: #selector(self.windowVisibilityChanged),
name: NSWindow.didBecomeKeyNotification,
object: nil)
NotificationCenter.default.addObserver(
self,
selector: #selector(self.windowVisibilityChanged),
name: NSWindow.didResignKeyNotification,
object: nil)
NotificationCenter.default.addObserver(
self,
selector: #selector(self.windowVisibilityChanged),
name: NSWindow.willCloseNotification,
object: nil)
NotificationCenter.default.addObserver(
self,
selector: #selector(self.dockPreferenceChanged),
name: UserDefaults.didChangeNotification,
object: nil)
}
}
@objc
private func windowVisibilityChanged(_: Notification) {
Task { @MainActor in
self.updateDockVisibility()
}
}
@objc
private func dockPreferenceChanged(_ notification: Notification) {
guard let userDefaults = notification.object as? UserDefaults,
userDefaults == UserDefaults.standard
else { return }
Task { @MainActor in
self.updateDockVisibility()
}
}
}