Add macOS menu bar app with chat and settings
- Restructure project into three targets: - AppleIntelligenceCore: Shared gRPC service code - AppleIntelligenceServer: CLI server - AppleIntelligenceApp: Menu bar app - Menu bar app features: - Toggle server on/off from menu bar - Chat window with streaming AI responses - Settings: host, port, API key, auto-start, launch at login - Proper window focus handling for menu bar apps - Add build scripts for distribution: - build-app.sh: Creates signed .app bundle - create-dmg.sh: Creates distributable DMG 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import Foundation
|
||||
import ServiceManagement
|
||||
|
||||
@Observable
|
||||
final class AppSettings {
|
||||
var host: String {
|
||||
didSet { UserDefaults.standard.set(host, forKey: "grpc_host") }
|
||||
}
|
||||
|
||||
var port: Int {
|
||||
didSet { UserDefaults.standard.set(port, forKey: "grpc_port") }
|
||||
}
|
||||
|
||||
var apiKey: String {
|
||||
didSet { UserDefaults.standard.set(apiKey, forKey: "api_key") }
|
||||
}
|
||||
|
||||
var autoStartServer: Bool {
|
||||
didSet { UserDefaults.standard.set(autoStartServer, forKey: "auto_start_server") }
|
||||
}
|
||||
|
||||
var launchAtLogin: Bool {
|
||||
didSet {
|
||||
do {
|
||||
if launchAtLogin {
|
||||
try SMAppService.mainApp.register()
|
||||
} else {
|
||||
try SMAppService.mainApp.unregister()
|
||||
}
|
||||
} catch {
|
||||
print("Failed to update launch at login: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
self.host = UserDefaults.standard.string(forKey: "grpc_host") ?? "0.0.0.0"
|
||||
let savedPort = UserDefaults.standard.integer(forKey: "grpc_port")
|
||||
self.port = savedPort == 0 ? 50051 : savedPort
|
||||
self.apiKey = UserDefaults.standard.string(forKey: "api_key") ?? ""
|
||||
self.autoStartServer = UserDefaults.standard.bool(forKey: "auto_start_server")
|
||||
self.launchAtLogin = SMAppService.mainApp.status == .enabled
|
||||
}
|
||||
|
||||
func resetToDefaults() {
|
||||
host = "0.0.0.0"
|
||||
port = 50051
|
||||
apiKey = ""
|
||||
autoStartServer = false
|
||||
launchAtLogin = false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import Foundation
|
||||
|
||||
struct ChatMessage: Identifiable, Equatable {
|
||||
let id: UUID
|
||||
let role: Role
|
||||
var content: String
|
||||
let timestamp: Date
|
||||
var isStreaming: Bool
|
||||
|
||||
enum Role: Equatable {
|
||||
case user
|
||||
case assistant
|
||||
}
|
||||
|
||||
init(role: Role, content: String, isStreaming: Bool = false) {
|
||||
self.id = UUID()
|
||||
self.role = role
|
||||
self.content = content
|
||||
self.timestamp = Date()
|
||||
self.isStreaming = isStreaming
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user