-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathFileSyncPrompting.swift
53 lines (47 loc) · 2.01 KB
/
FileSyncPrompting.swift
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
import GRPC
extension MutagenDaemon {
typealias PromptStream = GRPCAsyncBidirectionalStreamingCall<Prompting_HostRequest, Prompting_HostResponse>
func host(allowPrompts: Bool = true) async throws(DaemonError) -> (PromptStream, identifier: String) {
let stream = client!.prompt.makeHostCall()
do {
try await stream.requestStream.send(.with { req in req.allowPrompts = allowPrompts })
} catch {
throw .grpcFailure(error)
}
// We can't make call `makeAsyncIterator` more than once
// (as a for-loop would do implicitly)
var iter = stream.responseStream.makeAsyncIterator()
let initResp: Prompting_HostResponse?
do {
initResp = try await iter.next()
} catch {
throw .grpcFailure(error)
}
guard let initResp else {
throw .unexpectedStreamClosure
}
try initResp.ensureValid(first: true, allowPrompts: allowPrompts)
Task.detached(priority: .background) {
do {
while let msg = try await iter.next() {
try msg.ensureValid(first: false, allowPrompts: allowPrompts)
var reply: Prompting_HostRequest = .init()
if msg.isPrompt {
// Handle SSH key prompts
if msg.message.contains("yes/no/[fingerprint]") {
reply.response = "yes"
}
// Any other messages that require a non-empty response will
// cause the create op to fail, showing an error. This is ok for now.
}
try await stream.requestStream.send(reply)
}
} catch let error as GRPCStatus where error.code == .cancelled {
return
} catch {
self.logger.critical("Prompt stream failed: \(error)")
}
}
return (stream, identifier: initResp.identifier)
}
}