// 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; } } }