// Copyright (c) Microsoft. All rights reserved.
using System.Runtime.CompilerServices;
using System.Text;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
namespace ChatWithAgent.Web;
///
/// The agent completions API client.
///
internal sealed class AgentCompletionsApiClient
{
private readonly HttpClient _httpClient;
private readonly ChatHistory _chatHistory;
///
/// Initializes a new instance of the class.
///
/// The HTTP client.
public AgentCompletionsApiClient(HttpClient httpClient)
{
this._httpClient = httpClient;
this._chatHistory = [];
}
///
/// Completes the prompt asynchronously.
///
/// The prompt.
/// The cancellation token.
/// The completion result.
internal async IAsyncEnumerable CompleteStreamingAsync(string prompt, [EnumeratorCancellation] CancellationToken cancellationToken)
{
var request = new AgentCompletionRequest()
{
Prompt = prompt,
ChatHistory = this._chatHistory,
IsStreaming = true,
};
var result = await this._httpClient.PostAsJsonAsync("/agent/completions", request, cancellationToken).ConfigureAwait(false);
result.EnsureSuccessStatusCode();
var streamedContent = result.Content.ReadFromJsonAsAsyncEnumerable(cancellationToken);
StringBuilder builder = new();
await foreach (StreamingChatMessageContent? update in streamedContent.ConfigureAwait(false))
{
if (string.IsNullOrEmpty(update?.Content))
{
continue;
}
builder.Append(update.Content);
yield return update.Content;
}
// Keep original prompt and agent response to maintain chat history
this._chatHistory.AddUserMessage(prompt);
this._chatHistory.AddAssistantMessage(builder.ToString());
}
///
/// The agent completion request model.
///
private sealed class AgentCompletionRequest
{
///
/// Gets or sets the prompt.
///
public required string Prompt { get; set; }
///
/// Gets or sets the chat history.
///
public required ChatHistory ChatHistory { get; set; }
///
/// Gets or sets a value indicating whether streaming is requested.
///
public bool IsStreaming { get; set; }
}
}