diff --git a/apps/macos/Sources/Clawdis/AppState.swift b/apps/macos/Sources/Clawdis/AppState.swift index ddcc44863..c4f07a7e0 100644 --- a/apps/macos/Sources/Clawdis/AppState.swift +++ b/apps/macos/Sources/Clawdis/AppState.swift @@ -62,7 +62,7 @@ final class AppState: ObservableObject { @Published var isWorking: Bool = false @Published var earBoostActive: Bool = false - private var earBoostTask: Task? = nil + private var earBoostTask: Task? init() { self.isPaused = UserDefaults.standard.bool(forKey: pauseDefaultsKey) diff --git a/apps/macos/Sources/Clawdis/MenuBar.swift b/apps/macos/Sources/Clawdis/MenuBar.swift index 1c03757e1..88e64fffe 100644 --- a/apps/macos/Sources/Clawdis/MenuBar.swift +++ b/apps/macos/Sources/Clawdis/MenuBar.swift @@ -23,15 +23,15 @@ struct ClawdisApp: App { earBoostActive: self.state.earBoostActive, relayStatus: self.relayManager.status) } - .menuBarExtraStyle(.menu) - .menuBarExtraAccess(isPresented: self.$isMenuPresented) { item in - self.statusItem = item - self.applyStatusItemAppearance(paused: self.state.isPaused) - } - .onChange(of: self.state.isPaused) { _, paused in - self.applyStatusItemAppearance(paused: paused) - self.relayManager.setActive(!paused) - } + .menuBarExtraStyle(.menu) + .menuBarExtraAccess(isPresented: self.$isMenuPresented) { item in + self.statusItem = item + self.applyStatusItemAppearance(paused: self.state.isPaused) + } + .onChange(of: self.state.isPaused) { _, paused in + self.applyStatusItemAppearance(paused: paused) + self.relayManager.setActive(!paused) + } Settings { SettingsRootView(state: self.state) @@ -90,10 +90,10 @@ private struct MenuContent: View { private func statusColor(_ status: RelayProcessManager.Status) -> Color { switch status { - case .running: return .green - case .starting, .restarting: return .orange - case .failed: return .red - case .stopped: return .secondary + case .running: .green + case .starting, .restarting: .orange + case .failed: .red + case .stopped: .secondary } } @@ -257,17 +257,17 @@ private struct CritterStatusLabel: View { private var relayNeedsAttention: Bool { switch self.relayStatus { case .failed, .stopped: - return !self.isPaused + !self.isPaused case .starting, .restarting, .running: - return false + false } } private var relayBadgeColor: Color { switch self.relayStatus { - case .failed: return .red - case .stopped: return .orange - default: return .clear + case .failed: .red + case .stopped: .orange + default: .clear } } } @@ -279,8 +279,8 @@ enum CritterIconRenderer { blink: CGFloat, legWiggle: CGFloat = 0, earWiggle: CGFloat = 0, - earScale: CGFloat = 1 - ) -> NSImage { + earScale: CGFloat = 1) -> NSImage + { let image = NSImage(size: size) image.lockFocus() defer { image.unlockFocus() } diff --git a/apps/macos/Sources/Clawdis/Onboarding.swift b/apps/macos/Sources/Clawdis/Onboarding.swift index dbc0878e9..f9851d567 100644 --- a/apps/macos/Sources/Clawdis/Onboarding.swift +++ b/apps/macos/Sources/Clawdis/Onboarding.swift @@ -120,7 +120,8 @@ struct OnboardingView: View { self.onboardingCard { self.featureRow( title: "Owns the TCC prompts", - subtitle: "Requests Notifications, Accessibility, and Screen Recording so your agents stay unblocked.", + subtitle: "Requests Notifications, Accessibility, and Screen Recording " + + "so your agents stay unblocked.", systemImage: "lock.shield") self.featureRow( title: "Native notifications", @@ -128,7 +129,8 @@ struct OnboardingView: View { systemImage: "bell.and.waveform") self.featureRow( title: "Privileged helpers", - subtitle: "Runs screenshots or shell actions from the `clawdis-mac` CLI with the right permissions.", + subtitle: "Runs screenshots or shell actions from the `clawdis-mac` CLI " + + "with the right permissions.", systemImage: "terminal") } } @@ -232,7 +234,8 @@ struct OnboardingView: View { Spacer() } Text( - "You can pause from the menu bar anytime. Settings keeps a \"Show onboarding\" button if you need to revisit.") + "You can pause from the menu bar anytime. Settings keeps a \"Show onboarding\" " + + "button if you need to revisit.") .font(.footnote) .foregroundStyle(.secondary) .frame(maxWidth: .infinity, alignment: .center) @@ -247,7 +250,8 @@ struct OnboardingView: View { self.onboardingCard { self.featureRow( title: "Run the dashboard", - subtitle: "Use the CLI helper from your scripts, and reopen onboarding from Settings if you add a new user.", + subtitle: "Use the CLI helper from your scripts, and reopen onboarding from " + + "Settings if you add a new user.", systemImage: "checkmark.seal") self.featureRow( title: "Test a notification", @@ -273,10 +277,10 @@ struct OnboardingView: View { .disabled(true) if self.currentPage > 0 { - Button(action: { self.handleBack() }) { + Button(action: self.handleBack, label: { Label("Back", systemImage: "chevron.left") .labelStyle(.iconOnly) - } + }) .buttonStyle(.plain) .foregroundColor(.secondary) .opacity(0.8) diff --git a/apps/macos/Sources/Clawdis/PermissionManager.swift b/apps/macos/Sources/Clawdis/PermissionManager.swift index 90dcdd93f..c7c557b20 100644 --- a/apps/macos/Sources/Clawdis/PermissionManager.swift +++ b/apps/macos/Sources/Clawdis/PermissionManager.swift @@ -23,7 +23,8 @@ enum PermissionManager { case .notDetermined: if interactive { - let granted = (try? await center.requestAuthorization(options: [.alert, .sound, .badge])) ?? false + let granted = await (try? center.requestAuthorization(options: [.alert, .sound, .badge])) ?? + false let updated = await center.notificationSettings() results[cap] = granted && (updated.authorizationStatus == .authorized || updated .authorizationStatus == .provisional) diff --git a/apps/macos/Sources/Clawdis/RelayProcessManager.swift b/apps/macos/Sources/Clawdis/RelayProcessManager.swift index 140393216..633113fac 100644 --- a/apps/macos/Sources/Clawdis/RelayProcessManager.swift +++ b/apps/macos/Sources/Clawdis/RelayProcessManager.swift @@ -46,7 +46,7 @@ final class RelayProcessManager: ObservableObject { private var recentCrashes: [Date] = [] private let logger = Logger(subsystem: "com.steipete.clawdis", category: "relay") - private let logLimit = 20_000 // characters to keep in-memory + private let logLimit = 20000 // characters to keep in-memory private let maxCrashes = 3 private let crashWindow: TimeInterval = 120 // seconds @@ -98,8 +98,8 @@ final class RelayProcessManager: ObservableObject { .name(command.first ?? "clawdis"), arguments: Arguments(Array(command.dropFirst())), environment: self.makeEnvironment(), - workingDirectory: FilePath(cwd) - ) { execution, stdin, stdout, stderr in + workingDirectory: FilePath(cwd)) + { execution, stdin, stdout, stderr in self.didStart(execution) async let out: Void = self.stream(output: stdout, label: "stdout") async let err: Void = self.stream(output: stderr, label: "stderr") @@ -122,12 +122,10 @@ final class RelayProcessManager: ObservableObject { } private func handleTermination(status: TerminationStatus) async { - let code: Int32 = { - switch status { - case let .exited(exitCode): return exitCode - case let .unhandledException(sig): return -Int32(sig) - } - }() + let code: Int32 = switch status { + case let .exited(exitCode): exitCode + case let .unhandledException(sig): -Int32(sig) + } self.execution = nil if self.stopping || !self.desiredActive { @@ -161,7 +159,7 @@ final class RelayProcessManager: ObservableObject { } self.appendLog("[relay] failed: \(message)\n") self.logger.error("relay failed: \(message, privacy: .public)") - if self.desiredActive && !self.shouldGiveUpAfterCrashes() { + if self.desiredActive, !self.shouldGiveUpAfterCrashes() { self.status = .restarting self.recentCrashes.append(Date()) self.startIfNeeded() @@ -200,7 +198,8 @@ final class RelayProcessManager: ObservableObject { // Keep it simple: rely on system-installed clawdis/warelay. // Default to `clawdis relay`; users can provide an override via env if needed. if let override = ProcessInfo.processInfo.environment["CLAWDIS_RELAY_CMD"], - !override.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { + !override.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + { return override.split(separator: " ").map(String.init) } @@ -257,7 +256,8 @@ final class RelayProcessManager: ObservableObject { private func defaultProjectRoot() -> URL { if let stored = UserDefaults.standard.string(forKey: Defaults.projectRootPath), - let url = self.expandPath(stored) { + let url = self.expandPath(stored) + { return url } let fallback = FileManager.default.homeDirectoryForCurrentUser @@ -275,7 +275,7 @@ final class RelayProcessManager: ObservableObject { func projectRootPath() -> String { UserDefaults.standard.string(forKey: Defaults.projectRootPath) ?? FileManager.default.homeDirectoryForCurrentUser - .appendingPathComponent("Projects/clawdis").path + .appendingPathComponent("Projects/clawdis").path } private func expandPath(_ path: String) -> URL? { diff --git a/apps/macos/Sources/Clawdis/SessionData.swift b/apps/macos/Sources/Clawdis/SessionData.swift index 0a265edb7..f3847add2 100644 --- a/apps/macos/Sources/Clawdis/SessionData.swift +++ b/apps/macos/Sources/Clawdis/SessionData.swift @@ -115,11 +115,9 @@ extension [String] { fileprivate func dedupedPreserveOrder() -> [String] { var seen = Set() var result: [String] = [] - for item in self { - if !seen.contains(item) { - seen.insert(item) - result.append(item) - } + for item in self where !seen.contains(item) { + seen.insert(item) + result.append(item) } return result } diff --git a/apps/macos/Sources/Clawdis/ToolsSettings.swift b/apps/macos/Sources/Clawdis/ToolsSettings.swift index dd61bf942..0153cd493 100644 --- a/apps/macos/Sources/Clawdis/ToolsSettings.swift +++ b/apps/macos/Sources/Clawdis/ToolsSettings.swift @@ -16,11 +16,11 @@ private enum InstallMethod: Equatable { let .npm(_, binary), let .go(_, binary), let .pnpm(_, _, binary): - return binary + binary case .gitClone: - return nil + nil case .mcporter: - return "mcporter" + "mcporter" } } } @@ -57,80 +57,70 @@ struct ToolsSettings: View { url: URL(string: "https://github.com/steipete/mcporter")!, description: "MCP runtime/CLI to discover servers, run tools, and sync configs across AI clients.", method: .npm(package: "mcporter", binary: "mcporter"), - kind: .tool - ), + kind: .tool), ToolEntry( id: "peekaboo", name: "Peekaboo", url: URL(string: "https://github.com/steipete/Peekaboo")!, description: "Lightning-fast macOS screenshots with AI vision helpers for step-by-step automation.", method: .brew(formula: "steipete/tap/peekaboo", binary: "peekaboo"), - kind: .tool - ), + kind: .tool), ToolEntry( id: "camsnap", name: "camsnap", url: URL(string: "https://github.com/steipete/camsnap")!, description: "One command to grab frames, clips, or motion alerts from RTSP/ONVIF cameras.", method: .brew(formula: "steipete/tap/camsnap", binary: "camsnap"), - kind: .tool - ), + kind: .tool), ToolEntry( id: "oracle", name: "oracle", url: URL(string: "https://github.com/steipete/oracle")!, description: "Runs OpenAI-ready agent workflows from the CLI with session replay and browser control.", method: .npm(package: "@steipete/oracle", binary: "oracle"), - kind: .tool - ), + kind: .tool), ToolEntry( id: "eightctl", name: "eightctl", url: URL(string: "https://github.com/steipete/eightctl")!, description: "Control Eight Sleep Pods (temp, alarms, schedules, metrics) from scripts or cron.", method: .go(module: "github.com/steipete/eightctl/cmd/eightctl@latest", binary: "eightctl"), - kind: .tool - ), + kind: .tool), ToolEntry( id: "imsg", name: "imsg", url: URL(string: "https://github.com/steipete/imsg")!, description: "CLI for macOS Messages: read/tail chats and send iMessage/SMS with attachments.", method: .go(module: "github.com/steipete/imsg/cmd/imsg@latest", binary: "imsg"), - kind: .tool - ), + kind: .tool), ToolEntry( id: "spotify-player", name: "spotify-player", url: URL(string: "https://github.com/aome510/spotify-player")!, description: "Terminal Spotify client to queue, search, and control playback without leaving chat.", method: .brew(formula: "spotify_player", binary: "spotify_player"), - kind: .tool - ), + kind: .tool), ToolEntry( id: "openhue-cli", name: "OpenHue CLI", url: URL(string: "https://github.com/openhue/openhue-cli")!, description: "Control Philips Hue lights from scripts—scenes, dimming, and automations.", method: .brew(formula: "openhue/cli/openhue-cli", binary: "openhue"), - kind: .tool - ), + kind: .tool), ToolEntry( id: "openai-whisper", name: "OpenAI Whisper", url: URL(string: "https://github.com/openai/whisper")!, description: "On-device speech-to-text for quick note taking or voicemail transcription.", method: .brew(formula: "openai-whisper", binary: "whisper"), - kind: .tool - ), + kind: .tool), ToolEntry( id: "gemini-cli", name: "Gemini CLI", url: URL(string: "https://github.com/google-gemini/gemini-cli")!, description: "Google Gemini models from the terminal for fast Q&A and web-grounded summaries.", method: .brew(formula: "gemini-cli", binary: "gemini"), - kind: .tool - ), + kind: .tool), ToolEntry( id: "bird", name: "bird", @@ -139,10 +129,8 @@ struct ToolsSettings: View { method: .pnpm( repoPath: "\(NSHomeDirectory())/Projects/bird", script: "binary", - binary: "bird" - ), - kind: .tool - ), + binary: "bird"), + kind: .tool), ToolEntry( id: "agent-tools", name: "agent-tools", @@ -150,10 +138,8 @@ struct ToolsSettings: View { description: "Collection of utilities and scripts tuned for autonomous agents and MCP clients.", method: .gitClone( url: "https://github.com/badlogic/agent-tools.git", - destination: "\(NSHomeDirectory())/agent-tools" - ), - kind: .tool - ), + destination: "\(NSHomeDirectory())/agent-tools"), + kind: .tool), ToolEntry( id: "gmail-mcp", name: "Gmail MCP", @@ -162,10 +148,8 @@ struct ToolsSettings: View { method: .mcporter( name: "gmail", command: "npx -y @gongrzhe/server-gmail-autoauth-mcp", - summary: "Adds Gmail MCP via mcporter (stdio transport, auto-auth)." - ), - kind: .mcp - ), + summary: "Adds Gmail MCP via mcporter (stdio transport, auto-auth)."), + kind: .mcp), ToolEntry( id: "google-calendar-mcp", name: "Google Calendar MCP", @@ -174,10 +158,8 @@ struct ToolsSettings: View { method: .mcporter( name: "google-calendar", command: "npx -y @cocal/google-calendar-mcp", - summary: "Adds Google Calendar MCP via mcporter (stdio transport)." - ), - kind: .mcp - ), + summary: "Adds Google Calendar MCP via mcporter (stdio transport)."), + kind: .mcp), ] var body: some View { @@ -188,8 +170,8 @@ struct ToolsSettings: View { ScrollView { LazyVStack(spacing: 12) { - section(for: .tool, title: "CLI Tools") - section(for: .mcp, title: "MCP Servers") + self.section(for: .tool, title: "CLI Tools") + self.section(for: .mcp, title: "MCP Servers") } } } @@ -198,7 +180,7 @@ struct ToolsSettings: View { } private func section(for kind: ToolEntry.Kind, title: String) -> some View { - let filtered = tools.filter { $0.kind == kind } + let filtered = self.tools.filter { $0.kind == kind } return VStack(alignment: .leading, spacing: 10) { Text(title) .font(.callout.weight(.semibold)) @@ -212,8 +194,7 @@ struct ToolsSettings: View { .clipShape(RoundedRectangle(cornerRadius: 10)) .overlay( RoundedRectangle(cornerRadius: 10) - .stroke(Color.secondary.opacity(0.15), lineWidth: 1) - ) + .stroke(Color.secondary.opacity(0.15), lineWidth: 1)) } } } @@ -231,15 +212,15 @@ private struct ToolRow: View { VStack(alignment: .leading, spacing: 6) { HStack(alignment: .top, spacing: 10) { VStack(alignment: .leading, spacing: 4) { - Link(tool.name, destination: tool.url) + Link(self.tool.name, destination: self.tool.url) .font(.headline) - Text(tool.description) + Text(self.tool.description) .font(.subheadline) .foregroundStyle(.secondary) .fixedSize(horizontal: false, vertical: true) } Spacer() - actionButton + self.actionButton } if let statusMessage, !statusMessage.isEmpty { @@ -248,12 +229,12 @@ private struct ToolRow: View { .foregroundStyle(.secondary) } } - .onAppear { refresh() } + .onAppear { self.refresh() } } private var actionButton: some View { VStack { - switch state { + switch self.state { case .installed: Label("Installed", systemImage: "checkmark.circle.fill") .foregroundStyle(.green) @@ -261,12 +242,12 @@ private struct ToolRow: View { case .installing: ProgressView().controlSize(.small) case .failed: - Button("Retry") { install() } + Button("Retry") { self.install() } .buttonStyle(.borderedProminent) case .checking: ProgressView().controlSize(.small) case .notInstalled: - Button("Install") { install() } + Button("Install") { self.install() } .buttonStyle(.borderedProminent) } } @@ -274,21 +255,21 @@ private struct ToolRow: View { private func refresh() { Task { - state = .checking - let installed = await ToolInstaller.isInstalled(tool.method) + self.state = .checking + let installed = await ToolInstaller.isInstalled(self.tool.method) await MainActor.run { - state = installed ? .installed : .notInstalled + self.state = installed ? .installed : .notInstalled } } } private func install() { Task { - state = .installing - let result = await ToolInstaller.install(tool.method) + self.state = .installing + let result = await ToolInstaller.install(self.tool.method) await MainActor.run { - statusMessage = result.message - state = result.installed ? .installed : .failed(result.message) + self.statusMessage = result.message + self.state = result.installed ? .installed : .failed(result.message) } } } @@ -305,30 +286,30 @@ private enum ToolInstaller { static func isInstalled(_ method: InstallMethod) async -> Bool { switch method { case let .brew(formula, _): - return await shellSucceeds("brew list --versions \(formula)") + return await self.shellSucceeds("brew list --versions \(formula)") case let .npm(_, binary), let .go(_, binary), let .pnpm(_, _, binary): - return await commandExists(binary) + return await self.commandExists(binary) case let .gitClone(_, destination): return FileManager.default.fileExists(atPath: destination) case let .mcporter(name, _, _): - guard await commandExists("mcporter") else { return false } - return await shellSucceeds("mcporter config get \(name) --json") + guard await self.commandExists("mcporter") else { return false } + return await self.shellSucceeds("mcporter config get \(name) --json") } } static func install(_ method: InstallMethod) async -> InstallResult { switch method { case let .brew(formula, _): - return await runInstall("brew install \(formula)") + return await self.runInstall("brew install \(formula)") case let .npm(package, _): - return await runInstall("npm install -g \(package)") + return await self.runInstall("npm install -g \(package)") case let .go(module, _): - return await runInstall("GO111MODULE=on go install \(module)") + return await self.runInstall("GO111MODULE=on go install \(module)") case let .pnpm(repoPath, script, _): let cmd = "cd \(escape(repoPath)) && pnpm install && pnpm run \(script)" - return await runInstall(cmd) + return await self.runInstall(cmd) case let .gitClone(url, destination): let cmd = """ if [ -d \(escape(destination)) ]; then @@ -337,19 +318,19 @@ private enum ToolInstaller { git clone \(url) \(escape(destination)) fi """ - return await runInstall(cmd) + return await self.runInstall(cmd) case let .mcporter(name, command, summary): let cmd = """ mcporter config add \(name) --command "\(command)" --transport stdio --scope home --description "\(summary)" """ - return await runInstall(cmd) + return await self.runInstall(cmd) } } // MARK: - Helpers private static func commandExists(_ binary: String) async -> Bool { - await shellSucceeds("command -v \(binary)") + await self.shellSucceeds("command -v \(binary)") } private static func shellSucceeds(_ command: String) async -> Bool { diff --git a/apps/macos/Sources/Clawdis/Utilities.swift b/apps/macos/Sources/Clawdis/Utilities.swift index fbbb40d7e..3edd7d841 100644 --- a/apps/macos/Sources/Clawdis/Utilities.swift +++ b/apps/macos/Sources/Clawdis/Utilities.swift @@ -1,5 +1,5 @@ -import Foundation import AppKit +import Foundation enum LaunchdManager { private static func runLaunchctl(_ args: [String]) { diff --git a/apps/macos/Sources/Clawdis/VoiceWakeSettings.swift b/apps/macos/Sources/Clawdis/VoiceWakeSettings.swift index 851002e04..57738e718 100644 --- a/apps/macos/Sources/Clawdis/VoiceWakeSettings.swift +++ b/apps/macos/Sources/Clawdis/VoiceWakeSettings.swift @@ -103,7 +103,10 @@ final class VoiceWakeTester { domain: "VoiceWakeTester", code: 3, userInfo: [ - NSLocalizedDescriptionKey: "Missing mic/speech privacy strings. Rebuild the mac app (scripts/restart-mac.sh) to include usage descriptions.", + NSLocalizedDescriptionKey: """ + Missing mic/speech privacy strings. Rebuild the mac app (scripts/restart-mac.sh) \ + to include usage descriptions. + """, ]) } @@ -256,7 +259,8 @@ struct VoiceWakeSettings: View { VStack(alignment: .leading, spacing: 14) { SettingsToggleRow( title: "Enable Voice Wake", - subtitle: "Listen for a wake phrase (e.g. \"Claude\") before running voice commands. Voice recognition runs fully on-device.", + subtitle: "Listen for a wake phrase (e.g. \"Claude\") before running voice commands. " + + "Voice recognition runs fully on-device.", binding: self.$state.swabbleEnabled) .disabled(!voiceWakeSupported) @@ -314,7 +318,8 @@ struct VoiceWakeSettings: View { .stroke(Color.secondary.opacity(0.25), lineWidth: 1)) Text( - "Clawdis reacts when any trigger appears in a transcription. Keep them short to avoid false positives.") + "Clawdis reacts when any trigger appears in a transcription. " + + "Keep them short to avoid false positives.") .font(.footnote) .foregroundStyle(.secondary) .fixedSize(horizontal: false, vertical: true) diff --git a/apps/macos/Sources/Clawdis/WebChatWindow.swift b/apps/macos/Sources/Clawdis/WebChatWindow.swift index 5c4eb0717..83cbf100a 100644 --- a/apps/macos/Sources/Clawdis/WebChatWindow.swift +++ b/apps/macos/Sources/Clawdis/WebChatWindow.swift @@ -69,7 +69,7 @@ final class WebChatWindowController: NSWindowController, WKScriptMessageHandler, } @available(*, unavailable) - required init?(coder: NSCoder) { fatalError() } + required init?(coder: NSCoder) { fatalError("init(coder:) is not supported") } private func loadPage() { let messagesJSON = self.initialMessagesJSON.replacingOccurrences(of: "", with: "<\\/script>") @@ -112,7 +112,13 @@ final class WebChatWindowController: NSWindowController, WKScriptMessageHandler, "{}" } - let html = """ + let html = self.makeHTML(importMapJSON: importMapJSON, messagesJSON: messagesJSON) + self.webView.loadHTMLString(html, baseURL: webChatURL) + } + + // swiftlint:disable line_length + private func makeHTML(importMapJSON: String, messagesJSON: String) -> String { + """ @@ -156,7 +162,7 @@ final class WebChatWindowController: NSWindowController, WKScriptMessageHandler, class NativeTransport { async *run(messages, userMessage, cfg, signal) { const result = await window.__clawdisSend({ type: 'chat', payload: { text: userMessage.content?.[0]?.text ?? '', sessionKey: '\( - sessionKey)' } }); + self.sessionKey)' } }); const usage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } }; const assistant = { role: 'assistant', @@ -225,9 +231,10 @@ final class WebChatWindowController: NSWindowController, WKScriptMessageHandler, """ - self.webView.loadHTMLString(html, baseURL: webChatURL) } + // swiftlint:enable line_length + func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { webView.evaluateJavaScript("document.body.innerText") { result, error in if let error { diff --git a/apps/macos/Sources/Clawdis/XPCService.swift b/apps/macos/Sources/Clawdis/XPCService.swift index 66d742144..a93a0233f 100644 --- a/apps/macos/Sources/Clawdis/XPCService.swift +++ b/apps/macos/Sources/Clawdis/XPCService.swift @@ -1,6 +1,6 @@ +import ClawdisIPC import Foundation import OSLog -import ClawdisIPC @objc protocol ClawdisXPCProtocol { func handle(_ data: Data, withReply reply: @escaping @Sendable (Data?, Error?) -> Void) diff --git a/apps/macos/Sources/ClawdisCLI/main.swift b/apps/macos/Sources/ClawdisCLI/main.swift index 03fa5b851..2cae552aa 100644 --- a/apps/macos/Sources/ClawdisCLI/main.swift +++ b/apps/macos/Sources/ClawdisCLI/main.swift @@ -37,6 +37,7 @@ struct ClawdisCLI { } } + // swiftlint:disable cyclomatic_complexity private static func parseCommandLine() throws -> Request { var args = Array(CommandLine.arguments.dropFirst()) guard let command = args.first else { throw CLIError.help } @@ -126,6 +127,8 @@ struct ClawdisCLI { } } + // swiftlint:enable cyclomatic_complexity + private static func send(request: Request) async throws -> Response { let conn = NSXPCConnection(machServiceName: serviceName) let interface = NSXPCInterface(with: ClawdisXPCProtocol.self)