@@ -31,8 +31,6 @@ enum CodeiumError: Error, LocalizedError {
3131 }
3232}
3333
34- let token = " "
35-
3634public class CodeiumSuggestionService {
3735 static let sessionId = UUID ( ) . uuidString
3836 let projectRootURL : URL
@@ -45,6 +43,10 @@ public class CodeiumSuggestionService {
4543 let languageServerURL : URL
4644 let supportURL : URL
4745
46+ let authService = CodeiumAuthService ( )
47+
48+ var xcodeVersion = " 14.0 "
49+
4850 init ( designatedServer: CodeiumLSP ) {
4951 projectRootURL = URL ( fileURLWithPath: " / " )
5052 server = designatedServer
@@ -62,12 +64,16 @@ public class CodeiumSuggestionService {
6264 guard FileManager . default. fileExists ( atPath: languageServerURL. path) else {
6365 throw CodeiumError . languageServerNotInstalled
6466 }
65- try setupServerIfNeeded ( )
67+ Task {
68+ try await setupServerIfNeeded ( )
69+ }
6670 }
6771
6872 @discardableResult
69- func setupServerIfNeeded( ) throws -> CodeiumLSP {
73+ func setupServerIfNeeded( ) async throws -> CodeiumLSP {
7074 if let server { return server }
75+ let metadata = try getMetadata ( )
76+ xcodeVersion = ( try ? await getXcodeVersion ( ) ) ?? xcodeVersion
7177 let tempFolderURL = FileManager . default. temporaryDirectory
7278 let managerDirectoryURL = tempFolderURL
7379 . appendingPathComponent ( " com.intii.CopilotForXcode " )
@@ -94,9 +100,8 @@ public class CodeiumSuggestionService {
94100
95101 server. launchHandler = { [ weak self] in
96102 guard let self else { return }
97- let metadata = self . getMetadata ( )
98103 self . onServiceLaunched ( )
99- self . heartbeatTask = Task { [ weak self] in
104+ self . heartbeatTask = Task { [ weak self, metadata ] in
100105 while true {
101106 try Task . checkCancellation ( )
102107 _ = try ? await self ? . server? . sendRequest (
@@ -151,13 +156,18 @@ public class CodeiumSuggestionService {
151156}
152157
153158extension CodeiumSuggestionService {
154- func getMetadata( ) -> Metadata {
155- Metadata (
156- ide_name: " jetbrains " ,
157- ide_version: " 14.3 " ,
158- extension_name: " Copilot for Xcode " ,
159+ func getMetadata( ) throws -> Metadata {
160+ guard let key = authService. key else {
161+ struct E : Error , LocalizedError {
162+ var errorDescription : String ? { " Codeium not signed in. " }
163+ }
164+ throw E ( )
165+ }
166+ return Metadata (
167+ ide_name: " xcode " ,
168+ ide_version: xcodeVersion,
159169 extension_version: " 14.0.0 " ,
160- api_key: token ,
170+ api_key: key ,
161171 session_id: CodeiumSuggestionService . sessionId,
162172 request_id: requestCounter
163173 )
@@ -195,7 +205,7 @@ extension CodeiumSuggestionService: CodeiumSuggestionServiceType {
195205 let relativePath = getRelativePath ( of: fileURL)
196206
197207 let request = CodeiumRequest . GetCompletion ( requestBody: . init(
198- metadata: getMetadata ( ) ,
208+ metadata: try getMetadata ( ) ,
199209 document: . init(
200210 absolute_path: fileURL. path,
201211 relative_path: relativePath,
@@ -221,7 +231,7 @@ extension CodeiumSuggestionService: CodeiumSuggestionServiceType {
221231 }
222232 ) )
223233
224- let result = try await ( try setupServerIfNeeded ( ) ) . sendRequest ( request)
234+ let result = try await ( try await setupServerIfNeeded ( ) ) . sendRequest ( request)
225235
226236 return result. completionItems? . filter { item in
227237 if ignoreSpaceOnlySuggestions {
@@ -279,3 +289,36 @@ extension CodeiumSuggestionService: CodeiumSuggestionServiceType {
279289 }
280290}
281291
292+ func getXcodeVersion( ) async throws -> String {
293+ let task = Process ( )
294+ task. launchPath = " /usr/bin/xcodebuild "
295+ task. arguments = [ " -version " ]
296+ let outpipe = Pipe ( )
297+ task. standardOutput = outpipe
298+ task. standardError = Pipe ( )
299+ return try await withUnsafeThrowingContinuation { continuation in
300+ do {
301+ task. terminationHandler = { _ in
302+ do {
303+ if let data = try outpipe. fileHandleForReading. readToEnd ( ) ,
304+ let content = String ( data: data, encoding: . utf8)
305+ {
306+ let firstLine = content. split ( separator: " \n " ) . first ?? " "
307+ var version = firstLine. replacingOccurrences ( of: " Xcode " , with: " " )
308+ if version. isEmpty {
309+ version = " 14.0 "
310+ }
311+ continuation. resume ( returning: version)
312+ return
313+ }
314+ continuation. resume ( returning: " " )
315+ } catch {
316+ continuation. resume ( throwing: error)
317+ }
318+ }
319+ try task. run ( )
320+ } catch {
321+ continuation. resume ( throwing: error)
322+ }
323+ }
324+ }
0 commit comments