From 87d995bcdedc2c43df652485d5d153a53adafe60 Mon Sep 17 00:00:00 2001 From: Ryan Lisse Date: Sun, 18 Jan 2026 20:00:26 +0100 Subject: [PATCH] refactor(macos): replace FileManager.default for Swift 6 --- .../Sources/Clawdbot/AgentWorkspace.swift | 24 +++++------ .../Clawdbot/AnthropicAuthControls.swift | 2 +- .../Sources/Clawdbot/AnthropicOAuth.swift | 14 +++---- .../macos/Sources/Clawdbot/CLIInstaller.swift | 2 +- .../Clawdbot/CameraCaptureService.swift | 8 ++-- .../Sources/Clawdbot/CanvasManager.swift | 10 ++--- .../Clawdbot/CanvasSchemeHandler.swift | 8 ++-- .../Clawdbot/CanvasWindowController.swift | 8 ++-- .../Sources/Clawdbot/ClawdbotConfigFile.swift | 4 +- .../Sources/Clawdbot/ClawdbotPaths.swift | 2 +- .../Sources/Clawdbot/CommandResolver.swift | 36 ++++++++--------- .../macos/Sources/Clawdbot/DebugActions.swift | 8 ++-- .../Sources/Clawdbot/DebugSettings.swift | 6 +-- .../Sources/Clawdbot/DiagnosticsFileLog.swift | 14 +++---- .../Sources/Clawdbot/ExecApprovals.swift | 14 +++---- .../Clawdbot/GatewayEndpointStore.swift | 28 ++++--------- .../Clawdbot/GatewayLaunchAgentManager.swift | 6 +-- .../Clawdbot/GatewayProcessManager.swift | 4 +- .../Sources/Clawdbot/LaunchAgentManager.swift | 12 +++--- apps/macos/Sources/Clawdbot/LogLocator.swift | 4 +- .../Sources/Clawdbot/ModelCatalogLoader.swift | 2 +- .../Clawdbot/NodeMode/MacNodeRuntime.swift | 6 +-- .../macos/Sources/Clawdbot/PortGuardian.swift | 4 +- .../Sources/Clawdbot/RuntimeLocator.swift | 2 +- .../Clawdbot/ScreenRecordService.swift | 4 +- .../Sources/Clawdbot/SessionActions.swift | 4 +- apps/macos/Sources/Clawdbot/SessionData.swift | 2 +- .../macos/Sources/Clawdbot/SoundEffects.swift | 4 +- .../Sources/Clawdbot/TailscaleService.swift | 2 +- .../Sources/Clawdbot/VoicePushToTalk.swift | 12 ++---- apps/macos/Sources/ClawdbotIPC/IPC.swift | 2 +- .../Sources/ClawdbotWizardCLI/main.swift | 2 +- .../AgentWorkspaceTests.swift | 40 +++++++++---------- .../AnthropicAuthResolverTests.swift | 4 +- .../ClawdbotIPCTests/CLIInstallerTests.swift | 2 +- .../CanvasFileWatcherTests.swift | 4 +- .../CanvasWindowSmokeTests.swift | 12 +++--- .../ClawdbotConfigFileTests.swift | 8 ++-- .../ClawdbotOAuthStoreTests.swift | 8 ++-- .../CommandResolverTests.swift | 10 ++--- .../FileHandleLegacyAPIGuardTests.swift | 2 +- .../GatewayLaunchAgentManagerTests.swift | 8 ++-- .../ClawdbotIPCTests/LogLocatorTests.swift | 2 +- .../LowCoverageHelperTests.swift | 12 +++--- .../MacNodeRuntimeTests.swift | 2 +- .../ModelCatalogLoaderTests.swift | 8 ++-- .../NodeManagerPathsTests.swift | 10 ++--- .../RuntimeLocatorTests.swift | 4 +- .../ClawdbotIPCTests/TestIsolation.swift | 2 +- .../ClawdbotIPCTests/UtilitiesTests.swift | 10 ++--- src/canvas-host/a2ui/.bundle.hash | 2 +- 51 files changed, 197 insertions(+), 213 deletions(-) diff --git a/apps/macos/Sources/Clawdbot/AgentWorkspace.swift b/apps/macos/Sources/Clawdbot/AgentWorkspace.swift index 8906f2f4c..f63c1dd4d 100644 --- a/apps/macos/Sources/Clawdbot/AgentWorkspace.swift +++ b/apps/macos/Sources/Clawdbot/AgentWorkspace.swift @@ -23,7 +23,7 @@ enum AgentWorkspace { } static func displayPath(for url: URL) -> String { - let home = FileManager.default.homeDirectoryForCurrentUser.path + let home = FileManager().homeDirectoryForCurrentUser.path let path = url.path if path == home { return "~" } if path.hasPrefix(home + "/") { @@ -44,12 +44,12 @@ enum AgentWorkspace { } static func workspaceEntries(workspaceURL: URL) throws -> [String] { - let contents = try FileManager.default.contentsOfDirectory(atPath: workspaceURL.path) + let contents = try FileManager().contentsOfDirectory(atPath: workspaceURL.path) return contents.filter { !self.ignoredEntries.contains($0) } } static func isWorkspaceEmpty(workspaceURL: URL) -> Bool { - let fm = FileManager.default + let fm = FileManager() var isDir: ObjCBool = false if !fm.fileExists(atPath: workspaceURL.path, isDirectory: &isDir) { return true @@ -66,7 +66,7 @@ enum AgentWorkspace { } static func bootstrapSafety(for workspaceURL: URL) -> BootstrapSafety { - let fm = FileManager.default + let fm = FileManager() var isDir: ObjCBool = false if !fm.fileExists(atPath: workspaceURL.path, isDirectory: &isDir) { return .safe @@ -90,29 +90,29 @@ enum AgentWorkspace { static func bootstrap(workspaceURL: URL) throws -> URL { let shouldSeedBootstrap = self.isWorkspaceEmpty(workspaceURL: workspaceURL) - try FileManager.default.createDirectory(at: workspaceURL, withIntermediateDirectories: true) + try FileManager().createDirectory(at: workspaceURL, withIntermediateDirectories: true) let agentsURL = self.agentsURL(workspaceURL: workspaceURL) - if !FileManager.default.fileExists(atPath: agentsURL.path) { + if !FileManager().fileExists(atPath: agentsURL.path) { try self.defaultTemplate().write(to: agentsURL, atomically: true, encoding: .utf8) self.logger.info("Created AGENTS.md at \(agentsURL.path, privacy: .public)") } let soulURL = workspaceURL.appendingPathComponent(self.soulFilename) - if !FileManager.default.fileExists(atPath: soulURL.path) { + if !FileManager().fileExists(atPath: soulURL.path) { try self.defaultSoulTemplate().write(to: soulURL, atomically: true, encoding: .utf8) self.logger.info("Created SOUL.md at \(soulURL.path, privacy: .public)") } let identityURL = workspaceURL.appendingPathComponent(self.identityFilename) - if !FileManager.default.fileExists(atPath: identityURL.path) { + if !FileManager().fileExists(atPath: identityURL.path) { try self.defaultIdentityTemplate().write(to: identityURL, atomically: true, encoding: .utf8) self.logger.info("Created IDENTITY.md at \(identityURL.path, privacy: .public)") } let userURL = workspaceURL.appendingPathComponent(self.userFilename) - if !FileManager.default.fileExists(atPath: userURL.path) { + if !FileManager().fileExists(atPath: userURL.path) { try self.defaultUserTemplate().write(to: userURL, atomically: true, encoding: .utf8) self.logger.info("Created USER.md at \(userURL.path, privacy: .public)") } let bootstrapURL = workspaceURL.appendingPathComponent(self.bootstrapFilename) - if shouldSeedBootstrap, !FileManager.default.fileExists(atPath: bootstrapURL.path) { + if shouldSeedBootstrap, !FileManager().fileExists(atPath: bootstrapURL.path) { try self.defaultBootstrapTemplate().write(to: bootstrapURL, atomically: true, encoding: .utf8) self.logger.info("Created BOOTSTRAP.md at \(bootstrapURL.path, privacy: .public)") } @@ -120,7 +120,7 @@ enum AgentWorkspace { } static func needsBootstrap(workspaceURL: URL) -> Bool { - let fm = FileManager.default + let fm = FileManager() var isDir: ObjCBool = false if !fm.fileExists(atPath: workspaceURL.path, isDirectory: &isDir) { return true @@ -305,7 +305,7 @@ enum AgentWorkspace { if let dev = self.devTemplateURL(named: named) { urls.append(dev) } - let cwd = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) + let cwd = URL(fileURLWithPath: FileManager().currentDirectoryPath) urls.append(cwd.appendingPathComponent("docs") .appendingPathComponent(self.templateDirname) .appendingPathComponent(named)) diff --git a/apps/macos/Sources/Clawdbot/AnthropicAuthControls.swift b/apps/macos/Sources/Clawdbot/AnthropicAuthControls.swift index 42106e50d..0f5f1d61c 100644 --- a/apps/macos/Sources/Clawdbot/AnthropicAuthControls.swift +++ b/apps/macos/Sources/Clawdbot/AnthropicAuthControls.swift @@ -45,7 +45,7 @@ struct AnthropicAuthControls: View { NSWorkspace.shared.activateFileViewerSelecting([ClawdbotOAuthStore.oauthURL()]) } .buttonStyle(.bordered) - .disabled(!FileManager.default.fileExists(atPath: ClawdbotOAuthStore.oauthURL().path)) + .disabled(!FileManager().fileExists(atPath: ClawdbotOAuthStore.oauthURL().path)) Button("Refresh") { self.refresh() diff --git a/apps/macos/Sources/Clawdbot/AnthropicOAuth.swift b/apps/macos/Sources/Clawdbot/AnthropicOAuth.swift index 09113324a..4ea7f7fb9 100644 --- a/apps/macos/Sources/Clawdbot/AnthropicOAuth.swift +++ b/apps/macos/Sources/Clawdbot/AnthropicOAuth.swift @@ -234,7 +234,7 @@ enum ClawdbotOAuthStore { return URL(fileURLWithPath: expanded, isDirectory: true) } - return FileManager.default.homeDirectoryForCurrentUser + return FileManager().homeDirectoryForCurrentUser .appendingPathComponent(".clawdbot", isDirectory: true) .appendingPathComponent("credentials", isDirectory: true) } @@ -253,7 +253,7 @@ enum ClawdbotOAuthStore { urls.append(URL(fileURLWithPath: expanded, isDirectory: true).appendingPathComponent(self.oauthFilename)) } - let home = FileManager.default.homeDirectoryForCurrentUser + let home = FileManager().homeDirectoryForCurrentUser urls.append(home.appendingPathComponent(".pi/agent/\(self.oauthFilename)")) urls.append(home.appendingPathComponent(".claude/\(self.oauthFilename)")) urls.append(home.appendingPathComponent(".config/claude/\(self.oauthFilename)")) @@ -270,10 +270,10 @@ enum ClawdbotOAuthStore { static func importLegacyAnthropicOAuthIfNeeded() -> URL? { let dest = self.oauthURL() - guard !FileManager.default.fileExists(atPath: dest.path) else { return nil } + guard !FileManager().fileExists(atPath: dest.path) else { return nil } for url in self.legacyOAuthURLs() { - guard FileManager.default.fileExists(atPath: url.path) else { continue } + guard FileManager().fileExists(atPath: url.path) else { continue } guard self.anthropicOAuthStatus(at: url).isConnected else { continue } guard let storage = self.loadStorage(at: url) else { continue } do { @@ -296,7 +296,7 @@ enum ClawdbotOAuthStore { } static func anthropicOAuthStatus(at url: URL) -> AnthropicOAuthStatus { - guard FileManager.default.fileExists(atPath: url.path) else { return .missingFile } + guard FileManager().fileExists(atPath: url.path) else { return .missingFile } guard let data = try? Data(contentsOf: url) else { return .unreadableFile } guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else { return .invalidJSON } @@ -360,7 +360,7 @@ enum ClawdbotOAuthStore { private static func saveStorage(_ storage: [String: Any]) throws { let dir = self.oauthDir() - try FileManager.default.createDirectory( + try FileManager().createDirectory( at: dir, withIntermediateDirectories: true, attributes: [.posixPermissions: 0o700]) @@ -370,7 +370,7 @@ enum ClawdbotOAuthStore { withJSONObject: storage, options: [.prettyPrinted, .sortedKeys]) try data.write(to: url, options: [.atomic]) - try FileManager.default.setAttributes([.posixPermissions: 0o600], ofItemAtPath: url.path) + try FileManager().setAttributes([.posixPermissions: 0o600], ofItemAtPath: url.path) } } diff --git a/apps/macos/Sources/Clawdbot/CLIInstaller.swift b/apps/macos/Sources/Clawdbot/CLIInstaller.swift index d967002f5..b9113e27a 100644 --- a/apps/macos/Sources/Clawdbot/CLIInstaller.swift +++ b/apps/macos/Sources/Clawdbot/CLIInstaller.swift @@ -61,7 +61,7 @@ enum CLIInstaller { } private static func installPrefix() -> String { - FileManager.default.homeDirectoryForCurrentUser + FileManager().homeDirectoryForCurrentUser .appendingPathComponent(".clawdbot") .path } diff --git a/apps/macos/Sources/Clawdbot/CameraCaptureService.swift b/apps/macos/Sources/Clawdbot/CameraCaptureService.swift index b7a7de308..c9893bbfb 100644 --- a/apps/macos/Sources/Clawdbot/CameraCaptureService.swift +++ b/apps/macos/Sources/Clawdbot/CameraCaptureService.swift @@ -167,20 +167,20 @@ actor CameraCaptureService { defer { session.stopRunning() } await Self.warmUpCaptureSession() - let tmpMovURL = FileManager.default.temporaryDirectory + let tmpMovURL = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-camera-\(UUID().uuidString).mov") - defer { try? FileManager.default.removeItem(at: tmpMovURL) } + defer { try? FileManager().removeItem(at: tmpMovURL) } let outputURL: URL = { if let outPath, !outPath.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { return URL(fileURLWithPath: outPath) } - return FileManager.default.temporaryDirectory + return FileManager().temporaryDirectory .appendingPathComponent("clawdbot-camera-\(UUID().uuidString).mp4") }() // Ensure we don't fail exporting due to an existing file. - try? FileManager.default.removeItem(at: outputURL) + try? FileManager().removeItem(at: outputURL) let logger = self.logger var delegate: MovieFileDelegate? diff --git a/apps/macos/Sources/Clawdbot/CanvasManager.swift b/apps/macos/Sources/Clawdbot/CanvasManager.swift index 868e71142..f65c123ca 100644 --- a/apps/macos/Sources/Clawdbot/CanvasManager.swift +++ b/apps/macos/Sources/Clawdbot/CanvasManager.swift @@ -25,7 +25,7 @@ final class CanvasManager { var defaultAnchorProvider: (() -> NSRect?)? private nonisolated static let canvasRoot: URL = { - let base = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first! + let base = FileManager().urls(for: .applicationSupportDirectory, in: .userDomainMask).first! return base.appendingPathComponent("Clawdbot/canvas", isDirectory: true) }() @@ -83,7 +83,7 @@ final class CanvasManager { self.panelSessionKey = nil Self.logger.debug("showDetailed ensure canvas root dir") - try FileManager.default.createDirectory(at: Self.canvasRoot, withIntermediateDirectories: true) + try FileManager().createDirectory(at: Self.canvasRoot, withIntermediateDirectories: true) Self.logger.debug("showDetailed init CanvasWindowController") let controller = try CanvasWindowController( sessionKey: session, @@ -258,7 +258,7 @@ final class CanvasManager { // (Avoid treating Canvas routes like "/" as filesystem paths.) if trimmed.hasPrefix("/") { var isDir: ObjCBool = false - if FileManager.default.fileExists(atPath: trimmed, isDirectory: &isDir), !isDir.boolValue { + if FileManager().fileExists(atPath: trimmed, isDirectory: &isDir), !isDir.boolValue { return URL(fileURLWithPath: trimmed) } } @@ -293,7 +293,7 @@ final class CanvasManager { } private static func localStatus(sessionDir: URL, target: String) -> CanvasShowStatus { - let fm = FileManager.default + let fm = FileManager() let trimmed = target.trimmingCharacters(in: .whitespacesAndNewlines) let withoutQuery = trimmed.split(separator: "?", maxSplits: 1, omittingEmptySubsequences: false).first .map(String.init) ?? trimmed @@ -331,7 +331,7 @@ final class CanvasManager { } private static func indexExists(in dir: URL) -> Bool { - let fm = FileManager.default + let fm = FileManager() let a = dir.appendingPathComponent("index.html", isDirectory: false) if fm.fileExists(atPath: a.path) { return true } let b = dir.appendingPathComponent("index.htm", isDirectory: false) diff --git a/apps/macos/Sources/Clawdbot/CanvasSchemeHandler.swift b/apps/macos/Sources/Clawdbot/CanvasSchemeHandler.swift index 8617a2d49..27dbd93bf 100644 --- a/apps/macos/Sources/Clawdbot/CanvasSchemeHandler.swift +++ b/apps/macos/Sources/Clawdbot/CanvasSchemeHandler.swift @@ -69,8 +69,8 @@ final class CanvasSchemeHandler: NSObject, WKURLSchemeHandler { if path.isEmpty { let indexA = sessionRoot.appendingPathComponent("index.html", isDirectory: false) let indexB = sessionRoot.appendingPathComponent("index.htm", isDirectory: false) - if !FileManager.default.fileExists(atPath: indexA.path), - !FileManager.default.fileExists(atPath: indexB.path) + if !FileManager().fileExists(atPath: indexA.path), + !FileManager().fileExists(atPath: indexB.path) { return self.scaffoldPage(sessionRoot: sessionRoot) } @@ -106,7 +106,7 @@ final class CanvasSchemeHandler: NSObject, WKURLSchemeHandler { } private func resolveFileURL(sessionRoot: URL, requestPath: String) -> URL? { - let fm = FileManager.default + let fm = FileManager() var candidate = sessionRoot.appendingPathComponent(requestPath, isDirectory: false) var isDir: ObjCBool = false @@ -137,7 +137,7 @@ final class CanvasSchemeHandler: NSObject, WKURLSchemeHandler { } private func resolveIndex(in dir: URL) -> URL? { - let fm = FileManager.default + let fm = FileManager() let a = dir.appendingPathComponent("index.html", isDirectory: false) if fm.fileExists(atPath: a.path) { return a } let b = dir.appendingPathComponent("index.htm", isDirectory: false) diff --git a/apps/macos/Sources/Clawdbot/CanvasWindowController.swift b/apps/macos/Sources/Clawdbot/CanvasWindowController.swift index d0d4e4ff5..b119efd85 100644 --- a/apps/macos/Sources/Clawdbot/CanvasWindowController.swift +++ b/apps/macos/Sources/Clawdbot/CanvasWindowController.swift @@ -32,7 +32,7 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS let safeSessionKey = CanvasWindowController.sanitizeSessionKey(sessionKey) canvasWindowLogger.debug("CanvasWindowController init sanitized session=\(safeSessionKey, privacy: .public)") self.sessionDir = root.appendingPathComponent(safeSessionKey, isDirectory: true) - try FileManager.default.createDirectory(at: self.sessionDir, withIntermediateDirectories: true) + try FileManager().createDirectory(at: self.sessionDir, withIntermediateDirectories: true) canvasWindowLogger.debug("CanvasWindowController init session dir ready") self.schemeHandler = CanvasSchemeHandler(root: root) @@ -143,8 +143,8 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS if path == "/" || path.isEmpty { let indexA = sessionDir.appendingPathComponent("index.html", isDirectory: false) let indexB = sessionDir.appendingPathComponent("index.htm", isDirectory: false) - if !FileManager.default.fileExists(atPath: indexA.path), - !FileManager.default.fileExists(atPath: indexB.path) + if !FileManager().fileExists(atPath: indexA.path), + !FileManager().fileExists(atPath: indexB.path) { return } @@ -233,7 +233,7 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS // (Avoid treating Canvas routes like "/" as filesystem paths.) if trimmed.hasPrefix("/") { var isDir: ObjCBool = false - if FileManager.default.fileExists(atPath: trimmed, isDirectory: &isDir), !isDir.boolValue { + if FileManager().fileExists(atPath: trimmed, isDirectory: &isDir), !isDir.boolValue { let url = URL(fileURLWithPath: trimmed) canvasWindowLogger.debug("canvas load file \(url.absoluteString, privacy: .public)") self.loadFile(url) diff --git a/apps/macos/Sources/Clawdbot/ClawdbotConfigFile.swift b/apps/macos/Sources/Clawdbot/ClawdbotConfigFile.swift index 6b2169010..1c054b557 100644 --- a/apps/macos/Sources/Clawdbot/ClawdbotConfigFile.swift +++ b/apps/macos/Sources/Clawdbot/ClawdbotConfigFile.swift @@ -18,7 +18,7 @@ enum ClawdbotConfigFile { static func loadDict() -> [String: Any] { let url = self.url() - guard FileManager.default.fileExists(atPath: url.path) else { return [:] } + guard FileManager().fileExists(atPath: url.path) else { return [:] } do { let data = try Data(contentsOf: url) guard let root = self.parseConfigData(data) else { @@ -38,7 +38,7 @@ enum ClawdbotConfigFile { do { let data = try JSONSerialization.data(withJSONObject: dict, options: [.prettyPrinted, .sortedKeys]) let url = self.url() - try FileManager.default.createDirectory( + try FileManager().createDirectory( at: url.deletingLastPathComponent(), withIntermediateDirectories: true) try data.write(to: url, options: [.atomic]) diff --git a/apps/macos/Sources/Clawdbot/ClawdbotPaths.swift b/apps/macos/Sources/Clawdbot/ClawdbotPaths.swift index 3e32782c0..7cda49ea6 100644 --- a/apps/macos/Sources/Clawdbot/ClawdbotPaths.swift +++ b/apps/macos/Sources/Clawdbot/ClawdbotPaths.swift @@ -21,7 +21,7 @@ enum ClawdbotPaths { if let override = ClawdbotEnv.path(self.stateDirEnv) { return URL(fileURLWithPath: override, isDirectory: true) } - return FileManager.default.homeDirectoryForCurrentUser + return FileManager().homeDirectoryForCurrentUser .appendingPathComponent(".clawdbot", isDirectory: true) } diff --git a/apps/macos/Sources/Clawdbot/CommandResolver.swift b/apps/macos/Sources/Clawdbot/CommandResolver.swift index 9e8ae1c41..117930710 100644 --- a/apps/macos/Sources/Clawdbot/CommandResolver.swift +++ b/apps/macos/Sources/Clawdbot/CommandResolver.swift @@ -6,9 +6,9 @@ enum CommandResolver { static func gatewayEntrypoint(in root: URL) -> String? { let distEntry = root.appendingPathComponent("dist/index.js").path - if FileManager.default.isReadableFile(atPath: distEntry) { return distEntry } + if FileManager().isReadableFile(atPath: distEntry) { return distEntry } let binEntry = root.appendingPathComponent("bin/clawdbot.js").path - if FileManager.default.isReadableFile(atPath: binEntry) { return binEntry } + if FileManager().isReadableFile(atPath: binEntry) { return binEntry } return nil } @@ -47,16 +47,16 @@ enum CommandResolver { static func projectRoot() -> URL { if let stored = UserDefaults.standard.string(forKey: self.projectRootDefaultsKey), let url = self.expandPath(stored), - FileManager.default.fileExists(atPath: url.path) + FileManager().fileExists(atPath: url.path) { return url } - let fallback = FileManager.default.homeDirectoryForCurrentUser + let fallback = FileManager().homeDirectoryForCurrentUser .appendingPathComponent("Projects/clawdbot") - if FileManager.default.fileExists(atPath: fallback.path) { + if FileManager().fileExists(atPath: fallback.path) { return fallback } - return FileManager.default.homeDirectoryForCurrentUser + return FileManager().homeDirectoryForCurrentUser } static func setProjectRoot(_ path: String) { @@ -70,7 +70,7 @@ enum CommandResolver { static func preferredPaths() -> [String] { let current = ProcessInfo.processInfo.environment["PATH"]? .split(separator: ":").map(String.init) ?? [] - let home = FileManager.default.homeDirectoryForCurrentUser + let home = FileManager().homeDirectoryForCurrentUser let projectRoot = self.projectRoot() return self.preferredPaths(home: home, current: current, projectRoot: projectRoot) } @@ -99,10 +99,10 @@ enum CommandResolver { let bin = base.appendingPathComponent("bin") let nodeBin = base.appendingPathComponent("tools/node/bin") var paths: [String] = [] - if FileManager.default.fileExists(atPath: bin.path) { + if FileManager().fileExists(atPath: bin.path) { paths.append(bin.path) } - if FileManager.default.fileExists(atPath: nodeBin.path) { + if FileManager().fileExists(atPath: nodeBin.path) { paths.append(nodeBin.path) } return paths @@ -113,13 +113,13 @@ enum CommandResolver { // Volta let volta = home.appendingPathComponent(".volta/bin") - if FileManager.default.fileExists(atPath: volta.path) { + if FileManager().fileExists(atPath: volta.path) { bins.append(volta.path) } // asdf let asdf = home.appendingPathComponent(".asdf/shims") - if FileManager.default.fileExists(atPath: asdf.path) { + if FileManager().fileExists(atPath: asdf.path) { bins.append(asdf.path) } @@ -137,10 +137,10 @@ enum CommandResolver { } private static func versionedNodeBinPaths(base: URL, suffix: String) -> [String] { - guard FileManager.default.fileExists(atPath: base.path) else { return [] } + guard FileManager().fileExists(atPath: base.path) else { return [] } let entries: [String] do { - entries = try FileManager.default.contentsOfDirectory(atPath: base.path) + entries = try FileManager().contentsOfDirectory(atPath: base.path) } catch { return [] } @@ -167,7 +167,7 @@ enum CommandResolver { for entry in sorted { let binDir = base.appendingPathComponent(entry).appendingPathComponent(suffix) let node = binDir.appendingPathComponent("node") - if FileManager.default.isExecutableFile(atPath: node.path) { + if FileManager().isExecutableFile(atPath: node.path) { paths.append(binDir.path) } } @@ -177,7 +177,7 @@ enum CommandResolver { static func findExecutable(named name: String, searchPaths: [String]? = nil) -> String? { for dir in searchPaths ?? self.preferredPaths() { let candidate = (dir as NSString).appendingPathComponent(name) - if FileManager.default.isExecutableFile(atPath: candidate) { + if FileManager().isExecutableFile(atPath: candidate) { return candidate } } @@ -191,12 +191,12 @@ enum CommandResolver { static func projectClawdbotExecutable(projectRoot: URL? = nil) -> String? { let root = projectRoot ?? self.projectRoot() let candidate = root.appendingPathComponent("node_modules/.bin").appendingPathComponent(self.helperName).path - return FileManager.default.isExecutableFile(atPath: candidate) ? candidate : nil + return FileManager().isExecutableFile(atPath: candidate) ? candidate : nil } static func nodeCliPath() -> String? { let candidate = self.projectRoot().appendingPathComponent("bin/clawdbot.js").path - return FileManager.default.isReadableFile(atPath: candidate) ? candidate : nil + return FileManager().isReadableFile(atPath: candidate) ? candidate : nil } static func hasAnyClawdbotInvoker(searchPaths: [String]? = nil) -> Bool { @@ -459,7 +459,7 @@ enum CommandResolver { private static func expandPath(_ path: String) -> URL? { var expanded = path if expanded.hasPrefix("~") { - let home = FileManager.default.homeDirectoryForCurrentUser.path + let home = FileManager().homeDirectoryForCurrentUser.path expanded.replaceSubrange(expanded.startIndex...expanded.startIndex, with: home) } return URL(fileURLWithPath: expanded) diff --git a/apps/macos/Sources/Clawdbot/DebugActions.swift b/apps/macos/Sources/Clawdbot/DebugActions.swift index 1bfbeeb24..f0f84ed3c 100644 --- a/apps/macos/Sources/Clawdbot/DebugActions.swift +++ b/apps/macos/Sources/Clawdbot/DebugActions.swift @@ -26,7 +26,7 @@ enum DebugActions { static func openLog() { let path = self.pinoLogPath() let url = URL(fileURLWithPath: path) - guard FileManager.default.fileExists(atPath: path) else { + guard FileManager().fileExists(atPath: path) else { let alert = NSAlert() alert.messageText = "Log file not found" alert.informativeText = path @@ -38,7 +38,7 @@ enum DebugActions { @MainActor static func openConfigFolder() { - let url = FileManager.default + let url = FileManager() .homeDirectoryForCurrentUser .appendingPathComponent(".clawdbot", isDirectory: true) NSWorkspace.shared.activateFileViewerSelecting([url]) @@ -55,7 +55,7 @@ enum DebugActions { } let path = self.resolveSessionStorePath() let url = URL(fileURLWithPath: path) - if FileManager.default.fileExists(atPath: path) { + if FileManager().fileExists(atPath: path) { NSWorkspace.shared.activateFileViewerSelecting([url]) } else { NSWorkspace.shared.open(url.deletingLastPathComponent()) @@ -195,7 +195,7 @@ enum DebugActions { @MainActor private static func resolveSessionStorePath() -> String { let defaultPath = SessionLoader.defaultStorePath - let configURL = FileManager.default.homeDirectoryForCurrentUser + let configURL = FileManager().homeDirectoryForCurrentUser .appendingPathComponent(".clawdbot/clawdbot.json") guard let data = try? Data(contentsOf: configURL), diff --git a/apps/macos/Sources/Clawdbot/DebugSettings.swift b/apps/macos/Sources/Clawdbot/DebugSettings.swift index c338edad8..26a1f9830 100644 --- a/apps/macos/Sources/Clawdbot/DebugSettings.swift +++ b/apps/macos/Sources/Clawdbot/DebugSettings.swift @@ -354,7 +354,7 @@ struct DebugSettings: View { Button("Save") { self.saveRelayRoot() } .buttonStyle(.borderedProminent) Button("Reset") { - let def = FileManager.default.homeDirectoryForCurrentUser + let def = FileManager().homeDirectoryForCurrentUser .appendingPathComponent("Projects/clawdbot").path self.gatewayRootInput = def self.saveRelayRoot() @@ -743,7 +743,7 @@ struct DebugSettings: View { do { let data = try JSONSerialization.data(withJSONObject: root, options: [.prettyPrinted, .sortedKeys]) - try FileManager.default.createDirectory( + try FileManager().createDirectory( at: url.deletingLastPathComponent(), withIntermediateDirectories: true) try data.write(to: url, options: [.atomic]) @@ -776,7 +776,7 @@ struct DebugSettings: View { } private func configURL() -> URL { - FileManager.default.homeDirectoryForCurrentUser + FileManager().homeDirectoryForCurrentUser .appendingPathComponent(".clawdbot") .appendingPathComponent("clawdbot.json") } diff --git a/apps/macos/Sources/Clawdbot/DiagnosticsFileLog.swift b/apps/macos/Sources/Clawdbot/DiagnosticsFileLog.swift index f62dd2c07..d42b76081 100644 --- a/apps/macos/Sources/Clawdbot/DiagnosticsFileLog.swift +++ b/apps/macos/Sources/Clawdbot/DiagnosticsFileLog.swift @@ -20,8 +20,8 @@ actor DiagnosticsFileLog { } nonisolated static func logDirectoryURL() -> URL { - let library = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first - ?? FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent("Library", isDirectory: true) + let library = FileManager().urls(for: .libraryDirectory, in: .userDomainMask).first + ?? FileManager().homeDirectoryForCurrentUser.appendingPathComponent("Library", isDirectory: true) return library .appendingPathComponent("Logs", isDirectory: true) .appendingPathComponent("Clawdbot", isDirectory: true) @@ -43,7 +43,7 @@ actor DiagnosticsFileLog { } func clear() throws { - let fm = FileManager.default + let fm = FileManager() let base = Self.logFileURL() if fm.fileExists(atPath: base.path) { try fm.removeItem(at: base) @@ -67,7 +67,7 @@ actor DiagnosticsFileLog { } private func ensureDirectory() throws { - try FileManager.default.createDirectory( + try FileManager().createDirectory( at: Self.logDirectoryURL(), withIntermediateDirectories: true) } @@ -79,7 +79,7 @@ actor DiagnosticsFileLog { line.append(data) line.append(0x0A) // newline - let fm = FileManager.default + let fm = FileManager() if !fm.fileExists(atPath: url.path) { fm.createFile(atPath: url.path, contents: nil) } @@ -92,13 +92,13 @@ actor DiagnosticsFileLog { private func rotateIfNeeded() throws { let url = Self.logFileURL() - guard let attrs = try? FileManager.default.attributesOfItem(atPath: url.path), + guard let attrs = try? FileManager().attributesOfItem(atPath: url.path), let size = attrs[.size] as? NSNumber else { return } if size.int64Value < self.maxBytes { return } - let fm = FileManager.default + let fm = FileManager() let oldest = self.rotatedURL(index: self.maxBackups) if fm.fileExists(atPath: oldest.path) { diff --git a/apps/macos/Sources/Clawdbot/ExecApprovals.swift b/apps/macos/Sources/Clawdbot/ExecApprovals.swift index 907490ba5..3647b5d82 100644 --- a/apps/macos/Sources/Clawdbot/ExecApprovals.swift +++ b/apps/macos/Sources/Clawdbot/ExecApprovals.swift @@ -176,7 +176,7 @@ enum ExecApprovalsStore { static func readSnapshot() -> ExecApprovalsSnapshot { let url = self.fileURL() - guard FileManager.default.fileExists(atPath: url.path) else { + guard FileManager().fileExists(atPath: url.path) else { return ExecApprovalsSnapshot( path: url.path, exists: false, @@ -216,7 +216,7 @@ enum ExecApprovalsStore { static func loadFile() -> ExecApprovalsFile { let url = self.fileURL() - guard FileManager.default.fileExists(atPath: url.path) else { + guard FileManager().fileExists(atPath: url.path) else { return ExecApprovalsFile(version: 1, socket: nil, defaults: nil, agents: [:]) } do { @@ -238,11 +238,11 @@ enum ExecApprovalsStore { encoder.outputFormatting = [.prettyPrinted, .sortedKeys] let data = try encoder.encode(file) let url = self.fileURL() - try FileManager.default.createDirectory( + try FileManager().createDirectory( at: url.deletingLastPathComponent(), withIntermediateDirectories: true) try data.write(to: url, options: [.atomic]) - try? FileManager.default.setAttributes([.posixPermissions: 0o600], ofItemAtPath: url.path) + try? FileManager().setAttributes([.posixPermissions: 0o600], ofItemAtPath: url.path) } catch { self.logger.error("exec approvals save failed: \(error.localizedDescription, privacy: .public)") } @@ -442,11 +442,11 @@ enum ExecApprovalsStore { private static func expandPath(_ raw: String) -> String { let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) if trimmed == "~" { - return FileManager.default.homeDirectoryForCurrentUser.path + return FileManager().homeDirectoryForCurrentUser.path } if trimmed.hasPrefix("~/") { let suffix = trimmed.dropFirst(2) - return FileManager.default.homeDirectoryForCurrentUser + return FileManager().homeDirectoryForCurrentUser .appendingPathComponent(String(suffix)).path } return trimmed @@ -497,7 +497,7 @@ struct ExecCommandResolution: Sendable { return expanded } let base = cwd?.trimmingCharacters(in: .whitespacesAndNewlines) - let root = (base?.isEmpty == false) ? base! : FileManager.default.currentDirectoryPath + let root = (base?.isEmpty == false) ? base! : FileManager().currentDirectoryPath return URL(fileURLWithPath: root).appendingPathComponent(expanded).path } let searchPaths = self.searchPaths(from: env) diff --git a/apps/macos/Sources/Clawdbot/GatewayEndpointStore.swift b/apps/macos/Sources/Clawdbot/GatewayEndpointStore.swift index 031f3dc22..b28f8fe3a 100644 --- a/apps/macos/Sources/Clawdbot/GatewayEndpointStore.swift +++ b/apps/macos/Sources/Clawdbot/GatewayEndpointStore.swift @@ -155,7 +155,8 @@ actor GatewayEndpointStore { let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) if !trimmed.isEmpty { if let configToken = self.resolveConfigToken(isRemote: isRemote, root: root), - !configToken.isEmpty + !configToken.isEmpty, + configToken != trimmed { self.warnEnvOverrideOnce( kind: .token, @@ -164,32 +165,19 @@ actor GatewayEndpointStore { } return trimmed } - if isRemote { - if let gateway = root["gateway"] as? [String: Any], - let remote = gateway["remote"] as? [String: Any], - let token = remote["token"] as? String - { - let value = token.trimmingCharacters(in: .whitespacesAndNewlines) - if !value.isEmpty { - return value - } - } - return nil - } - if let gateway = root["gateway"] as? [String: Any], - let auth = gateway["auth"] as? [String: Any], - let token = auth["token"] as? String + + if let configToken = self.resolveConfigToken(isRemote: isRemote, root: root), + !configToken.isEmpty { - let value = token.trimmingCharacters(in: .whitespacesAndNewlines) - if !value.isEmpty { - return value - } + return configToken } + if let token = launchdSnapshot?.token?.trimmingCharacters(in: .whitespacesAndNewlines), !token.isEmpty { return token } + return nil } diff --git a/apps/macos/Sources/Clawdbot/GatewayLaunchAgentManager.swift b/apps/macos/Sources/Clawdbot/GatewayLaunchAgentManager.swift index 700b79f19..6031677ea 100644 --- a/apps/macos/Sources/Clawdbot/GatewayLaunchAgentManager.swift +++ b/apps/macos/Sources/Clawdbot/GatewayLaunchAgentManager.swift @@ -5,7 +5,7 @@ enum GatewayLaunchAgentManager { private static let disableLaunchAgentMarker = ".clawdbot/disable-launchagent" private static var plistURL: URL { - FileManager.default.homeDirectoryForCurrentUser + FileManager().homeDirectoryForCurrentUser .appendingPathComponent("Library/LaunchAgents/\(gatewayLaunchdLabel).plist") } @@ -67,9 +67,9 @@ enum GatewayLaunchAgentManager { extension GatewayLaunchAgentManager { private static func isLaunchAgentWriteDisabled() -> Bool { - let marker = FileManager.default.homeDirectoryForCurrentUser + let marker = FileManager().homeDirectoryForCurrentUser .appendingPathComponent(self.disableLaunchAgentMarker) - return FileManager.default.fileExists(atPath: marker.path) + return FileManager().fileExists(atPath: marker.path) } private static func readDaemonLoaded() async -> Bool? { diff --git a/apps/macos/Sources/Clawdbot/GatewayProcessManager.swift b/apps/macos/Sources/Clawdbot/GatewayProcessManager.swift index 35d81243b..9c1761544 100644 --- a/apps/macos/Sources/Clawdbot/GatewayProcessManager.swift +++ b/apps/macos/Sources/Clawdbot/GatewayProcessManager.swift @@ -365,7 +365,7 @@ final class GatewayProcessManager { func clearLog() { self.log = "" - try? FileManager.default.removeItem(atPath: GatewayLaunchAgentManager.launchdGatewayLogPath()) + try? FileManager().removeItem(atPath: GatewayLaunchAgentManager.launchdGatewayLogPath()) self.logger.debug("gateway log cleared") } @@ -378,7 +378,7 @@ final class GatewayProcessManager { } private nonisolated static func readGatewayLog(path: String, limit: Int) -> String { - guard FileManager.default.fileExists(atPath: path) else { return "" } + guard FileManager().fileExists(atPath: path) else { return "" } guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else { return "" } let text = String(data: data, encoding: .utf8) ?? "" if text.count <= limit { return text } diff --git a/apps/macos/Sources/Clawdbot/LaunchAgentManager.swift b/apps/macos/Sources/Clawdbot/LaunchAgentManager.swift index 2d2c3342a..ca967a133 100644 --- a/apps/macos/Sources/Clawdbot/LaunchAgentManager.swift +++ b/apps/macos/Sources/Clawdbot/LaunchAgentManager.swift @@ -3,17 +3,17 @@ import Foundation enum LaunchAgentManager { private static let legacyLaunchdLabel = "com.steipete.clawdbot" private static var plistURL: URL { - FileManager.default.homeDirectoryForCurrentUser + FileManager().homeDirectoryForCurrentUser .appendingPathComponent("Library/LaunchAgents/com.clawdbot.mac.plist") } private static var legacyPlistURL: URL { - FileManager.default.homeDirectoryForCurrentUser + FileManager().homeDirectoryForCurrentUser .appendingPathComponent("Library/LaunchAgents/\(legacyLaunchdLabel).plist") } static func status() async -> Bool { - guard FileManager.default.fileExists(atPath: self.plistURL.path) else { return false } + guard FileManager().fileExists(atPath: self.plistURL.path) else { return false } let result = await self.runLaunchctl(["print", "gui/\(getuid())/\(launchdLabel)"]) return result == 0 } @@ -21,7 +21,7 @@ enum LaunchAgentManager { static func set(enabled: Bool, bundlePath: String) async { if enabled { _ = await self.runLaunchctl(["bootout", "gui/\(getuid())/\(self.legacyLaunchdLabel)"]) - try? FileManager.default.removeItem(at: self.legacyPlistURL) + try? FileManager().removeItem(at: self.legacyPlistURL) self.writePlist(bundlePath: bundlePath) _ = await self.runLaunchctl(["bootout", "gui/\(getuid())/\(launchdLabel)"]) _ = await self.runLaunchctl(["bootstrap", "gui/\(getuid())", self.plistURL.path]) @@ -29,7 +29,7 @@ enum LaunchAgentManager { } else { // Disable autostart going forward but leave the current app running. // bootout would terminate the launchd job immediately (and crash the app if launched via agent). - try? FileManager.default.removeItem(at: self.plistURL) + try? FileManager().removeItem(at: self.plistURL) } } @@ -46,7 +46,7 @@ enum LaunchAgentManager { \(bundlePath)/Contents/MacOS/Clawdbot WorkingDirectory - \(FileManager.default.homeDirectoryForCurrentUser.path) + \(FileManager().homeDirectoryForCurrentUser.path) RunAtLoad KeepAlive diff --git a/apps/macos/Sources/Clawdbot/LogLocator.swift b/apps/macos/Sources/Clawdbot/LogLocator.swift index 8714f7d0c..0ce7eea2f 100644 --- a/apps/macos/Sources/Clawdbot/LogLocator.swift +++ b/apps/macos/Sources/Clawdbot/LogLocator.swift @@ -18,7 +18,7 @@ enum LogLocator { } private static func ensureLogDirExists() { - try? FileManager.default.createDirectory(at: self.logDir, withIntermediateDirectories: true) + try? FileManager().createDirectory(at: self.logDir, withIntermediateDirectories: true) } private static func modificationDate(for url: URL) -> Date { @@ -28,7 +28,7 @@ enum LogLocator { /// Returns the newest log file under /tmp/clawdbot/ (rolling or stdout), or nil if none exist. static func bestLogFile() -> URL? { self.ensureLogDirExists() - let fm = FileManager.default + let fm = FileManager() let files = (try? fm.contentsOfDirectory( at: self.logDir, includingPropertiesForKeys: [.contentModificationDateKey], diff --git a/apps/macos/Sources/Clawdbot/ModelCatalogLoader.swift b/apps/macos/Sources/Clawdbot/ModelCatalogLoader.swift index bf55c564e..48001b4e9 100644 --- a/apps/macos/Sources/Clawdbot/ModelCatalogLoader.swift +++ b/apps/macos/Sources/Clawdbot/ModelCatalogLoader.swift @@ -2,7 +2,7 @@ import Foundation import JavaScriptCore enum ModelCatalogLoader { - static let defaultPath: String = FileManager.default.homeDirectoryForCurrentUser + static let defaultPath: String = FileManager().homeDirectoryForCurrentUser .appendingPathComponent("Projects/pi-mono/packages/ai/src/models.generated.ts").path private static let logger = Logger(subsystem: "com.clawdbot", category: "models") diff --git a/apps/macos/Sources/Clawdbot/NodeMode/MacNodeRuntime.swift b/apps/macos/Sources/Clawdbot/NodeMode/MacNodeRuntime.swift index 51f6c8e82..16f340415 100644 --- a/apps/macos/Sources/Clawdbot/NodeMode/MacNodeRuntime.swift +++ b/apps/macos/Sources/Clawdbot/NodeMode/MacNodeRuntime.swift @@ -133,7 +133,7 @@ actor MacNodeRuntime { let sessionKey = self.mainSessionKey let path = try await CanvasManager.shared.snapshot(sessionKey: sessionKey, outPath: nil) - defer { try? FileManager.default.removeItem(atPath: path) } + defer { try? FileManager().removeItem(atPath: path) } let data = try Data(contentsOf: URL(fileURLWithPath: path)) guard let image = NSImage(data: data) else { return Self.errorResponse(req, code: .unavailable, message: "canvas snapshot decode failed") @@ -206,7 +206,7 @@ actor MacNodeRuntime { includeAudio: params.includeAudio ?? true, deviceId: params.deviceId, outPath: nil) - defer { try? FileManager.default.removeItem(atPath: res.path) } + defer { try? FileManager().removeItem(atPath: res.path) } let data = try Data(contentsOf: URL(fileURLWithPath: res.path)) struct ClipPayload: Encodable { var format: String @@ -312,7 +312,7 @@ actor MacNodeRuntime { fps: params.fps, includeAudio: params.includeAudio, outPath: nil) - defer { try? FileManager.default.removeItem(atPath: res.path) } + defer { try? FileManager().removeItem(atPath: res.path) } let data = try Data(contentsOf: URL(fileURLWithPath: res.path)) struct ScreenPayload: Encodable { var format: String diff --git a/apps/macos/Sources/Clawdbot/PortGuardian.swift b/apps/macos/Sources/Clawdbot/PortGuardian.swift index 071de5b2a..50d4e0e9f 100644 --- a/apps/macos/Sources/Clawdbot/PortGuardian.swift +++ b/apps/macos/Sources/Clawdbot/PortGuardian.swift @@ -24,7 +24,7 @@ actor PortGuardian { private var records: [Record] = [] private let logger = Logger(subsystem: "com.clawdbot", category: "portguard") private nonisolated static let appSupportDir: URL = { - let base = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first! + let base = FileManager().urls(for: .applicationSupportDirectory, in: .userDomainMask).first! return base.appendingPathComponent("Clawdbot", isDirectory: true) }() @@ -71,7 +71,7 @@ actor PortGuardian { } func record(port: Int, pid: Int32, command: String, mode: AppState.ConnectionMode) async { - try? FileManager.default.createDirectory(at: Self.appSupportDir, withIntermediateDirectories: true) + try? FileManager().createDirectory(at: Self.appSupportDir, withIntermediateDirectories: true) self.records.removeAll { $0.pid == pid } self.records.append( Record( diff --git a/apps/macos/Sources/Clawdbot/RuntimeLocator.swift b/apps/macos/Sources/Clawdbot/RuntimeLocator.swift index 761c63b17..aadbe2d21 100644 --- a/apps/macos/Sources/Clawdbot/RuntimeLocator.swift +++ b/apps/macos/Sources/Clawdbot/RuntimeLocator.swift @@ -111,7 +111,7 @@ enum RuntimeLocator { // MARK: - Internals private static func findExecutable(named name: String, searchPaths: [String]) -> String? { - let fm = FileManager.default + let fm = FileManager() for dir in searchPaths { let candidate = (dir as NSString).appendingPathComponent(name) if fm.isExecutableFile(atPath: candidate) { diff --git a/apps/macos/Sources/Clawdbot/ScreenRecordService.swift b/apps/macos/Sources/Clawdbot/ScreenRecordService.swift index d48538e26..e0878a5c9 100644 --- a/apps/macos/Sources/Clawdbot/ScreenRecordService.swift +++ b/apps/macos/Sources/Clawdbot/ScreenRecordService.swift @@ -42,10 +42,10 @@ final class ScreenRecordService { if let outPath, !outPath.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { return URL(fileURLWithPath: outPath) } - return FileManager.default.temporaryDirectory + return FileManager().temporaryDirectory .appendingPathComponent("clawdbot-screen-record-\(UUID().uuidString).mp4") }() - try? FileManager.default.removeItem(at: outURL) + try? FileManager().removeItem(at: outURL) let content = try await SCShareableContent.current let displays = content.displays.sorted { $0.displayID < $1.displayID } diff --git a/apps/macos/Sources/Clawdbot/SessionActions.swift b/apps/macos/Sources/Clawdbot/SessionActions.swift index 6315f08c7..6e11c93cb 100644 --- a/apps/macos/Sources/Clawdbot/SessionActions.swift +++ b/apps/macos/Sources/Clawdbot/SessionActions.swift @@ -66,12 +66,12 @@ enum SessionActions { let dir = URL(fileURLWithPath: storePath).deletingLastPathComponent() urls.append(dir.appendingPathComponent("\(sessionId).jsonl")) } - let home = FileManager.default.homeDirectoryForCurrentUser + let home = FileManager().homeDirectoryForCurrentUser urls.append(home.appendingPathComponent(".clawdbot/sessions/\(sessionId).jsonl")) return urls }() - let existing = candidates.first(where: { FileManager.default.fileExists(atPath: $0.path) }) + let existing = candidates.first(where: { FileManager().fileExists(atPath: $0.path) }) guard let url = existing else { let alert = NSAlert() alert.messageText = "Session log not found" diff --git a/apps/macos/Sources/Clawdbot/SessionData.swift b/apps/macos/Sources/Clawdbot/SessionData.swift index 7ce1dc8fc..d4c85a4a2 100644 --- a/apps/macos/Sources/Clawdbot/SessionData.swift +++ b/apps/macos/Sources/Clawdbot/SessionData.swift @@ -246,7 +246,7 @@ enum SessionLoader { static let fallbackContextTokens = 200_000 static let defaultStorePath = standardize( - FileManager.default.homeDirectoryForCurrentUser + FileManager().homeDirectoryForCurrentUser .appendingPathComponent(".clawdbot/sessions/sessions.json").path) static func loadSnapshot( diff --git a/apps/macos/Sources/Clawdbot/SoundEffects.swift b/apps/macos/Sources/Clawdbot/SoundEffects.swift index c1f0cb9b4..b32123829 100644 --- a/apps/macos/Sources/Clawdbot/SoundEffects.swift +++ b/apps/macos/Sources/Clawdbot/SoundEffects.swift @@ -44,7 +44,7 @@ enum SoundEffectCatalog { ] private static let searchRoots: [URL] = [ - FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent("Library/Sounds"), + FileManager().homeDirectoryForCurrentUser.appendingPathComponent("Library/Sounds"), URL(fileURLWithPath: "/Library/Sounds"), URL(fileURLWithPath: "/System/Applications/Mail.app/Contents/Resources"), // Mail “swoosh” URL(fileURLWithPath: "/System/Library/Sounds"), @@ -53,7 +53,7 @@ enum SoundEffectCatalog { private static let discoveredSoundMap: [String: URL] = { var map: [String: URL] = [:] for root in Self.searchRoots { - guard let contents = try? FileManager.default.contentsOfDirectory( + guard let contents = try? FileManager().contentsOfDirectory( at: root, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles]) diff --git a/apps/macos/Sources/Clawdbot/TailscaleService.swift b/apps/macos/Sources/Clawdbot/TailscaleService.swift index 262ac371e..53a3b7109 100644 --- a/apps/macos/Sources/Clawdbot/TailscaleService.swift +++ b/apps/macos/Sources/Clawdbot/TailscaleService.swift @@ -53,7 +53,7 @@ final class TailscaleService { #endif func checkAppInstallation() -> Bool { - let installed = FileManager.default.fileExists(atPath: "/Applications/Tailscale.app") + let installed = FileManager().fileExists(atPath: "/Applications/Tailscale.app") self.logger.info("Tailscale app installed: \(installed)") return installed } diff --git a/apps/macos/Sources/Clawdbot/VoicePushToTalk.swift b/apps/macos/Sources/Clawdbot/VoicePushToTalk.swift index 5984a8641..2bb1ec1f5 100644 --- a/apps/macos/Sources/Clawdbot/VoicePushToTalk.swift +++ b/apps/macos/Sources/Clawdbot/VoicePushToTalk.swift @@ -37,7 +37,7 @@ final class VoicePushToTalkHotkey: @unchecked Sendable { } private func startMonitoring() { - assert(Thread.isMainThread) + // assert(Thread.isMainThread) - Removed for Swift 6 guard self.globalMonitor == nil, self.localMonitor == nil else { return } // Listen-only global monitor; we rely on Input Monitoring permission to receive events. self.globalMonitor = NSEvent.addGlobalMonitorForEvents(matching: .flagsChanged) { [weak self] event in @@ -55,7 +55,7 @@ final class VoicePushToTalkHotkey: @unchecked Sendable { } private func stopMonitoring() { - assert(Thread.isMainThread) + // assert(Thread.isMainThread) - Removed for Swift 6 if let globalMonitor { NSEvent.removeMonitor(globalMonitor) self.globalMonitor = nil @@ -75,15 +75,11 @@ final class VoicePushToTalkHotkey: @unchecked Sendable { } private func withMainThread(_ block: @escaping @Sendable () -> Void) { - if Thread.isMainThread { - block() - } else { - DispatchQueue.main.async(execute: block) - } + DispatchQueue.main.async(execute: block) } private func updateModifierState(keyCode: UInt16, modifierFlags: NSEvent.ModifierFlags) { - assert(Thread.isMainThread) + // assert(Thread.isMainThread) - Removed for Swift 6 // Right Option (keyCode 61) acts as a hold-to-talk modifier. if keyCode == 61 { self.optionDown = modifierFlags.contains(.option) diff --git a/apps/macos/Sources/ClawdbotIPC/IPC.swift b/apps/macos/Sources/ClawdbotIPC/IPC.swift index dc066a10d..5ad0afcd1 100644 --- a/apps/macos/Sources/ClawdbotIPC/IPC.swift +++ b/apps/macos/Sources/ClawdbotIPC/IPC.swift @@ -409,7 +409,7 @@ extension Request: Codable { // Shared transport settings public let controlSocketPath = - FileManager.default + FileManager() .homeDirectoryForCurrentUser .appendingPathComponent("Library/Application Support/clawdbot/control.sock") .path diff --git a/apps/macos/Sources/ClawdbotWizardCLI/main.swift b/apps/macos/Sources/ClawdbotWizardCLI/main.swift index bf328b87c..b94053f65 100644 --- a/apps/macos/Sources/ClawdbotWizardCLI/main.swift +++ b/apps/macos/Sources/ClawdbotWizardCLI/main.swift @@ -187,7 +187,7 @@ private func resolvedPassword(opts: WizardCliOptions, config: GatewayConfig) -> } private func loadGatewayConfig() -> GatewayConfig { - let url = FileManager.default.homeDirectoryForCurrentUser + let url = FileManager().homeDirectoryForCurrentUser .appendingPathComponent(".clawdbot") .appendingPathComponent("clawdbot.json") guard let data = try? Data(contentsOf: url) else { return GatewayConfig() } diff --git a/apps/macos/Tests/ClawdbotIPCTests/AgentWorkspaceTests.swift b/apps/macos/Tests/ClawdbotIPCTests/AgentWorkspaceTests.swift index 320a44c39..9368f643c 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/AgentWorkspaceTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/AgentWorkspaceTests.swift @@ -6,7 +6,7 @@ import Testing struct AgentWorkspaceTests { @Test func displayPathUsesTildeForHome() { - let home = FileManager.default.homeDirectoryForCurrentUser + let home = FileManager().homeDirectoryForCurrentUser #expect(AgentWorkspace.displayPath(for: home) == "~") let inside = home.appendingPathComponent("Projects", isDirectory: true) @@ -28,12 +28,12 @@ struct AgentWorkspaceTests { @Test func bootstrapCreatesAgentsFileWhenMissing() throws { - let tmp = FileManager.default.temporaryDirectory + let tmp = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-ws-\(UUID().uuidString)", isDirectory: true) - defer { try? FileManager.default.removeItem(at: tmp) } + defer { try? FileManager().removeItem(at: tmp) } let agentsURL = try AgentWorkspace.bootstrap(workspaceURL: tmp) - #expect(FileManager.default.fileExists(atPath: agentsURL.path)) + #expect(FileManager().fileExists(atPath: agentsURL.path)) let contents = try String(contentsOf: agentsURL, encoding: .utf8) #expect(contents.contains("# AGENTS.md")) @@ -41,9 +41,9 @@ struct AgentWorkspaceTests { let identityURL = tmp.appendingPathComponent(AgentWorkspace.identityFilename) let userURL = tmp.appendingPathComponent(AgentWorkspace.userFilename) let bootstrapURL = tmp.appendingPathComponent(AgentWorkspace.bootstrapFilename) - #expect(FileManager.default.fileExists(atPath: identityURL.path)) - #expect(FileManager.default.fileExists(atPath: userURL.path)) - #expect(FileManager.default.fileExists(atPath: bootstrapURL.path)) + #expect(FileManager().fileExists(atPath: identityURL.path)) + #expect(FileManager().fileExists(atPath: userURL.path)) + #expect(FileManager().fileExists(atPath: bootstrapURL.path)) let second = try AgentWorkspace.bootstrap(workspaceURL: tmp) #expect(second == agentsURL) @@ -51,10 +51,10 @@ struct AgentWorkspaceTests { @Test func bootstrapSafetyRejectsNonEmptyFolderWithoutAgents() throws { - let tmp = FileManager.default.temporaryDirectory + let tmp = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-ws-\(UUID().uuidString)", isDirectory: true) - defer { try? FileManager.default.removeItem(at: tmp) } - try FileManager.default.createDirectory(at: tmp, withIntermediateDirectories: true) + defer { try? FileManager().removeItem(at: tmp) } + try FileManager().createDirectory(at: tmp, withIntermediateDirectories: true) let marker = tmp.appendingPathComponent("notes.txt") try "hello".write(to: marker, atomically: true, encoding: .utf8) @@ -69,10 +69,10 @@ struct AgentWorkspaceTests { @Test func bootstrapSafetyAllowsExistingAgentsFile() throws { - let tmp = FileManager.default.temporaryDirectory + let tmp = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-ws-\(UUID().uuidString)", isDirectory: true) - defer { try? FileManager.default.removeItem(at: tmp) } - try FileManager.default.createDirectory(at: tmp, withIntermediateDirectories: true) + defer { try? FileManager().removeItem(at: tmp) } + try FileManager().createDirectory(at: tmp, withIntermediateDirectories: true) let agents = tmp.appendingPathComponent(AgentWorkspace.agentsFilename) try "# AGENTS.md".write(to: agents, atomically: true, encoding: .utf8) @@ -87,25 +87,25 @@ struct AgentWorkspaceTests { @Test func bootstrapSkipsBootstrapFileWhenWorkspaceHasContent() throws { - let tmp = FileManager.default.temporaryDirectory + let tmp = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-ws-\(UUID().uuidString)", isDirectory: true) - defer { try? FileManager.default.removeItem(at: tmp) } - try FileManager.default.createDirectory(at: tmp, withIntermediateDirectories: true) + defer { try? FileManager().removeItem(at: tmp) } + try FileManager().createDirectory(at: tmp, withIntermediateDirectories: true) let marker = tmp.appendingPathComponent("notes.txt") try "hello".write(to: marker, atomically: true, encoding: .utf8) _ = try AgentWorkspace.bootstrap(workspaceURL: tmp) let bootstrapURL = tmp.appendingPathComponent(AgentWorkspace.bootstrapFilename) - #expect(!FileManager.default.fileExists(atPath: bootstrapURL.path)) + #expect(!FileManager().fileExists(atPath: bootstrapURL.path)) } @Test func needsBootstrapFalseWhenIdentityAlreadySet() throws { - let tmp = FileManager.default.temporaryDirectory + let tmp = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-ws-\(UUID().uuidString)", isDirectory: true) - defer { try? FileManager.default.removeItem(at: tmp) } - try FileManager.default.createDirectory(at: tmp, withIntermediateDirectories: true) + defer { try? FileManager().removeItem(at: tmp) } + try FileManager().createDirectory(at: tmp, withIntermediateDirectories: true) let identityURL = tmp.appendingPathComponent(AgentWorkspace.identityFilename) try """ # IDENTITY.md - Agent Identity diff --git a/apps/macos/Tests/ClawdbotIPCTests/AnthropicAuthResolverTests.swift b/apps/macos/Tests/ClawdbotIPCTests/AnthropicAuthResolverTests.swift index 41f9ffefb..1af9108c2 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/AnthropicAuthResolverTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/AnthropicAuthResolverTests.swift @@ -6,9 +6,9 @@ import Testing struct AnthropicAuthResolverTests { @Test func prefersOAuthFileOverEnv() throws { - let dir = FileManager.default.temporaryDirectory + let dir = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-oauth-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try FileManager().createDirectory(at: dir, withIntermediateDirectories: true) let oauthFile = dir.appendingPathComponent("oauth.json") let payload = [ "anthropic": [ diff --git a/apps/macos/Tests/ClawdbotIPCTests/CLIInstallerTests.swift b/apps/macos/Tests/ClawdbotIPCTests/CLIInstallerTests.swift index 829dd28a4..46144a455 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/CLIInstallerTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/CLIInstallerTests.swift @@ -6,7 +6,7 @@ import Testing @MainActor struct CLIInstallerTests { @Test func installedLocationFindsExecutable() throws { - let fm = FileManager.default + let fm = FileManager() let root = fm.temporaryDirectory.appendingPathComponent( "clawdbot-cli-installer-\(UUID().uuidString)") defer { try? fm.removeItem(at: root) } diff --git a/apps/macos/Tests/ClawdbotIPCTests/CanvasFileWatcherTests.swift b/apps/macos/Tests/ClawdbotIPCTests/CanvasFileWatcherTests.swift index 03fe58fda..28093abc8 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/CanvasFileWatcherTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/CanvasFileWatcherTests.swift @@ -7,13 +7,13 @@ import Testing private func makeTempDir() throws -> URL { let base = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) let dir = base.appendingPathComponent("clawdbot-canvaswatch-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try FileManager().createDirectory(at: dir, withIntermediateDirectories: true) return dir } @Test func detectsInPlaceFileWrites() async throws { let dir = try self.makeTempDir() - defer { try? FileManager.default.removeItem(at: dir) } + defer { try? FileManager().removeItem(at: dir) } let file = dir.appendingPathComponent("index.html") try "hello".write(to: file, atomically: false, encoding: .utf8) diff --git a/apps/macos/Tests/ClawdbotIPCTests/CanvasWindowSmokeTests.swift b/apps/macos/Tests/ClawdbotIPCTests/CanvasWindowSmokeTests.swift index 1168802b2..92f20bf0b 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/CanvasWindowSmokeTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/CanvasWindowSmokeTests.swift @@ -8,10 +8,10 @@ import Testing @MainActor struct CanvasWindowSmokeTests { @Test func panelControllerShowsAndHides() async throws { - let root = FileManager.default.temporaryDirectory + let root = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-canvas-test-\(UUID().uuidString)") - try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: root) } + try FileManager().createDirectory(at: root, withIntermediateDirectories: true) + defer { try? FileManager().removeItem(at: root) } let anchor = { NSRect(x: 200, y: 400, width: 40, height: 40) } let controller = try CanvasWindowController( @@ -31,10 +31,10 @@ struct CanvasWindowSmokeTests { } @Test func windowControllerShowsAndCloses() async throws { - let root = FileManager.default.temporaryDirectory + let root = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-canvas-test-\(UUID().uuidString)") - try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: root) } + try FileManager().createDirectory(at: root, withIntermediateDirectories: true) + defer { try? FileManager().removeItem(at: root) } let controller = try CanvasWindowController( sessionKey: "main", diff --git a/apps/macos/Tests/ClawdbotIPCTests/ClawdbotConfigFileTests.swift b/apps/macos/Tests/ClawdbotIPCTests/ClawdbotConfigFileTests.swift index 513117c72..15a0f3905 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/ClawdbotConfigFileTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/ClawdbotConfigFileTests.swift @@ -6,7 +6,7 @@ import Testing struct ClawdbotConfigFileTests { @Test func configPathRespectsEnvOverride() async { - let override = FileManager.default.temporaryDirectory + let override = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-config-\(UUID().uuidString)") .appendingPathComponent("clawdbot.json") .path @@ -19,7 +19,7 @@ struct ClawdbotConfigFileTests { @MainActor @Test func remoteGatewayPortParsesAndMatchesHost() async { - let override = FileManager.default.temporaryDirectory + let override = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-config-\(UUID().uuidString)") .appendingPathComponent("clawdbot.json") .path @@ -42,7 +42,7 @@ struct ClawdbotConfigFileTests { @MainActor @Test func setRemoteGatewayUrlPreservesScheme() async { - let override = FileManager.default.temporaryDirectory + let override = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-config-\(UUID().uuidString)") .appendingPathComponent("clawdbot.json") .path @@ -64,7 +64,7 @@ struct ClawdbotConfigFileTests { @Test func stateDirOverrideSetsConfigPath() async { - let dir = FileManager.default.temporaryDirectory + let dir = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-state-\(UUID().uuidString)", isDirectory: true) .path diff --git a/apps/macos/Tests/ClawdbotIPCTests/ClawdbotOAuthStoreTests.swift b/apps/macos/Tests/ClawdbotIPCTests/ClawdbotOAuthStoreTests.swift index 4f4c8542a..0fcfdec84 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/ClawdbotOAuthStoreTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/ClawdbotOAuthStoreTests.swift @@ -6,7 +6,7 @@ import Testing struct ClawdbotOAuthStoreTests { @Test func returnsMissingWhenFileAbsent() { - let url = FileManager.default.temporaryDirectory + let url = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-oauth-\(UUID().uuidString)") .appendingPathComponent("oauth.json") #expect(ClawdbotOAuthStore.anthropicOAuthStatus(at: url) == .missingFile) @@ -24,7 +24,7 @@ struct ClawdbotOAuthStoreTests { } } - let dir = FileManager.default.temporaryDirectory + let dir = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-oauth-\(UUID().uuidString)", isDirectory: true) setenv(key, dir.path, 1) @@ -85,9 +85,9 @@ struct ClawdbotOAuthStoreTests { } private func writeOAuthFile(_ json: [String: Any]) throws -> URL { - let dir = FileManager.default.temporaryDirectory + let dir = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-oauth-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try FileManager().createDirectory(at: dir, withIntermediateDirectories: true) let url = dir.appendingPathComponent("oauth.json") let data = try JSONSerialization.data(withJSONObject: json, options: [.prettyPrinted, .sortedKeys]) diff --git a/apps/macos/Tests/ClawdbotIPCTests/CommandResolverTests.swift b/apps/macos/Tests/ClawdbotIPCTests/CommandResolverTests.swift index 8feb00f12..827057888 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/CommandResolverTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/CommandResolverTests.swift @@ -12,16 +12,16 @@ import Testing private func makeTempDir() throws -> URL { let base = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) let dir = base.appendingPathComponent(UUID().uuidString, isDirectory: true) - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try FileManager().createDirectory(at: dir, withIntermediateDirectories: true) return dir } private func makeExec(at path: URL) throws { - try FileManager.default.createDirectory( + try FileManager().createDirectory( at: path.deletingLastPathComponent(), withIntermediateDirectories: true) - FileManager.default.createFile(atPath: path.path, contents: Data("echo ok\n".utf8)) - try FileManager.default.setAttributes([.posixPermissions: 0o755], ofItemAtPath: path.path) + FileManager().createFile(atPath: path.path, contents: Data("echo ok\n".utf8)) + try FileManager().setAttributes([.posixPermissions: 0o755], ofItemAtPath: path.path) } @Test func prefersClawdbotBinary() async throws { @@ -49,7 +49,7 @@ import Testing let scriptPath = tmp.appendingPathComponent("bin/clawdbot.js") try self.makeExec(at: nodePath) try "#!/bin/sh\necho v22.0.0\n".write(to: nodePath, atomically: true, encoding: .utf8) - try FileManager.default.setAttributes([.posixPermissions: 0o755], ofItemAtPath: nodePath.path) + try FileManager().setAttributes([.posixPermissions: 0o755], ofItemAtPath: nodePath.path) try self.makeExec(at: scriptPath) let cmd = CommandResolver.clawdbotCommand( diff --git a/apps/macos/Tests/ClawdbotIPCTests/FileHandleLegacyAPIGuardTests.swift b/apps/macos/Tests/ClawdbotIPCTests/FileHandleLegacyAPIGuardTests.swift index 5e30cf584..2de87f693 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/FileHandleLegacyAPIGuardTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/FileHandleLegacyAPIGuardTests.swift @@ -32,7 +32,7 @@ import Testing } private static func swiftFiles(under root: URL) throws -> [URL] { - let fm = FileManager.default + let fm = FileManager() guard let enumerator = fm.enumerator(at: root, includingPropertiesForKeys: [.isRegularFileKey]) else { return [] } diff --git a/apps/macos/Tests/ClawdbotIPCTests/GatewayLaunchAgentManagerTests.swift b/apps/macos/Tests/ClawdbotIPCTests/GatewayLaunchAgentManagerTests.swift index ae8357b0c..af41a2a8e 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/GatewayLaunchAgentManagerTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/GatewayLaunchAgentManagerTests.swift @@ -4,7 +4,7 @@ import Testing @Suite struct GatewayLaunchAgentManagerTests { @Test func launchAgentPlistSnapshotParsesArgsAndEnv() throws { - let url = FileManager.default.temporaryDirectory + let url = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-launchd-\(UUID().uuidString).plist") let plist: [String: Any] = [ "ProgramArguments": ["clawdbot", "gateway-daemon", "--port", "18789", "--bind", "loopback"], @@ -15,7 +15,7 @@ import Testing ] let data = try PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0) try data.write(to: url, options: [.atomic]) - defer { try? FileManager.default.removeItem(at: url) } + defer { try? FileManager().removeItem(at: url) } let snapshot = try #require(LaunchAgentPlist.snapshot(url: url)) #expect(snapshot.port == 18789) @@ -25,14 +25,14 @@ import Testing } @Test func launchAgentPlistSnapshotAllowsMissingBind() throws { - let url = FileManager.default.temporaryDirectory + let url = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-launchd-\(UUID().uuidString).plist") let plist: [String: Any] = [ "ProgramArguments": ["clawdbot", "gateway-daemon", "--port", "18789"], ] let data = try PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0) try data.write(to: url, options: [.atomic]) - defer { try? FileManager.default.removeItem(at: url) } + defer { try? FileManager().removeItem(at: url) } let snapshot = try #require(LaunchAgentPlist.snapshot(url: url)) #expect(snapshot.port == 18789) diff --git a/apps/macos/Tests/ClawdbotIPCTests/LogLocatorTests.swift b/apps/macos/Tests/ClawdbotIPCTests/LogLocatorTests.swift index bc29f9e2b..6d87208ea 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/LogLocatorTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/LogLocatorTests.swift @@ -5,7 +5,7 @@ import Testing @Suite struct LogLocatorTests { @Test func launchdGatewayLogPathEnsuresTmpDirExists() throws { - let fm = FileManager.default + let fm = FileManager() let baseDir = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) let logDir = baseDir.appendingPathComponent("clawdbot-tests-\(UUID().uuidString)") diff --git a/apps/macos/Tests/ClawdbotIPCTests/LowCoverageHelperTests.swift b/apps/macos/Tests/ClawdbotIPCTests/LowCoverageHelperTests.swift index b68f98cb9..7d934d6e0 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/LowCoverageHelperTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/LowCoverageHelperTests.swift @@ -77,9 +77,9 @@ struct LowCoverageHelperTests { } @Test func pairedNodesStorePersists() async throws { - let dir = FileManager.default.temporaryDirectory + let dir = FileManager().temporaryDirectory .appendingPathComponent("paired-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try FileManager().createDirectory(at: dir, withIntermediateDirectories: true) let url = dir.appendingPathComponent("nodes.json") let store = PairedNodesStore(fileURL: url) await store.load() @@ -143,12 +143,12 @@ struct LowCoverageHelperTests { } @Test @MainActor func canvasSchemeHandlerResolvesFilesAndErrors() throws { - let root = FileManager.default.temporaryDirectory + let root = FileManager().temporaryDirectory .appendingPathComponent("canvas-\(UUID().uuidString)", isDirectory: true) - defer { try? FileManager.default.removeItem(at: root) } - try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) + defer { try? FileManager().removeItem(at: root) } + try FileManager().createDirectory(at: root, withIntermediateDirectories: true) let session = root.appendingPathComponent("main", isDirectory: true) - try FileManager.default.createDirectory(at: session, withIntermediateDirectories: true) + try FileManager().createDirectory(at: session, withIntermediateDirectories: true) let index = session.appendingPathComponent("index.html") try "

Hello

".write(to: index, atomically: true, encoding: .utf8) diff --git a/apps/macos/Tests/ClawdbotIPCTests/MacNodeRuntimeTests.swift b/apps/macos/Tests/ClawdbotIPCTests/MacNodeRuntimeTests.swift index 12d03c185..6c7343725 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/MacNodeRuntimeTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/MacNodeRuntimeTests.swift @@ -59,7 +59,7 @@ struct MacNodeRuntimeTests { includeAudio: Bool?, outPath: String?) async throws -> (path: String, hasAudio: Bool) { - let url = FileManager.default.temporaryDirectory + let url = FileManager().temporaryDirectory .appendingPathComponent("clawdbot-test-screen-record-\(UUID().uuidString).mp4") try Data("ok".utf8).write(to: url) return (path: url.path, hasAudio: false) diff --git a/apps/macos/Tests/ClawdbotIPCTests/ModelCatalogLoaderTests.swift b/apps/macos/Tests/ClawdbotIPCTests/ModelCatalogLoaderTests.swift index d446dad64..7b87dc5ec 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/ModelCatalogLoaderTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/ModelCatalogLoaderTests.swift @@ -19,9 +19,9 @@ struct ModelCatalogLoaderTests { }; """ - let tmp = FileManager.default.temporaryDirectory + let tmp = FileManager().temporaryDirectory .appendingPathComponent("models-\(UUID().uuidString).ts") - defer { try? FileManager.default.removeItem(at: tmp) } + defer { try? FileManager().removeItem(at: tmp) } try src.write(to: tmp, atomically: true, encoding: .utf8) let choices = try await ModelCatalogLoader.load(from: tmp.path) @@ -42,9 +42,9 @@ struct ModelCatalogLoaderTests { @Test func loadWithNoExportReturnsEmptyChoices() async throws { let src = "const NOPE = 1;" - let tmp = FileManager.default.temporaryDirectory + let tmp = FileManager().temporaryDirectory .appendingPathComponent("models-\(UUID().uuidString).ts") - defer { try? FileManager.default.removeItem(at: tmp) } + defer { try? FileManager().removeItem(at: tmp) } try src.write(to: tmp, atomically: true, encoding: .utf8) let choices = try await ModelCatalogLoader.load(from: tmp.path) diff --git a/apps/macos/Tests/ClawdbotIPCTests/NodeManagerPathsTests.swift b/apps/macos/Tests/ClawdbotIPCTests/NodeManagerPathsTests.swift index 1300cbf7e..bd4a3c0f9 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/NodeManagerPathsTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/NodeManagerPathsTests.swift @@ -6,16 +6,16 @@ import Testing private func makeTempDir() throws -> URL { let base = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) let dir = base.appendingPathComponent(UUID().uuidString, isDirectory: true) - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try FileManager().createDirectory(at: dir, withIntermediateDirectories: true) return dir } private func makeExec(at path: URL) throws { - try FileManager.default.createDirectory( + try FileManager().createDirectory( at: path.deletingLastPathComponent(), withIntermediateDirectories: true) - FileManager.default.createFile(atPath: path.path, contents: Data("echo ok\n".utf8)) - try FileManager.default.setAttributes([.posixPermissions: 0o755], ofItemAtPath: path.path) + FileManager().createFile(atPath: path.path, contents: Data("echo ok\n".utf8)) + try FileManager().setAttributes([.posixPermissions: 0o755], ofItemAtPath: path.path) } @Test func fnmNodeBinsPreferNewestInstalledVersion() throws { @@ -37,7 +37,7 @@ import Testing let home = try self.makeTempDir() let missingNodeBin = home .appendingPathComponent(".local/share/fnm/node-versions/v99.0.0/installation/bin") - try FileManager.default.createDirectory(at: missingNodeBin, withIntermediateDirectories: true) + try FileManager().createDirectory(at: missingNodeBin, withIntermediateDirectories: true) let bins = CommandResolver._testNodeManagerBinPaths(home: home) #expect(!bins.contains(missingNodeBin.path)) diff --git a/apps/macos/Tests/ClawdbotIPCTests/RuntimeLocatorTests.swift b/apps/macos/Tests/ClawdbotIPCTests/RuntimeLocatorTests.swift index c1bcc957f..81d2c7494 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/RuntimeLocatorTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/RuntimeLocatorTests.swift @@ -6,10 +6,10 @@ import Testing private func makeTempExecutable(contents: String) throws -> URL { let dir = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) .appendingPathComponent(UUID().uuidString, isDirectory: true) - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try FileManager().createDirectory(at: dir, withIntermediateDirectories: true) let path = dir.appendingPathComponent("node") try contents.write(to: path, atomically: true, encoding: .utf8) - try FileManager.default.setAttributes([.posixPermissions: 0o755], ofItemAtPath: path.path) + try FileManager().setAttributes([.posixPermissions: 0o755], ofItemAtPath: path.path) return path } diff --git a/apps/macos/Tests/ClawdbotIPCTests/TestIsolation.swift b/apps/macos/Tests/ClawdbotIPCTests/TestIsolation.swift index c15606a06..6207df141 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/TestIsolation.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/TestIsolation.swift @@ -109,7 +109,7 @@ enum TestIsolation { } nonisolated static func tempConfigPath() -> String { - FileManager.default.temporaryDirectory + FileManager().temporaryDirectory .appendingPathComponent("clawdbot-test-config-\(UUID().uuidString).json") .path } diff --git a/apps/macos/Tests/ClawdbotIPCTests/UtilitiesTests.swift b/apps/macos/Tests/ClawdbotIPCTests/UtilitiesTests.swift index 4a01e8aee..7b8753ef1 100644 --- a/apps/macos/Tests/ClawdbotIPCTests/UtilitiesTests.swift +++ b/apps/macos/Tests/ClawdbotIPCTests/UtilitiesTests.swift @@ -47,17 +47,17 @@ import Testing .appendingPathComponent(UUID().uuidString, isDirectory: true) let dist = tmp.appendingPathComponent("dist/index.js") let bin = tmp.appendingPathComponent("bin/clawdbot.js") - try FileManager.default.createDirectory(at: dist.deletingLastPathComponent(), withIntermediateDirectories: true) - try FileManager.default.createDirectory(at: bin.deletingLastPathComponent(), withIntermediateDirectories: true) - FileManager.default.createFile(atPath: dist.path, contents: Data()) - FileManager.default.createFile(atPath: bin.path, contents: Data()) + try FileManager().createDirectory(at: dist.deletingLastPathComponent(), withIntermediateDirectories: true) + try FileManager().createDirectory(at: bin.deletingLastPathComponent(), withIntermediateDirectories: true) + FileManager().createFile(atPath: dist.path, contents: Data()) + FileManager().createFile(atPath: bin.path, contents: Data()) let entry = CommandResolver.gatewayEntrypoint(in: tmp) #expect(entry == dist.path) } @Test func logLocatorPicksNewestLogFile() throws { - let fm = FileManager.default + let fm = FileManager() let dir = URL(fileURLWithPath: "/tmp/clawdbot", isDirectory: true) try? fm.createDirectory(at: dir, withIntermediateDirectories: true) diff --git a/src/canvas-host/a2ui/.bundle.hash b/src/canvas-host/a2ui/.bundle.hash index deb2c89b7..8f2c132f8 100644 --- a/src/canvas-host/a2ui/.bundle.hash +++ b/src/canvas-host/a2ui/.bundle.hash @@ -1 +1 @@ -c51e9080b032ccb0dd153452854f2ffdaca8e1db14d7b98ed56cca8f0f1a5257 +cc37623c53c8c111322d9163926fa430b4f5c56c9d964001bd6d66ea42a2a8bc