useShared method

Adds an anonymous delegating middleware that wraps both operations with a shared callback.

Implementation

ChatClientBuilder useShared(ChatClientSharedDelegate sharedFunc) {
  ArgumentError.checkNotNull(sharedFunc, 'sharedFunc');

  return useWithServices(
    (innerClient, _) => AnonymousDelegatingChatClient(
      innerClient,
      responseHandler: (messages, options, inner, cancellationToken) async {
        ChatResponse? response;

        await sharedFunc(
          messages,
          options,
          (nextMessages, nextOptions, nextCancellationToken) async {
            response = await inner.getResponse(
              messages: nextMessages,
              options: nextOptions,
              cancellationToken: nextCancellationToken,
            );
          },
          cancellationToken,
        );

        final result = response;
        if (result == null) {
          throw StateError(
            'The wrapper completed successfully without producing a ChatResponse.',
          );
        }

        return result;
      },
      streamingResponseHandler:
          (messages, options, inner, cancellationToken) {
        final controller = StreamController<ChatResponseUpdate>();

        Future<void>(() async {
          Object? error;
          StackTrace? stackTrace;

          try {
            await sharedFunc(
              messages,
              options,
              (nextMessages, nextOptions, nextCancellationToken) async {
                await for (final update in inner.getStreamingResponse(
                  messages: nextMessages,
                  options: nextOptions,
                  cancellationToken: nextCancellationToken,
                )) {
                  controller.add(update);
                }
              },
              cancellationToken,
            );
          } catch (e, st) {
            error = e;
            stackTrace = st;
          } finally {
            if (error != null) {
              controller.addError(error, stackTrace);
            }
            await controller.close();
          }
        });

        return controller.stream;
      },
    ),
  );
}