@@ -222,15 +222,15 @@ extension GitHubCopilotExtension {
222222 public static func fetchToken( ) async throws -> Token {
223223 guard let authToken = authInfo? . oauth_token
224224 else { throw GitHubCopilotError . notLoggedIn }
225-
225+
226226 let oldToken = await MainActor . run { cachedToken }
227227 if let oldToken {
228228 let expiresAt = Date ( timeIntervalSince1970: TimeInterval ( oldToken. expires_at) )
229229 if expiresAt > Date ( ) {
230230 return oldToken
231231 }
232232 }
233-
233+
234234 let url = URL ( string: " https://api.github.com/copilot_internal/v2/token " ) !
235235 var request = URLRequest ( url: url)
236236 request. httpMethod = " GET "
@@ -255,5 +255,64 @@ extension GitHubCopilotExtension {
255255 throw error
256256 }
257257 }
258+
259+ public static func fetchLLMModels( ) async throws -> [ GitHubCopilotLLMModel ] {
260+ let token = try await GitHubCopilotExtension . fetchToken ( )
261+ guard let endpoint = URL ( string: token. endpoints. api + " /models " ) else {
262+ throw CancellationError ( )
263+ }
264+ var request = URLRequest ( url: endpoint)
265+ request. setValue (
266+ " Copilot for Xcode/ \( Bundle . main. infoDictionary ? [ " CFBundleShortVersionString " ] as? String ?? " unknown " ) " ,
267+ forHTTPHeaderField: " Editor-Version "
268+ )
269+ request. setValue ( " Bearer \( token. token) " , forHTTPHeaderField: " Authorization " )
270+ request. setValue ( " application/json " , forHTTPHeaderField: " Content-Type " )
271+ request. setValue ( " vscode-chat " , forHTTPHeaderField: " Copilot-Integration-Id " )
272+ request. setValue ( " 2023-07-07 " , forHTTPHeaderField: " X-Github-Api-Version " )
273+
274+ let ( data, response) = try await URLSession . shared. data ( for: request)
275+
276+ guard let response = response as? HTTPURLResponse else {
277+ throw CancellationError ( )
278+ }
279+
280+ guard response. statusCode == 200 else {
281+ throw CancellationError ( )
282+ }
283+
284+ struct Model : Decodable {
285+ struct Limit : Decodable {
286+ var max_context_window_tokens : Int
287+ }
288+
289+ struct Capability : Decodable {
290+ var type : String ?
291+ var family : String ?
292+ var limit : Limit ?
293+ }
294+
295+ var id : String
296+ var capabilities : Capability
297+ }
298+
299+ struct Body : Decodable {
300+ var data : [ Model ]
301+ }
302+
303+ let models = try JSONDecoder ( ) . decode ( Body . self, from: data)
304+ . data
305+ . filter {
306+ $0. capabilities. type == " chat "
307+ }
308+ . map {
309+ GitHubCopilotLLMModel (
310+ modelId: $0. id,
311+ familyName: $0. capabilities. family ?? " " ,
312+ contextWindow: $0. capabilities. limit? . max_context_window_tokens ?? 0
313+ )
314+ }
315+ return models
316+ }
258317}
259318
0 commit comments