Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public sealed class AnonymousDelegatingChatClient : DelegatingChatClient
private readonly Func<IList<ChatMessage>, ChatOptions?, IChatClient, CancellationToken, IAsyncEnumerable<ChatResponseUpdate>>? _getStreamingResponseFunc;

/// <summary>The delegate to use as the implementation of both <see cref="GetResponseAsync"/> and <see cref="GetStreamingResponseAsync"/>.</summary>
private readonly CompleteSharedFunc? _sharedFunc;
private readonly GetResponseSharedFunc? _sharedFunc;

/// <summary>
/// Initializes a new instance of the <see cref="AnonymousDelegatingChatClient"/> class.
Expand All @@ -45,7 +45,7 @@ public sealed class AnonymousDelegatingChatClient : DelegatingChatClient
/// </remarks>
/// <exception cref="ArgumentNullException"><paramref name="innerClient"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="sharedFunc"/> is <see langword="null"/>.</exception>
public AnonymousDelegatingChatClient(IChatClient innerClient, CompleteSharedFunc sharedFunc)
public AnonymousDelegatingChatClient(IChatClient innerClient, GetResponseSharedFunc sharedFunc)
: base(innerClient)
{
_ = Throw.IfNull(sharedFunc);
Expand Down Expand Up @@ -178,12 +178,12 @@ static async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsyncViaGe
}

/// <summary>Throws an exception if both of the specified delegates are null.</summary>
/// <exception cref="ArgumentNullException">Both <paramref name="completeFunc"/> and <paramref name="completeStreamingFunc"/> are <see langword="null"/>.</exception>
internal static void ThrowIfBothDelegatesNull(object? completeFunc, object? completeStreamingFunc)
/// <exception cref="ArgumentNullException">Both <paramref name="getResponseFunc"/> and <paramref name="getStreamingResponseFunc"/> are <see langword="null"/>.</exception>
internal static void ThrowIfBothDelegatesNull(object? getResponseFunc, object? getStreamingResponseFunc)
{
if (completeFunc is null && completeStreamingFunc is null)
if (getResponseFunc is null && getStreamingResponseFunc is null)
{
Throw.ArgumentNullException(nameof(completeFunc), $"At least one of the {nameof(completeFunc)} or {nameof(completeStreamingFunc)} delegates must be non-null.");
Throw.ArgumentNullException(nameof(getResponseFunc), $"At least one of the {nameof(getResponseFunc)} or {nameof(getStreamingResponseFunc)} delegates must be non-null.");
}
}

Expand All @@ -205,7 +205,7 @@ internal static void ThrowIfBothDelegatesNull(object? completeFunc, object? comp
/// </param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A <see cref="Task"/> that represents the completion of the operation.</returns>
public delegate Task CompleteSharedFunc(
public delegate Task GetResponseSharedFunc(
IList<ChatMessage> chatMessages,
ChatOptions? options,
Func<IList<ChatMessage>, ChatOptions?, CancellationToken, Task> nextAsync,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public ChatClientBuilder Use(Func<IChatClient, IServiceProvider, IChatClient> cl
/// need to interact with the results of the operation, which will come from the inner client.
/// </remarks>
/// <exception cref="ArgumentNullException"><paramref name="sharedFunc"/> is <see langword="null"/>.</exception>
public ChatClientBuilder Use(AnonymousDelegatingChatClient.CompleteSharedFunc sharedFunc)
public ChatClientBuilder Use(AnonymousDelegatingChatClient.GetResponseSharedFunc sharedFunc)
{
_ = Throw.IfNull(sharedFunc);

Expand All @@ -106,34 +106,34 @@ public ChatClientBuilder Use(AnonymousDelegatingChatClient.CompleteSharedFunc sh
/// Adds to the chat client pipeline an anonymous delegating chat client based on a delegate that provides
/// an implementation for both <see cref="IChatClient.GetResponseAsync"/> and <see cref="IChatClient.GetStreamingResponseAsync"/>.
/// </summary>
/// <param name="completeFunc">
/// <param name="getResponseFunc">
/// A delegate that provides the implementation for <see cref="IChatClient.GetResponseAsync"/>. When <see langword="null"/>,
/// <paramref name="completeStreamingFunc"/> must be non-null, and the implementation of <see cref="IChatClient.GetResponseAsync"/>
/// will use <paramref name="completeStreamingFunc"/> for the implementation.
/// <paramref name="getStreamingResponseFunc"/> must be non-null, and the implementation of <see cref="IChatClient.GetResponseAsync"/>
/// will use <paramref name="getStreamingResponseFunc"/> for the implementation.
/// </param>
/// <param name="completeStreamingFunc">
/// <param name="getStreamingResponseFunc">
/// A delegate that provides the implementation for <see cref="IChatClient.GetStreamingResponseAsync"/>. When <see langword="null"/>,
/// <paramref name="completeFunc"/> must be non-null, and the implementation of <see cref="IChatClient.GetStreamingResponseAsync"/>
/// will use <paramref name="completeFunc"/> for the implementation.
/// <paramref name="getResponseFunc"/> must be non-null, and the implementation of <see cref="IChatClient.GetStreamingResponseAsync"/>
/// will use <paramref name="getResponseFunc"/> for the implementation.
/// </param>
/// <returns>The updated <see cref="ChatClientBuilder"/> instance.</returns>
/// <remarks>
/// One or both delegates may be provided. If both are provided, they will be used for their respective methods:
/// <paramref name="completeFunc"/> will provide the implementation of <see cref="IChatClient.GetResponseAsync"/>, and
/// <paramref name="completeStreamingFunc"/> will provide the implementation of <see cref="IChatClient.GetStreamingResponseAsync"/>.
/// If only one of the delegates is provided, it will be used for both methods. That means that if <paramref name="completeFunc"/>
/// is supplied without <paramref name="completeStreamingFunc"/>, the implementation of <see cref="IChatClient.GetStreamingResponseAsync"/>
/// will employ limited streaming, as it will be operating on the batch output produced by <paramref name="completeFunc"/>. And if
/// <paramref name="completeStreamingFunc"/> is supplied without <paramref name="completeFunc"/>, the implementation of
/// <see cref="IChatClient.GetResponseAsync"/> will be implemented by combining the updates from <paramref name="completeStreamingFunc"/>.
/// <paramref name="getResponseFunc"/> will provide the implementation of <see cref="IChatClient.GetResponseAsync"/>, and
/// <paramref name="getStreamingResponseFunc"/> will provide the implementation of <see cref="IChatClient.GetStreamingResponseAsync"/>.
/// If only one of the delegates is provided, it will be used for both methods. That means that if <paramref name="getResponseFunc"/>
/// is supplied without <paramref name="getStreamingResponseFunc"/>, the implementation of <see cref="IChatClient.GetStreamingResponseAsync"/>
/// will employ limited streaming, as it will be operating on the batch output produced by <paramref name="getResponseFunc"/>. And if
/// <paramref name="getStreamingResponseFunc"/> is supplied without <paramref name="getResponseFunc"/>, the implementation of
/// <see cref="IChatClient.GetResponseAsync"/> will be implemented by combining the updates from <paramref name="getStreamingResponseFunc"/>.
/// </remarks>
/// <exception cref="ArgumentNullException">Both <paramref name="completeFunc"/> and <paramref name="completeStreamingFunc"/> are <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Both <paramref name="getResponseFunc"/> and <paramref name="getStreamingResponseFunc"/> are <see langword="null"/>.</exception>
public ChatClientBuilder Use(
Func<IList<ChatMessage>, ChatOptions?, IChatClient, CancellationToken, Task<ChatResponse>>? completeFunc,
Func<IList<ChatMessage>, ChatOptions?, IChatClient, CancellationToken, IAsyncEnumerable<ChatResponseUpdate>>? completeStreamingFunc)
Func<IList<ChatMessage>, ChatOptions?, IChatClient, CancellationToken, Task<ChatResponse>>? getResponseFunc,
Func<IList<ChatMessage>, ChatOptions?, IChatClient, CancellationToken, IAsyncEnumerable<ChatResponseUpdate>>? getStreamingResponseFunc)
{
AnonymousDelegatingChatClient.ThrowIfBothDelegatesNull(completeFunc, completeStreamingFunc);
AnonymousDelegatingChatClient.ThrowIfBothDelegatesNull(getResponseFunc, getStreamingResponseFunc);

return Use((innerClient, _) => new AnonymousDelegatingChatClient(innerClient, completeFunc, completeStreamingFunc));
return Use((innerClient, _) => new AnonymousDelegatingChatClient(innerClient, getResponseFunc, getStreamingResponseFunc));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ public void InvalidArgs_Throws()
ChatClientBuilder builder = new(client);

Assert.Throws<ArgumentNullException>("sharedFunc", () =>
builder.Use((AnonymousDelegatingChatClient.CompleteSharedFunc)null!));
builder.Use((AnonymousDelegatingChatClient.GetResponseSharedFunc)null!));

Assert.Throws<ArgumentNullException>("completeFunc", () => builder.Use(null!, null!));
Assert.Throws<ArgumentNullException>("getResponseFunc", () => builder.Use(null!, null!));

Assert.Throws<ArgumentNullException>("innerClient", () => new AnonymousDelegatingChatClient(null!, delegate { return Task.CompletedTask; }));
Assert.Throws<ArgumentNullException>("sharedFunc", () => new AnonymousDelegatingChatClient(client, null!));

Assert.Throws<ArgumentNullException>("innerClient", () => new AnonymousDelegatingChatClient(null!, null!, null!));
Assert.Throws<ArgumentNullException>("completeFunc", () => new AnonymousDelegatingChatClient(client, null!, null!));
Assert.Throws<ArgumentNullException>("getResponseFunc", () => new AnonymousDelegatingChatClient(client, null!, null!));
}

[Fact]
Expand Down Expand Up @@ -81,7 +81,7 @@ public async Task Shared_ContextPropagated()
}

[Fact]
public async Task CompleteFunc_ContextPropagated()
public async Task GetResponseFunc_ContextPropagated()
{
IList<ChatMessage> expectedMessages = [];
ChatOptions expectedOptions = new();
Expand Down Expand Up @@ -123,7 +123,7 @@ public async Task CompleteFunc_ContextPropagated()
}

[Fact]
public async Task CompleteStreamingFunc_ContextPropagated()
public async Task GetStreamingResponseFunc_ContextPropagated()
{
IList<ChatMessage> expectedMessages = [];
ChatOptions expectedOptions = new();
Expand Down Expand Up @@ -174,7 +174,7 @@ static async IAsyncEnumerable<ChatResponseUpdate> Impl(
}

[Fact]
public async Task BothCompleteAndCompleteStreamingFuncs_ContextPropagated()
public async Task BothGetResponseAndGetStreamingResponseFuncs_ContextPropagated()
{
IList<ChatMessage> expectedMessages = [];
ChatOptions expectedOptions = new();
Expand Down
Loading