File size: 1,445 Bytes
b8370f5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import Foundation

struct ChatMediaPlaybackRetryPolicy: Sendable {
    /// Eleven waits total 120 seconds. The initial request plus these retries
    /// gives transcoding time to finish without leaving a card pending forever.
    static let bounded = ChatMediaPlaybackRetryPolicy(delays: [
        .seconds(1),
        .seconds(2),
        .seconds(4),
        .seconds(8),
        .seconds(15),
        .seconds(15),
        .seconds(15),
        .seconds(15),
        .seconds(15),
        .seconds(15),
        .seconds(15),
    ])

    let delays: [Duration]
}

enum ChatMediaPlaybackLoader {
    typealias Load = @MainActor @Sendable () async throws -> OpenClawChatLoadedMedia?
    typealias Sleep = @MainActor @Sendable (Duration) async throws -> Void

    @MainActor
    static func load(
        policy: ChatMediaPlaybackRetryPolicy = .bounded,
        request: Load,
        onPreparing: @MainActor @Sendable () -> Void,
        sleep: Sleep = { try await Task.sleep(for: $0) }) async throws -> OpenClawChatLoadedMedia?
    {
        var loaded = try await request()
        guard case .preparing = loaded else { return loaded }
        onPreparing()

        for delay in policy.delays {
            try Task.checkCancellation()
            try await sleep(delay)
            loaded = try await request()
            guard case .preparing = loaded else { return loaded }
            onPreparing()
        }
        return nil
    }
}