diff --git a/clients/shared/Network/AppsClient.swift b/clients/shared/Network/AppsClient.swift index e3f4b277b5c..0553487fd94 100644 --- a/clients/shared/Network/AppsClient.swift +++ b/clients/shared/Network/AppsClient.swift @@ -7,7 +7,6 @@ private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum. /// /// Covers listing, opening, deleting, previewing, bundling, sharing, and /// version history for both local and shared apps. -@MainActor public protocol AppsClientProtocol { func fetchAppsList() async -> AppsListResponse? func openApp(id: String) async -> AppOpenResult? @@ -36,7 +35,6 @@ public struct AppOpenResult: Sendable { } /// Gateway-backed implementation of ``AppsClientProtocol``. -@MainActor public struct AppsClient: AppsClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/BtwClient.swift b/clients/shared/Network/BtwClient.swift index a0e1c809856..2169086d391 100644 --- a/clients/shared/Network/BtwClient.swift +++ b/clients/shared/Network/BtwClient.swift @@ -4,13 +4,11 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "BtwClient") /// Focused client for BTW side-chain messages routed through the gateway. -@MainActor public protocol BtwClientProtocol { func sendMessage(content: String, conversationKey: String) -> AsyncThrowingStream } /// Gateway-backed implementation of ``BtwClientProtocol``. -@MainActor public struct BtwClient: BtwClientProtocol { nonisolated public init() {} @@ -18,7 +16,7 @@ public struct BtwClient: BtwClientProtocol { /// Returns an `AsyncThrowingStream` that yields text deltas from SSE `btw_text_delta` events. public func sendMessage(content: String, conversationKey: String) -> AsyncThrowingStream { return AsyncThrowingStream { continuation in - let task = Task { @MainActor in + let task = Task { do { try await Self.streamBtw(content: content, conversationKey: conversationKey, continuation: continuation) } catch { diff --git a/clients/shared/Network/ChannelClient.swift b/clients/shared/Network/ChannelClient.swift index f48cb389bdc..b2d2b06debf 100644 --- a/clients/shared/Network/ChannelClient.swift +++ b/clients/shared/Network/ChannelClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "ChannelClient") /// Focused client for channel readiness operations routed through the gateway. -@MainActor public protocol ChannelClientProtocol { func fetchChannelReadiness() async -> [String: ChannelReadinessInfo] } @@ -45,7 +44,6 @@ public struct ReadinessCheck: Sendable { } /// Gateway-backed implementation of ``ChannelClientProtocol``. -@MainActor public struct ChannelClient: ChannelClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/ComputerUseClient.swift b/clients/shared/Network/ComputerUseClient.swift index 16b8972de89..9f9bc97c7ad 100644 --- a/clients/shared/Network/ComputerUseClient.swift +++ b/clients/shared/Network/ComputerUseClient.swift @@ -4,14 +4,12 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "ComputerUseClient") /// Focused client for watch observation and recording lifecycle operations via the gateway. -@MainActor public protocol ComputerUseClientProtocol { func sendWatchObservation(_ msg: WatchObservationMessage) async -> Bool func sendRecordingStatus(_ msg: RecordingStatus) async -> Bool } /// Gateway-backed implementation of ``ComputerUseClientProtocol``. -@MainActor public struct ComputerUseClient: ComputerUseClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/ContactClient.swift b/clients/shared/Network/ContactClient.swift index 6a520e29bc7..dbcbf7a2980 100644 --- a/clients/shared/Network/ContactClient.swift +++ b/clients/shared/Network/ContactClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "ContactClient") /// Focused client for contact management operations routed through the gateway. -@MainActor public protocol ContactClientProtocol { func updateContact( contactId: String, @@ -51,7 +50,6 @@ public struct NewContactChannel: Codable { } /// Gateway-backed implementation of ``ContactClientProtocol``. -@MainActor public struct ContactClient: ContactClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/ConversationClient.swift b/clients/shared/Network/ConversationClient.swift index a3629dcb425..e65ae5575bf 100644 --- a/clients/shared/Network/ConversationClient.swift +++ b/clients/shared/Network/ConversationClient.swift @@ -4,13 +4,11 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "ConversationClient") /// Focused client for conversation-related operations routed through the gateway. -@MainActor public protocol ConversationClientProtocol { func fetchMessageContent(conversationId: String, messageId: String) async -> MessageContentResponse? } /// Gateway-backed implementation of ``ConversationClientProtocol``. -@MainActor public struct ConversationClient: ConversationClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/ConversationDetailClient.swift b/clients/shared/Network/ConversationDetailClient.swift index 14759ded83c..ed5d6731caf 100644 --- a/clients/shared/Network/ConversationDetailClient.swift +++ b/clients/shared/Network/ConversationDetailClient.swift @@ -4,13 +4,11 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "ConversationDetailClient") /// Focused client for fetching a single conversation summary through the gateway. -@MainActor public protocol ConversationDetailClientProtocol { func fetchConversation(conversationId: String) async -> ConversationListResponseItem? } /// Gateway-backed implementation of ``ConversationDetailClientProtocol``. -@MainActor public struct ConversationDetailClient: ConversationDetailClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/ConversationForkClient.swift b/clients/shared/Network/ConversationForkClient.swift index 96197c51633..e1dc202ad93 100644 --- a/clients/shared/Network/ConversationForkClient.swift +++ b/clients/shared/Network/ConversationForkClient.swift @@ -4,13 +4,11 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "ConversationForkClient") /// Focused client for creating conversation forks through the gateway. -@MainActor public protocol ConversationForkClientProtocol { func forkConversation(conversationId: String, throughMessageId: String?) async -> ConversationListResponseItem? } /// Gateway-backed implementation of ``ConversationForkClientProtocol``. -@MainActor public struct ConversationForkClient: ConversationForkClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/ConversationHistoryClient.swift b/clients/shared/Network/ConversationHistoryClient.swift index 149d7ffb490..a16223cb784 100644 --- a/clients/shared/Network/ConversationHistoryClient.swift +++ b/clients/shared/Network/ConversationHistoryClient.swift @@ -5,13 +5,11 @@ private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum. private let perfLog = OSLog(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: .pointsOfInterest) /// Focused client for conversation history operations routed through the gateway. -@MainActor public protocol ConversationHistoryClientProtocol { func fetchHistory(conversationId: String, limit: Int?, beforeTimestamp: Double?, mode: String?, maxTextChars: Int?, maxToolResultChars: Int?) async -> HistoryResponse? } /// Gateway-backed implementation of ``ConversationHistoryClientProtocol``. -@MainActor public struct ConversationHistoryClient: ConversationHistoryClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/ConversationListClient.swift b/clients/shared/Network/ConversationListClient.swift index 21a4389dbf1..8795d3387bf 100644 --- a/clients/shared/Network/ConversationListClient.swift +++ b/clients/shared/Network/ConversationListClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "ConversationListClient") /// Focused client for conversation list and management operations via the gateway. -@MainActor public protocol ConversationListClientProtocol { func fetchConversationList(offset: Int, limit: Int) async -> ConversationListResponse? func switchConversation(conversationId: String) async -> Bool @@ -18,7 +17,6 @@ public protocol ConversationListClientProtocol { } /// Gateway-backed implementation of ``ConversationListClientProtocol``. -@MainActor public struct ConversationListClient: ConversationListClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/ConversationQueueClient.swift b/clients/shared/Network/ConversationQueueClient.swift index 94c231b7955..258ac075178 100644 --- a/clients/shared/Network/ConversationQueueClient.swift +++ b/clients/shared/Network/ConversationQueueClient.swift @@ -4,13 +4,11 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "ConversationQueueClient") /// Focused client for message queue operations routed through the gateway. -@MainActor public protocol ConversationQueueClientProtocol { func deleteQueuedMessage(conversationId: String, requestId: String) async -> Bool } /// Gateway-backed implementation of ``ConversationQueueClientProtocol``. -@MainActor public struct ConversationQueueClient: ConversationQueueClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/ConversationUnreadClient.swift b/clients/shared/Network/ConversationUnreadClient.swift index 75edfaefcf5..dcf3b55315d 100644 --- a/clients/shared/Network/ConversationUnreadClient.swift +++ b/clients/shared/Network/ConversationUnreadClient.swift @@ -16,13 +16,11 @@ public enum ConversationUnreadError: LocalizedError { } /// Focused client for marking conversations as unread through the gateway. -@MainActor public protocol ConversationUnreadClientProtocol { func sendConversationUnread(_ signal: ConversationUnreadSignal) async throws } /// Gateway-backed implementation of ``ConversationUnreadClientProtocol``. -@MainActor public struct ConversationUnreadClient: ConversationUnreadClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/DiagnosticsClient.swift b/clients/shared/Network/DiagnosticsClient.swift index 3c077ce55da..fc765616e82 100644 --- a/clients/shared/Network/DiagnosticsClient.swift +++ b/clients/shared/Network/DiagnosticsClient.swift @@ -4,13 +4,11 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "DiagnosticsClient") /// Focused client for diagnostics operations routed through the gateway. -@MainActor public protocol DiagnosticsClientProtocol { func fetchEnvVars() async -> EnvVarsResponseMessage? } /// Gateway-backed implementation of ``DiagnosticsClientProtocol``. -@MainActor public struct DiagnosticsClient: DiagnosticsClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/DictationClient.swift b/clients/shared/Network/DictationClient.swift index 600328780fa..e55523ffb9b 100644 --- a/clients/shared/Network/DictationClient.swift +++ b/clients/shared/Network/DictationClient.swift @@ -4,13 +4,11 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "DictationClient") /// Focused client for dictation requests routed through the gateway. -@MainActor public protocol DictationClientProtocol { func process(_ request: DictationRequest) async -> DictationResponseMessage } /// Gateway-backed implementation of ``DictationClientProtocol``. -@MainActor public struct DictationClient: DictationClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/DocumentClient.swift b/clients/shared/Network/DocumentClient.swift index 0dc6e4ec133..8e4147172aa 100644 --- a/clients/shared/Network/DocumentClient.swift +++ b/clients/shared/Network/DocumentClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "DocumentClient") /// Focused client for document persistence operations routed through the gateway. -@MainActor public protocol DocumentClientProtocol { func fetchList(conversationId: String?) async -> DocumentListResponse? func fetchDocument(surfaceId: String) async -> DocumentLoadResponse? @@ -12,7 +11,6 @@ public protocol DocumentClientProtocol { } /// Gateway-backed implementation of ``DocumentClientProtocol``. -@MainActor public struct DocumentClient: DocumentClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/FeatureFlagClient.swift b/clients/shared/Network/FeatureFlagClient.swift index 38c50d3f425..0f1d19c81b7 100644 --- a/clients/shared/Network/FeatureFlagClient.swift +++ b/clients/shared/Network/FeatureFlagClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "FeatureFlagClient") /// Focused client for feature-flag and privacy-config operations routed through the gateway. -@MainActor public protocol FeatureFlagClientProtocol { func getFeatureFlags() async throws -> [AssistantFeatureFlag] func setFeatureFlag(key: String, enabled: Bool) async throws @@ -64,7 +63,6 @@ public enum FeatureFlagError: Error, LocalizedError { // MARK: - Gateway-Backed Implementation /// Gateway-backed implementation of ``FeatureFlagClientProtocol``. -@MainActor public struct FeatureFlagClient: FeatureFlagClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/GatewayConnectionManager.swift b/clients/shared/Network/GatewayConnectionManager.swift index 376e8a8267b..26ce7b9c63a 100644 --- a/clients/shared/Network/GatewayConnectionManager.swift +++ b/clients/shared/Network/GatewayConnectionManager.swift @@ -270,7 +270,7 @@ public final class GatewayConnectionManager: ObservableObject { private func performHealthCheck() async throws { do { - let isManaged = (try? GatewayHTTPClient.isConnectionManaged()) ?? false + let isManaged = (try? await GatewayHTTPClient.isConnectionManaged()) ?? false let healthPath = isManaged ? "assistants/{assistantId}/health" : "health" let response = try await GatewayHTTPClient.get( path: healthPath, @@ -280,8 +280,8 @@ public final class GatewayConnectionManager: ObservableObject { guard response.isSuccess else { if response.statusCode == 401 { - handleAuthenticationFailure() - let isManaged = (try? GatewayHTTPClient.isConnectionManaged()) ?? false + await handleAuthenticationFailure() + let isManaged = (try? await GatewayHTTPClient.isConnectionManaged()) ?? false if isManaged { shouldReconnect = false } @@ -481,8 +481,8 @@ public final class GatewayConnectionManager: ObservableObject { // MARK: - 401 Recovery - private func handleAuthenticationFailure() { - let isManaged = (try? GatewayHTTPClient.isConnectionManaged()) ?? false + private func handleAuthenticationFailure() async { + let isManaged = (try? await GatewayHTTPClient.isConnectionManaged()) ?? false if isManaged { log.warning("401 in managed mode — session token may be expired") eventStreamClient.broadcastMessage(.conversationError(ConversationErrorMessage( diff --git a/clients/shared/Network/GatewayHTTPClient.swift b/clients/shared/Network/GatewayHTTPClient.swift index 2b7566e3d01..257913a3479 100644 --- a/clients/shared/Network/GatewayHTTPClient.swift +++ b/clients/shared/Network/GatewayHTTPClient.swift @@ -10,7 +10,6 @@ private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum. /// /// let response = try await GatewayHTTPClient.get(path: "health") /// let response = try await GatewayHTTPClient.post(path: "assistants/upgrade") -@MainActor public enum GatewayHTTPClient { /// Response from a gateway HTTP request. @@ -225,7 +224,7 @@ public enum GatewayHTTPClient { /// - Returns: A ``DownloadResponse`` with the local file URL and HTTP status code. /// - Throws: `ClientError` if the request cannot be constructed, or network errors from `URLSession`. public static func download(path: String, params: [String: String]? = nil, timeout: TimeInterval = 30) async throws -> DownloadResponse { - let connection = try resolveConnection() + let connection = try await resolveConnection() let request = try buildRequest(path: path, params: params, method: "GET", timeout: timeout, connection: connection) let response = try await executeDownload(request) @@ -240,7 +239,7 @@ public enum GatewayHTTPClient { // Clean up the 401 download only after confirming we will retry. try? FileManager.default.removeItem(at: response.fileURL) - let freshConnection = try resolveConnection() + let freshConnection = try await resolveConnection() let retryRequest = try buildRequest(path: path, params: params, method: "GET", timeout: timeout, connection: freshConnection) return try await executeDownload(retryRequest) } @@ -256,7 +255,7 @@ public enum GatewayHTTPClient { /// - Returns: A tuple of `(URLSession.AsyncBytes, URLResponse)` for streaming consumption. /// - Throws: `ClientError` if the request cannot be constructed, or network errors from `URLSession`. public static func stream(path: String, timeout: TimeInterval = 30) async throws -> (URLSession.AsyncBytes, URLResponse) { - let connection = try resolveConnection() + let connection = try await resolveConnection() var request = try buildRequest(path: path, params: nil, method: "GET", timeout: timeout, connection: connection) request.setValue("text/event-stream", forHTTPHeaderField: "Accept") logOutgoing(request, quiet: false) @@ -279,7 +278,7 @@ public enum GatewayHTTPClient { /// - Returns: A tuple of `(URLSession.AsyncBytes, URLResponse)` for streaming consumption. /// - Throws: `ClientError` if the request cannot be constructed, or network errors from `URLSession`. public static func streamPost(path: String, body: Data, timeout: TimeInterval = 30) async throws -> (URLSession.AsyncBytes, URLResponse) { - let connection = try resolveConnection() + let connection = try await resolveConnection() var request = try buildRequest(path: path, params: nil, method: "POST", timeout: timeout, connection: connection) request.setValue("text/event-stream", forHTTPHeaderField: "Accept") request.httpBody = body @@ -307,7 +306,7 @@ public enum GatewayHTTPClient { /// `URLError(.userAuthenticationRequired)` if credential refresh fails, /// or network errors from `URLSession`. public static func streamPostWithRetry(path: String, body: Data, timeout: TimeInterval = 30) async throws -> (URLSession.AsyncBytes, URLResponse) { - let connection = try resolveConnection() + let connection = try await resolveConnection() var request = try buildRequest(path: path, params: nil, method: "POST", timeout: timeout, connection: connection) request.setValue("text/event-stream", forHTTPHeaderField: "Accept") request.httpBody = body @@ -334,7 +333,7 @@ public enum GatewayHTTPClient { } // Rebuild with fresh credentials from the credential store. - let freshConnection = try resolveConnection() + let freshConnection = try await resolveConnection() var retryRequest = try buildRequest(path: path, params: nil, method: "POST", timeout: timeout, connection: freshConnection) retryRequest.setValue("text/event-stream", forHTTPHeaderField: "Accept") retryRequest.httpBody = body @@ -373,7 +372,7 @@ public enum GatewayHTTPClient { /// - iOS: Uses UserDefaults for managed assistants (`managed_assistant_id` + /// `managed_platform_base_url`) and QR-paired assistants (`gateway_base_url`), /// with tokens from credential storage via `SessionTokenManager` / `ActorTokenManager`. - private static func resolveConnection() throws -> ConnectionInfo { + private static func resolveConnection() async throws -> ConnectionInfo { #if os(macOS) guard let assistant = resolveConnectedAssistant() else { throw ClientError.noConnectedAssistant @@ -383,7 +382,12 @@ public enum GatewayHTTPClient { guard let token = SessionTokenManager.getToken(), !token.isEmpty else { throw ClientError.notAuthenticated } - let baseURL = assistant.runtimeUrl ?? AuthService.shared.baseURL + let baseURL: String + if let runtimeUrl = assistant.runtimeUrl { + baseURL = runtimeUrl + } else { + baseURL = await AuthService.shared.baseURL + } return ConnectionInfo(baseURL: baseURL, authHeader: ("X-Session-Token", token), assistantId: assistant.assistantId, isManaged: true) } else { let token = ActorTokenManager.getToken() @@ -447,8 +451,8 @@ public enum GatewayHTTPClient { /// Callers can use this to decide whether request paths need the /// `assistants/{assistantId}/` scope prefix (required by the platform) or /// should use flat paths (required by non-managed runtimes). - public static func isConnectionManaged() throws -> Bool { - return try resolveConnection().isManaged + public static func isConnectionManaged() async throws -> Bool { + return try await resolveConnection().isManaged } /// Constructs a gateway URL for the given path and query parameters. @@ -462,8 +466,8 @@ public enum GatewayHTTPClient { /// - params: Optional query parameters. /// - Returns: The fully-qualified URL with `{assistantId}` resolved. /// - Throws: `ClientError` if the connection cannot be resolved or the URL is invalid. - public static func buildURL(path: String, params: [String: String]? = nil) throws -> URL { - let connection = try resolveConnection() + public static func buildURL(path: String, params: [String: String]? = nil) async throws -> URL { + let connection = try await resolveConnection() return try constructURL(path: path, params: params, connection: connection) } @@ -595,7 +599,7 @@ public enum GatewayHTTPClient { quiet: Bool = false, configure: ((_ request: inout URLRequest) -> Void)? = nil ) async throws -> Response { - let connection = try resolveConnection() + let connection = try await resolveConnection() var request = try buildRequest(path: path, params: params, method: method, timeout: timeout, connection: connection) configure?(&request) let response = try await execute(request, quiet: quiet) @@ -609,7 +613,7 @@ public enum GatewayHTTPClient { } // Rebuild with fresh credentials from the credential store. - let freshConnection = try resolveConnection() + let freshConnection = try await resolveConnection() var retryRequest = try buildRequest(path: path, params: params, method: method, timeout: timeout, connection: freshConnection) configure?(&retryRequest) return try await execute(retryRequest, quiet: quiet) diff --git a/clients/shared/Network/GuardianClient.swift b/clients/shared/Network/GuardianClient.swift index 75a920d5e61..ea896649180 100644 --- a/clients/shared/Network/GuardianClient.swift +++ b/clients/shared/Network/GuardianClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "GuardianClient") /// Focused client for guardian operations routed through the gateway. -@MainActor public protocol GuardianClientProtocol { func fetchPendingActions(conversationId: String) async -> GuardianActionsPendingResponseMessage? func submitDecision(requestId: String, action: String, conversationId: String?) async -> GuardianActionDecisionResponseMessage? @@ -12,7 +11,6 @@ public protocol GuardianClientProtocol { } /// Gateway-backed implementation of ``GuardianClientProtocol``. -@MainActor public struct GuardianClient: GuardianClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/HealthCheckClient.swift b/clients/shared/Network/HealthCheckClient.swift index 8d0d818f00b..e2d29245841 100644 --- a/clients/shared/Network/HealthCheckClient.swift +++ b/clients/shared/Network/HealthCheckClient.swift @@ -8,7 +8,6 @@ private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum. /// Local assistants are checked by hitting their own gateway's `/readyz` endpoint /// directly (unauthenticated). Remote/managed assistants route through /// `GatewayHTTPClient` which handles URL resolution, authentication, and 401 retry. -@MainActor public enum HealthCheckClient { /// Check whether the currently connected assistant is reachable. diff --git a/clients/shared/Network/HeartbeatClient.swift b/clients/shared/Network/HeartbeatClient.swift index 221e8b94783..2285f44e876 100644 --- a/clients/shared/Network/HeartbeatClient.swift +++ b/clients/shared/Network/HeartbeatClient.swift @@ -7,7 +7,6 @@ private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum. /// /// Covers heartbeat configuration, run history, on-demand runs, and checklist /// management. -@MainActor public protocol HeartbeatClientProtocol { func fetchConfig() async -> HeartbeatConfigResponse? func updateConfig(enabled: Bool?, intervalMs: Double?, activeHoursStart: Double?, activeHoursEnd: Double?) async -> HeartbeatConfigResponse? @@ -18,7 +17,6 @@ public protocol HeartbeatClientProtocol { } /// Gateway-backed implementation of ``HeartbeatClientProtocol``. -@MainActor public struct HeartbeatClient: HeartbeatClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/HostProxyClient.swift b/clients/shared/Network/HostProxyClient.swift index d2bbbb85aee..3168c871d97 100644 --- a/clients/shared/Network/HostProxyClient.swift +++ b/clients/shared/Network/HostProxyClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "HostProxyClient") /// Focused client for posting host proxy execution results back to the gateway. -@MainActor public protocol HostProxyClientProtocol { func postBashResult(_ result: HostBashResultPayload) async -> Bool func postFileResult(_ result: HostFileResultPayload) async -> Bool @@ -12,7 +11,6 @@ public protocol HostProxyClientProtocol { } /// Gateway-backed implementation of ``HostProxyClientProtocol``. -@MainActor public struct HostProxyClient: HostProxyClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/HostToolExecutor.swift b/clients/shared/Network/HostToolExecutor.swift index 6e6ce314173..77218571834 100644 --- a/clients/shared/Network/HostToolExecutor.swift +++ b/clients/shared/Network/HostToolExecutor.swift @@ -48,7 +48,6 @@ public enum HostToolExecutor { /// Execute a host bash request locally and post the result back to the daemon. /// Spawns `/bin/bash -c -- ` via `Foundation.Process`, enforces a /// timeout, and collects stdout/stderr. - @MainActor public static func executeHostBashRequest(_ request: HostBashRequest) { Task.detached { // If already cancelled before we start, skip entirely @@ -234,7 +233,6 @@ public enum HostToolExecutor { #if os(macOS) /// Execute a host file request locally and post the result back to the daemon. /// Dispatches by operation: read, write, or edit. - @MainActor public static func executeHostFileRequest(_ request: HostFileRequest) { Task.detached { // Check cancellation BEFORE performing the file operation to prevent diff --git a/clients/shared/Network/IdentityClient.swift b/clients/shared/Network/IdentityClient.swift index 5983b82b1b4..8ddb65372f5 100644 --- a/clients/shared/Network/IdentityClient.swift +++ b/clients/shared/Network/IdentityClient.swift @@ -29,7 +29,6 @@ public struct RemoteIdentityInfo: Decodable { } /// Focused client for fetching remote assistant identity via the gateway. -@MainActor public protocol IdentityClientProtocol { func fetchRemoteIdentity() async -> RemoteIdentityInfo? func fetchIdentity() async -> IdentityGetResponse? @@ -37,7 +36,6 @@ public protocol IdentityClientProtocol { } /// Gateway-backed implementation of ``IdentityClientProtocol``. -@MainActor public struct IdentityClient: IdentityClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/IntegrationClient.swift b/clients/shared/Network/IntegrationClient.swift index 8e5467cc095..8fef2091b37 100644 --- a/clients/shared/Network/IntegrationClient.swift +++ b/clients/shared/Network/IntegrationClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "IntegrationClient") /// Focused client for integration status operations routed through the gateway. -@MainActor public protocol IntegrationClientProtocol { func fetchIntegrationsStatus() async -> IntegrationsStatusResponse? } @@ -18,7 +17,6 @@ public struct IntegrationsStatusResponse: Decodable, Sendable { } /// Gateway-backed implementation of ``IntegrationClientProtocol``. -@MainActor public struct IntegrationClient: IntegrationClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/InteractionClient.swift b/clients/shared/Network/InteractionClient.swift index 06ba8f4414a..5c2543d1e83 100644 --- a/clients/shared/Network/InteractionClient.swift +++ b/clients/shared/Network/InteractionClient.swift @@ -5,14 +5,12 @@ private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum. /// Focused client for user interaction responses (confirmations, secrets) /// routed through the gateway. -@MainActor public protocol InteractionClientProtocol { func sendConfirmationResponse(requestId: String, decision: String, selectedPattern: String?, selectedScope: String?) async -> Bool func sendSecretResponse(requestId: String, value: String?, delivery: String?) async -> Bool } /// Gateway-backed implementation of ``InteractionClientProtocol``. -@MainActor public struct InteractionClient: InteractionClientProtocol { nonisolated public init() {} @@ -31,7 +29,7 @@ public struct InteractionClient: InteractionClientProtocol { if let selectedPattern { body["selectedPattern"] = selectedPattern } if let selectedScope { body["selectedScope"] = selectedScope } - let path = try Self.approvalPath(endpoint: "confirm") + let path = try await Self.approvalPath(endpoint: "confirm") log.info("[confirm-flow] Sending POST /confirm: requestId=\(requestId, privacy: .public) decision=\(decision, privacy: .public)") let response = try await GatewayHTTPClient.post(path: path, json: body, timeout: 10) if !response.isSuccess { @@ -80,7 +78,7 @@ public struct InteractionClient: InteractionClientProtocol { body["value"] = value ?? "" if let delivery { body["delivery"] = delivery } - let path = try Self.approvalPath(endpoint: "secret") + let path = try await Self.approvalPath(endpoint: "secret") let response = try await GatewayHTTPClient.post(path: path, json: body, timeout: 10) if !response.isSuccess { log.error("sendSecretResponse failed (HTTP \(response.statusCode))") @@ -101,8 +99,8 @@ public struct InteractionClient: InteractionClientProtocol { /// Managed connections route through the platform proxy which expects /// `assistants/{assistantId}/`. Non-managed connections (local /// gateway or direct remote runtime) use flat `` paths. - private static func approvalPath(endpoint: String) throws -> String { - let managed = try GatewayHTTPClient.isConnectionManaged() + private static func approvalPath(endpoint: String) async throws -> String { + let managed = try await GatewayHTTPClient.isConnectionManaged() return managed ? "assistants/{assistantId}/\(endpoint)" : endpoint } } diff --git a/clients/shared/Network/LLMContextClient.swift b/clients/shared/Network/LLMContextClient.swift index 46326cb16b8..e1511258f31 100644 --- a/clients/shared/Network/LLMContextClient.swift +++ b/clients/shared/Network/LLMContextClient.swift @@ -525,14 +525,12 @@ public enum LLMContextFetchResult: Sendable { /// Focused client for fetching LLM request/response context for a given message, /// routed through the gateway. -@MainActor public protocol LLMContextClientProtocol { func fetchContext(messageId: String) async -> LLMContextResponse? func fetchContextResult(messageId: String) async throws -> LLMContextFetchResult } /// Gateway-backed implementation of ``LLMContextClientProtocol``. -@MainActor public struct LLMContextClient: LLMContextClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/MemoryItemClient.swift b/clients/shared/Network/MemoryItemClient.swift index 567f18e3f74..a58aeb5ed7d 100644 --- a/clients/shared/Network/MemoryItemClient.swift +++ b/clients/shared/Network/MemoryItemClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "MemoryItemClient") /// Focused client for memory item operations routed through the gateway. -@MainActor public protocol MemoryItemClientProtocol { func fetchMemoryItems( kind: String?, @@ -39,7 +38,6 @@ public protocol MemoryItemClientProtocol { } /// Gateway-backed implementation of ``MemoryItemClientProtocol``. -@MainActor public struct MemoryItemClient: MemoryItemClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/MessageClient.swift b/clients/shared/Network/MessageClient.swift index 009c899c649..49461994480 100644 --- a/clients/shared/Network/MessageClient.swift +++ b/clients/shared/Network/MessageClient.swift @@ -25,14 +25,12 @@ public enum MessageSendResult: Sendable { } /// Focused client for uploading attachments and sending user messages. -@MainActor public protocol MessageClientProtocol { func uploadAttachment(filename: String, mimeType: String, data: String, filePath: String?) async -> AttachmentUploadResult func sendMessage(content: String?, conversationKey: String, attachmentIds: [String], conversationType: String?, automated: Bool?, bypassSecretCheck: Bool?) async -> MessageSendResult } /// Gateway-backed implementation of ``MessageClientProtocol``. -@MainActor public struct MessageClient: MessageClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/NotificationClient.swift b/clients/shared/Network/NotificationClient.swift index fd663173c78..11744e2299d 100644 --- a/clients/shared/Network/NotificationClient.swift +++ b/clients/shared/Network/NotificationClient.swift @@ -4,13 +4,11 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "NotificationClient") /// Focused client for notification delivery acknowledgments. -@MainActor public protocol NotificationClientProtocol { func sendIntentResult(deliveryId: String, success: Bool, errorMessage: String?, errorCode: String?) async } /// Gateway-backed implementation of ``NotificationClientProtocol``. -@MainActor public struct NotificationClient: NotificationClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/PairingClient.swift b/clients/shared/Network/PairingClient.swift index ae4cf995331..490f6b4549e 100644 --- a/clients/shared/Network/PairingClient.swift +++ b/clients/shared/Network/PairingClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "PairingClient") /// Focused client for pairing approval and device management operations routed through the gateway. -@MainActor public protocol PairingClientProtocol { func sendPairingApprovalResponse(pairingRequestId: String, decision: String) async throws -> Bool func fetchApprovedDevices() async throws -> [ApprovedDevicesListResponseMessage.Device] @@ -13,7 +12,6 @@ public protocol PairingClientProtocol { } /// Gateway-backed implementation of ``PairingClientProtocol``. -@MainActor public struct PairingClient: PairingClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/PublishClient.swift b/clients/shared/Network/PublishClient.swift index 39cb657888e..e58525353ef 100644 --- a/clients/shared/Network/PublishClient.swift +++ b/clients/shared/Network/PublishClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "PublishClient") /// Focused client for page publishing and link-open operations routed through the gateway. -@MainActor public protocol PublishClientProtocol { func publishPage(html: String, title: String?, appId: String?) async throws -> PublishPageResponseMessage? func unpublishPage(deploymentId: String) async -> Bool @@ -12,7 +11,6 @@ public protocol PublishClientProtocol { } /// Gateway-backed implementation of ``PublishClientProtocol``. -@MainActor public struct PublishClient: PublishClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/RegenerateClient.swift b/clients/shared/Network/RegenerateClient.swift index 6f30c3ad9b0..f522ebadcb9 100644 --- a/clients/shared/Network/RegenerateClient.swift +++ b/clients/shared/Network/RegenerateClient.swift @@ -4,13 +4,11 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "RegenerateClient") /// Focused client for regenerating the last assistant response through the gateway. -@MainActor public protocol RegenerateClientProtocol { func regenerate(conversationId: String) async -> Bool } /// Gateway-backed implementation of ``RegenerateClientProtocol``. -@MainActor public struct RegenerateClient: RegenerateClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/ScheduleClient.swift b/clients/shared/Network/ScheduleClient.swift index 61ee7beb56f..aac5a568c62 100644 --- a/clients/shared/Network/ScheduleClient.swift +++ b/clients/shared/Network/ScheduleClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "ScheduleClient") /// Focused client for schedule management operations routed through the gateway. -@MainActor public protocol ScheduleClientProtocol { func fetchSchedulesList() async throws -> [ScheduleItem] func toggleSchedule(id: String, enabled: Bool) async throws -> [ScheduleItem] @@ -15,7 +14,6 @@ public protocol ScheduleClientProtocol { } /// Gateway-backed implementation of ``ScheduleClientProtocol``. -@MainActor public struct ScheduleClient: ScheduleClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/SettingsClient.swift b/clients/shared/Network/SettingsClient.swift index 48eaf6f9b8a..6444a44f3a4 100644 --- a/clients/shared/Network/SettingsClient.swift +++ b/clients/shared/Network/SettingsClient.swift @@ -7,7 +7,6 @@ private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum. /// /// Covers Vercel API config, model info, Telegram config, and channel /// verification status — the endpoints invoked during `SettingsStore.init()`. -@MainActor public protocol SettingsClientProtocol { func fetchVercelConfig() async -> VercelApiConfigResponseMessage? func saveVercelConfig(apiToken: String) async -> VercelApiConfigResponseMessage? @@ -48,7 +47,6 @@ public protocol SettingsClientProtocol { } /// Gateway-backed implementation of ``SettingsClientProtocol``. -@MainActor public struct SettingsClient: SettingsClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/SkillsClient.swift b/clients/shared/Network/SkillsClient.swift index 255fb0183b7..51c4e08e3b4 100644 --- a/clients/shared/Network/SkillsClient.swift +++ b/clients/shared/Network/SkillsClient.swift @@ -7,7 +7,6 @@ private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum. /// /// Covers listing, enabling, disabling, configuring, installing, uninstalling, /// updating, searching, inspecting, drafting, and creating skills. -@MainActor public protocol SkillsClientProtocol { func fetchSkillsList(includeCatalog: Bool) async -> SkillsListResponseMessage? func enableSkill(name: String) async -> SkillsOperationResponseMessage? @@ -26,7 +25,6 @@ public protocol SkillsClientProtocol { } /// Gateway-backed implementation of ``SkillsClientProtocol``. -@MainActor public struct SkillsClient: SkillsClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/SubagentClient.swift b/clients/shared/Network/SubagentClient.swift index 3066952d6dd..39d8144af47 100644 --- a/clients/shared/Network/SubagentClient.swift +++ b/clients/shared/Network/SubagentClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "SubagentClient") /// Focused client for subagent operations routed through the gateway. -@MainActor public protocol SubagentClientProtocol { func abort(subagentId: String, conversationId: String?) async -> Bool func fetchDetail(subagentId: String, conversationId: String) async -> SubagentDetailResponse? @@ -12,7 +11,6 @@ public protocol SubagentClientProtocol { } /// Gateway-backed implementation of ``SubagentClientProtocol``. -@MainActor public struct SubagentClient: SubagentClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/SurfaceActionClient.swift b/clients/shared/Network/SurfaceActionClient.swift index 9b2caaafa55..9d6ab1b4220 100644 --- a/clients/shared/Network/SurfaceActionClient.swift +++ b/clients/shared/Network/SurfaceActionClient.swift @@ -4,14 +4,12 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "SurfaceActionClient") /// Focused client for surface action and undo operations routed through the gateway. -@MainActor public protocol SurfaceActionClientProtocol { func sendSurfaceAction(conversationId: String?, surfaceId: String, actionId: String, data: [String: AnyCodable]?) async func sendSurfaceUndo(conversationId: String, surfaceId: String) async } /// Gateway-backed implementation of ``SurfaceActionClientProtocol``. -@MainActor public struct SurfaceActionClient: SurfaceActionClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/TTSClient.swift b/clients/shared/Network/TTSClient.swift index a0b4a23d3c5..e9cc2d588b6 100644 --- a/clients/shared/Network/TTSClient.swift +++ b/clients/shared/Network/TTSClient.swift @@ -18,13 +18,11 @@ public enum TTSResult: Sendable { } /// Focused client for message text-to-speech synthesis routed through the gateway. -@MainActor public protocol TTSClientProtocol { func synthesize(messageId: String, conversationId: String?) async -> TTSResult } /// Gateway-backed implementation of ``TTSClientProtocol``. -@MainActor public struct TTSClient: TTSClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/TelemetryClient.swift b/clients/shared/Network/TelemetryClient.swift index d5b67c89a9c..fae64bd1ea5 100644 --- a/clients/shared/Network/TelemetryClient.swift +++ b/clients/shared/Network/TelemetryClient.swift @@ -4,13 +4,11 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "TelemetryClient") /// Focused client for telemetry operations routed through the gateway. -@MainActor public protocol TelemetryClientProtocol { func recordLifecycleEvent(_ eventName: String) async } /// Gateway-backed implementation of ``TelemetryClientProtocol``. -@MainActor public struct TelemetryClient: TelemetryClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/ToolClient.swift b/clients/shared/Network/ToolClient.swift index 95e072a44dc..1acdc86ef63 100644 --- a/clients/shared/Network/ToolClient.swift +++ b/clients/shared/Network/ToolClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "ToolClient") /// Focused client for tool-related operations routed through the gateway. -@MainActor public protocol ToolClientProtocol { func fetchToolNamesList() async throws -> ToolNamesListResponseMessage func simulateToolPermission( @@ -17,7 +16,6 @@ public protocol ToolClientProtocol { } /// Gateway-backed implementation of ``ToolClientProtocol``. -@MainActor public struct ToolClient: ToolClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/TraceEventClient.swift b/clients/shared/Network/TraceEventClient.swift index 8cd6c84c1a1..3d39688b0e2 100644 --- a/clients/shared/Network/TraceEventClient.swift +++ b/clients/shared/Network/TraceEventClient.swift @@ -4,13 +4,11 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "TraceEventClient") /// Focused client for trace event history operations routed through the gateway. -@MainActor public protocol TraceEventClientProtocol { func fetchHistory(conversationId: String) async throws -> [TraceEventMessage] } /// Gateway-backed implementation of ``TraceEventClientProtocol``. -@MainActor public struct TraceEventClient: TraceEventClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/TrustRuleClient.swift b/clients/shared/Network/TrustRuleClient.swift index 70d66a42f9f..2e2a1bc52fe 100644 --- a/clients/shared/Network/TrustRuleClient.swift +++ b/clients/shared/Network/TrustRuleClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "TrustRuleClient") /// Focused client for trust rule management operations routed through the gateway. -@MainActor public protocol TrustRuleClientProtocol { func fetchTrustRules() async throws -> [TrustRuleItem] func addTrustRule( @@ -27,7 +26,6 @@ public protocol TrustRuleClientProtocol { } /// Gateway-backed implementation of ``TrustRuleClientProtocol``. -@MainActor public struct TrustRuleClient: TrustRuleClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/WorkItemClient.swift b/clients/shared/Network/WorkItemClient.swift index 0f804fa51d7..9abf86872a2 100644 --- a/clients/shared/Network/WorkItemClient.swift +++ b/clients/shared/Network/WorkItemClient.swift @@ -7,7 +7,6 @@ private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum. /// /// Covers listing, completing, deleting, running, fetching output, and updating /// work items. -@MainActor public protocol WorkItemClientProtocol { func fetchList(status: String?) async -> WorkItemsListResponse? func complete(id: String) async -> Bool @@ -21,7 +20,6 @@ public protocol WorkItemClientProtocol { } /// Gateway-backed implementation of ``WorkItemClientProtocol``. -@MainActor public struct WorkItemClient: WorkItemClientProtocol { nonisolated public init() {} diff --git a/clients/shared/Network/WorkspaceClient.swift b/clients/shared/Network/WorkspaceClient.swift index 88e262b8fe2..6c79fdceafe 100644 --- a/clients/shared/Network/WorkspaceClient.swift +++ b/clients/shared/Network/WorkspaceClient.swift @@ -4,7 +4,6 @@ import os private let log = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.vellum.vellum-assistant", category: "WorkspaceClient") /// Focused client for workspace file-system operations routed through the gateway. -@MainActor public protocol WorkspaceClientProtocol { func fetchWorkspaceTree(path: String, showHidden: Bool) async -> WorkspaceTreeResponse? func fetchWorkspaceFile(path: String, showHidden: Bool) async -> WorkspaceFileResponse? @@ -17,7 +16,6 @@ public protocol WorkspaceClientProtocol { } /// Gateway-backed implementation of ``WorkspaceClientProtocol``. -@MainActor public struct WorkspaceClient: WorkspaceClientProtocol { nonisolated public init() {}