-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathServerRequestHandler.swift
More file actions
133 lines (119 loc) · 5.88 KB
/
ServerRequestHandler.swift
File metadata and controls
133 lines (119 loc) · 5.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import Combine
import ConversationServiceProvider
import Foundation
import JSONRPC
import LanguageClient
import LanguageServerProtocol
import Logger
public typealias ResponseHandler = ServerRequest.Handler<JSONValue>
public typealias LegacyResponseHandler = (AnyJSONRPCResponse) -> Void
protocol ServerRequestHandler {
func handleRequest(id: JSONId, _ request: ServerRequest, workspaceURL: URL, service: GitHubCopilotService?)
}
class ServerRequestHandlerImpl: ServerRequestHandler {
public static let shared = ServerRequestHandlerImpl()
private let conversationContextHandler: ConversationContextHandler = ConversationContextHandlerImpl.shared
private let watchedFilesHandler: WatchedFilesHandler = WatchedFilesHandlerImpl.shared
private let showMessageRequestHandler: ShowMessageRequestHandler = ShowMessageRequestHandlerImpl.shared
private let dynamicOAuthRequestHandler: DynamicOAuthRequestHandler = DynamicOAuthRequestHandlerImpl.shared
func handleRequest(id: JSONId, _ request: ServerRequest, workspaceURL: URL, service: GitHubCopilotService?) {
switch request {
case let .windowShowMessageRequest(params, callback):
if workspaceURL.path != "/" {
do {
let paramsData = try JSONEncoder().encode(params)
let showMessageRequestParams = try JSONDecoder().decode(ShowMessageRequestParams.self, from: paramsData)
showMessageRequestHandler.handleShowMessageRequest(
ShowMessageRequest(
id: id,
method: "window/showMessageRequest",
params: showMessageRequestParams
),
callback: callback
)
} catch {
Task {
await callback(.success(nil))
}
}
}
case let .custom(method, params, callback):
let legacyResponseHandler = toLegacyResponseHandler(callback)
do {
switch method {
case "conversation/context":
let paramsData = try JSONEncoder().encode(params)
let contextParams = try JSONDecoder().decode(ConversationContextParams.self, from: paramsData)
conversationContextHandler.handleConversationContext(
ConversationContextRequest(id: id, method: method, params: contextParams),
completion: legacyResponseHandler
)
case "copilot/watchedFiles":
let paramsData = try JSONEncoder().encode(params)
let watchedFilesParams = try JSONDecoder().decode(WatchedFilesParams.self, from: paramsData)
watchedFilesHandler.handleWatchedFiles(
WatchedFilesRequest(id: id, method: method, params: watchedFilesParams),
workspaceURL: workspaceURL,
completion: legacyResponseHandler,
service: service
)
case "conversation/invokeClientTool":
let paramsData = try JSONEncoder().encode(params)
let invokeParams = try JSONDecoder().decode(InvokeClientToolParams.self, from: paramsData)
ClientToolHandlerImpl.shared.invokeClientTool(
InvokeClientToolRequest(id: id, method: method, params: invokeParams),
completion: legacyResponseHandler
)
case "conversation/invokeClientToolConfirmation":
let paramsData = try JSONEncoder().encode(params)
let invokeParams = try JSONDecoder().decode(InvokeClientToolParams.self, from: paramsData)
ClientToolHandlerImpl.shared.invokeClientToolConfirmation(
InvokeClientToolConfirmationRequest(id: id, method: method, params: invokeParams),
completion: legacyResponseHandler
)
case "copilot/dynamicOAuth":
let paramsData = try JSONEncoder().encode(params)
let dynamicOAuthParams = try JSONDecoder().decode(DynamicOAuthParams.self, from: paramsData)
DynamicOAuthRequestHandlerImpl.shared.handleDynamicOAuthRequest(
DynamicOAuthRequest(id: id, method: method, params: dynamicOAuthParams),
completion: legacyResponseHandler
)
default:
break
}
} catch {
handleError(id: id, method: method, error: error, callback: legacyResponseHandler)
}
default:
break
}
}
private func handleError(id: JSONId, method: String, error: Error, callback: @escaping (AnyJSONRPCResponse) -> Void) {
callback(
AnyJSONRPCResponse(
id: id,
result: JSONValue.array([
JSONValue.null,
JSONValue.hash([
"code": .number(-32602 /* Invalid params */ ),
"message": .string("Error handling \(method): \(error.localizedDescription)")]),
])
)
)
Logger.gitHubCopilot.error(error)
}
/// Converts a new Handler to work with old code that expects LegacyResponseHandler
private func toLegacyResponseHandler(
_ newHandler: @escaping ResponseHandler
) -> LegacyResponseHandler {
return { response in
Task {
if let error = response.error {
await newHandler(.failure(error))
} else if let result = response.result {
await newHandler(.success(result))
}
}
}
}
}