@@ -125,16 +125,17 @@ public extension Messages {
125125 *
126126 * - Returns: A subscription ``MessageSubscription`` that can be used to iterate through new messages.
127127 */
128- func subscribe( bufferingPolicy: BufferingPolicy ) -> MessageSubscriptionResponseAsyncSequence < SubscribeResponse . HistoryResult > {
128+ func subscribe( bufferingPolicy: BufferingPolicy ) -> MessageSubscriptionResponseAsyncSequence {
129129 var emitEvent : ( ( ChatMessageEvent ) -> Void ) ?
130130 let subscription = subscribe { event in
131131 emitEvent ? ( event)
132132 }
133133
134134 let subscriptionAsyncSequence = MessageSubscriptionResponseAsyncSequence (
135135 bufferingPolicy: bufferingPolicy,
136- historyBeforeSubscribe: subscription. historyBeforeSubscribe,
137- )
136+ ) { params throws ( ErrorInfo) in
137+ try await subscription. historyBeforeSubscribe ( withParams: params)
138+ }
138139 emitEvent = { [ weak subscriptionAsyncSequence] event in
139140 subscriptionAsyncSequence? . emit ( event)
140141 }
@@ -149,7 +150,7 @@ public extension Messages {
149150 }
150151
151152 /// Same as calling ``subscribe(bufferingPolicy:)`` with ``BufferingPolicy/unbounded``.
152- func subscribe( ) -> MessageSubscriptionResponseAsyncSequence < SubscribeResponse . HistoryResult > {
153+ func subscribe( ) -> MessageSubscriptionResponseAsyncSequence {
153154 subscribe ( bufferingPolicy: . unbounded)
154155 }
155156}
@@ -409,27 +410,43 @@ public struct ChatMessageEvent: Sendable {
409410/// A non-throwing `AsyncSequence` whose element is ``ChatMessageEvent``. The Chat SDK uses this type as the return value of the `AsyncSequence` convenience variants of the ``Messages`` methods that allow you to find out about received chat messages.
410411///
411412/// You should only iterate over a given `MessageSubscriptionResponseAsyncSequence` once; the results of iterating more than once are undefined.
412- public final class MessageSubscriptionResponseAsyncSequence < HistoryResult: PaginatedResult < Message > > : Sendable , AsyncSequence {
413+ public final class MessageSubscriptionResponseAsyncSequence : Sendable , AsyncSequence {
414+ /*
415+ Design note: Unlike other SDK types, this is a concrete class rather than a protocol. Ideally, for
416+ consistency with the rest of the SDK, this would be a protocol that users could reference as
417+ `any MessageSubscriptionResponseAsyncSequence`. However, creating an AsyncSequence-inheriting protocol
418+ that allows iteration without `try` on an existential requires the `Failure` associated type, which is
419+ only available in iOS 18+.
420+
421+ Additionally, this class intentionally has no generic parameters, even though the underlying implementation
422+ uses concrete PaginatedResult types. This is because the type is impossible for users to spell due to Swift
423+ compiler limitations with opaque types — attempting to write
424+ `MessageSubscriptionResponseAsyncSequence<ChatClient.Rooms.Room.Messages.HistoryResult>` fails with
425+ "Underlying type for opaque result type 'some Rooms<...>' could not be inferred from return expression".
426+ By removing the generic parameter and having `historyBeforeSubscribe(withParams:)` return
427+ `any PaginatedResult<Message>`, users can store subscriptions as simple properties
428+ (e.g., `var subscription: MessageSubscriptionResponseAsyncSequence?`).
429+ */
413430 // swiftlint:disable:next missing_docs
414431 public typealias Element = ChatMessageEvent
415432
416433 private let subscription : SubscriptionAsyncSequence < Element >
417434
418435 // can be set by either initialiser
419- private let historyBeforeSubscribe : @Sendable ( HistoryBeforeSubscribeParams) async throws ( ErrorInfo ) -> HistoryResult
436+ private let historyBeforeSubscribe : @Sendable ( HistoryBeforeSubscribeParams) async throws ( ErrorInfo ) -> any PaginatedResult < Message >
420437
421438 // used internally
422439 internal init (
423440 bufferingPolicy: BufferingPolicy ,
424- historyBeforeSubscribe: @escaping @Sendable ( HistoryBeforeSubscribeParams) async throws ( ErrorInfo ) -> HistoryResult ,
441+ historyBeforeSubscribe: @escaping @Sendable ( HistoryBeforeSubscribeParams) async throws ( ErrorInfo ) -> any PaginatedResult < Message > ,
425442 ) {
426443 subscription = . init( bufferingPolicy: bufferingPolicy)
427444 self . historyBeforeSubscribe = historyBeforeSubscribe
428445 }
429446
430447 // used for testing
431448 // swiftlint:disable:next missing_docs
432- public init < Underlying: AsyncSequence & Sendable > ( mockAsyncSequence: Underlying , mockHistoryBeforeSubscribe: @escaping @Sendable ( HistoryBeforeSubscribeParams) async throws ( ErrorInfo ) -> HistoryResult ) where Underlying. Element == Element {
449+ public init < Underlying: AsyncSequence & Sendable > ( mockAsyncSequence: Underlying , mockHistoryBeforeSubscribe: @escaping @Sendable ( HistoryBeforeSubscribeParams) async throws ( ErrorInfo ) -> any PaginatedResult < Message > ) where Underlying. Element == Element {
433450 subscription = . init( mockAsyncSequence: mockAsyncSequence)
434451 historyBeforeSubscribe = mockHistoryBeforeSubscribe
435452 }
@@ -444,7 +461,7 @@ public final class MessageSubscriptionResponseAsyncSequence<HistoryResult: Pagin
444461 }
445462
446463 // swiftlint:disable:next missing_docs
447- public func historyBeforeSubscribe( withParams params: HistoryBeforeSubscribeParams ) async throws ( ErrorInfo) -> HistoryResult {
464+ public func historyBeforeSubscribe( withParams params: HistoryBeforeSubscribeParams ) async throws ( ErrorInfo) -> any PaginatedResult < Message > {
448465 try await historyBeforeSubscribe ( params)
449466 }
450467
0 commit comments