From e6d58f260acbc49765385fd320cd95a35212932c Mon Sep 17 00:00:00 2001 From: Shx Guo Date: Fri, 31 May 2024 14:17:40 +0800 Subject: [PATCH 1/4] Force language server to update when it doesn't match the min version --- Tool/Package.swift | 1 + .../GitHubCopilotWorkspacePlugin.swift | 48 +++++++++++++++++++ .../GitHubCopilotInstallationManager.swift | 19 ++++++-- 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/Tool/Package.swift b/Tool/Package.swift index 36ecdb15..a42040e0 100644 --- a/Tool/Package.swift +++ b/Tool/Package.swift @@ -316,6 +316,7 @@ let package = Package( "Preferences", "Terminal", "BuiltinExtension", + "Toast", .product(name: "LanguageServerProtocol", package: "LanguageServerProtocol"), .product(name: "CopilotForXcodeKit", package: "CopilotForXcodeKit"), ], diff --git a/Tool/Sources/GitHubCopilotService/GitHubCopilotWorkspacePlugin.swift b/Tool/Sources/GitHubCopilotService/GitHubCopilotWorkspacePlugin.swift index 0c3b8615..e893c133 100644 --- a/Tool/Sources/GitHubCopilotService/GitHubCopilotWorkspacePlugin.swift +++ b/Tool/Sources/GitHubCopilotService/GitHubCopilotWorkspacePlugin.swift @@ -1,14 +1,35 @@ import Foundation import Logger import Workspace +import Toast +import Dependencies public final class GitHubCopilotWorkspacePlugin: WorkspacePlugin { + enum Error: Swift.Error, LocalizedError { + case gitHubCopilotLanguageServerMustBeUpdated + var errorDescription: String? { + switch self { + case .gitHubCopilotLanguageServerMustBeUpdated: + return "GitHub Copilot language server must be updated. Update will start immediately. \nIf it fails, please go to Host app > Service > GitHub Copilot and check if there is an update available." + } + } + } + + @Dependency(\.toast) var toast + + let installationManager = GitHubCopilotInstallationManager() private var _gitHubCopilotService: GitHubCopilotService? @GitHubCopilotSuggestionActor var gitHubCopilotService: GitHubCopilotService? { if let service = _gitHubCopilotService { return service } do { return try createGitHubCopilotService() + } catch let error as Error { + toast(error.localizedDescription, .warning) + Task { + await updateLanguageServerIfPossible() + } + return nil } catch { Logger.gitHubCopilot.error("Failed to create GitHub Copilot service: \(error)") return nil @@ -23,6 +44,9 @@ public final class GitHubCopilotWorkspacePlugin: WorkspacePlugin { @GitHubCopilotSuggestionActor func createGitHubCopilotService() throws -> GitHubCopilotService { + if case .outdated(_, _, true) = installationManager.checkInstallation() { + throw Error.gitHubCopilotLanguageServerMustBeUpdated + } let newService = try GitHubCopilotService(projectRootURL: projectRootURL) _gitHubCopilotService = newService newService.localProcessServer?.terminationHandler = { [weak self] in @@ -50,6 +74,30 @@ public final class GitHubCopilotWorkspacePlugin: WorkspacePlugin { } } } + + @GitHubCopilotSuggestionActor + func updateLanguageServerIfPossible() async { + guard !GitHubCopilotInstallationManager.isInstalling else { return } + let events = installationManager.installLatestVersion() + do { + for try await event in events { + switch event { + case .downloading: + toast("Updating GitHub Copilot language server", .info) + case .uninstalling: + break + case .decompressing: + break + case .done: + toast("Finished updating GitHub Copilot language server", .info) + } + } + } catch GitHubCopilotInstallationManager.Error.isInstalling { + return + } catch { + toast(error.localizedDescription, .error) + } + } func terminate() { _gitHubCopilotService = nil diff --git a/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotInstallationManager.swift b/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotInstallationManager.swift index efd8576b..94165428 100644 --- a/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotInstallationManager.swift +++ b/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotInstallationManager.swift @@ -2,7 +2,8 @@ import Foundation import Terminal public struct GitHubCopilotInstallationManager { - private static var isInstalling = false + @GitHubCopilotSuggestionActor + public private(set) static var isInstalling = false static var downloadURL: URL { let commitHash = "c79d711cbf7c6672c6c57d6df7c5ab7b6cac2b7a" @@ -11,13 +12,14 @@ public struct GitHubCopilotInstallationManager { } static let latestSupportedVersion = "1.33.0" + static let minimumSupportedVersion = "1.32.0" public init() {} public enum InstallationStatus { case notInstalled case installed(String) - case outdated(current: String, latest: String) + case outdated(current: String, latest: String, mandatory: Bool) case unsupported(current: String, latest: String) } @@ -38,7 +40,14 @@ public struct GitHubCopilotInstallationManager { { switch version.compare(Self.latestSupportedVersion) { case .orderedAscending: - return .outdated(current: version, latest: Self.latestSupportedVersion) + switch version.compare(Self.minimumSupportedVersion) { + case .orderedAscending: + return .outdated(current: version, latest: Self.latestSupportedVersion, mandatory: true) + case .orderedSame: + return .outdated(current: version, latest: Self.latestSupportedVersion, mandatory: false) + case .orderedDescending: + return .outdated(current: version, latest: Self.latestSupportedVersion, mandatory: false) + } case .orderedSame: return .installed(version) case .orderedDescending: @@ -46,7 +55,7 @@ public struct GitHubCopilotInstallationManager { } } - return .outdated(current: "Unknown", latest: Self.latestSupportedVersion) + return .outdated(current: "Unknown", latest: Self.latestSupportedVersion, mandatory: false) } public enum InstallationStep { @@ -75,7 +84,7 @@ public struct GitHubCopilotInstallationManager { public func installLatestVersion() -> AsyncThrowingStream { AsyncThrowingStream { continuation in - Task { + Task { @GitHubCopilotSuggestionActor in guard !GitHubCopilotInstallationManager.isInstalling else { continuation.finish(throwing: Error.isInstalling) return From 2e65bbd01d84b82fb764f95e42e2a9d6479b1496 Mon Sep 17 00:00:00 2001 From: Shx Guo Date: Fri, 31 May 2024 14:19:12 +0800 Subject: [PATCH 2/4] Adjust border color --- .../SuggestionPanelContent/ToastPanelView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Sources/SuggestionWidget/SuggestionPanelContent/ToastPanelView.swift b/Core/Sources/SuggestionWidget/SuggestionPanelContent/ToastPanelView.swift index 6e9ffab9..5cd6ba23 100644 --- a/Core/Sources/SuggestionWidget/SuggestionPanelContent/ToastPanelView.swift +++ b/Core/Sources/SuggestionWidget/SuggestionPanelContent/ToastPanelView.swift @@ -28,7 +28,7 @@ struct ToastPanelView: View { }() as Color, in: RoundedRectangle(cornerRadius: 8)) .overlay { RoundedRectangle(cornerRadius: 8) - .stroke(Color.black.opacity(0.3), lineWidth: 1) + .stroke(Color.black.opacity(0.1), lineWidth: 1) } } From 77bdac02bcf4b7c719108e3b70fa7c86a6a8fa5c Mon Sep 17 00:00:00 2001 From: Shx Guo Date: Fri, 31 May 2024 14:34:15 +0800 Subject: [PATCH 3/4] Format code --- Core/Sources/HostApp/AccountSettings/GitHubCopilotView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Sources/HostApp/AccountSettings/GitHubCopilotView.swift b/Core/Sources/HostApp/AccountSettings/GitHubCopilotView.swift index 94affa6d..44d724ae 100644 --- a/Core/Sources/HostApp/AccountSettings/GitHubCopilotView.swift +++ b/Core/Sources/HostApp/AccountSettings/GitHubCopilotView.swift @@ -218,7 +218,7 @@ struct GitHubCopilotView: View { case let .installed(version): Text("Copilot.Vim Version: \(version)") uninstallButton - case let .outdated(version, latest): + case let .outdated(version, latest, _): Text("Copilot.Vim Version: \(version) (Update Available: \(latest))") updateButton uninstallButton From 5b68e575fd1ef0c5034ac3b8ebd497dc94832eb2 Mon Sep 17 00:00:00 2001 From: Shx Guo Date: Fri, 31 May 2024 14:34:29 +0800 Subject: [PATCH 4/4] Update appcast.xml --- appcast.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appcast.xml b/appcast.xml index 8cccd8f8..48f08812 100644 --- a/appcast.xml +++ b/appcast.xml @@ -9,7 +9,7 @@ 0.33.2 12.0 https://github.com/intitni/CopilotForXcode/releases/tag/0.33.2 - + 0.33.1