// Copyright (c) Microsoft. All rights reserved. using Microsoft.Extensions.AI; namespace Microsoft.AspNetCore.Components.AI; /// /// Represents a suggestion that can be displayed and sent to the agent. /// public readonly struct Suggestion : IEquatable { /// /// Initializes a new instance of the struct. /// /// The display text for the suggestion. /// The message to send when the suggestion is selected. public Suggestion(string text, ChatMessage message) { this.Text = text; this.Message = message; } /// /// Initializes a new instance of the struct with a simple text message. /// /// The display text for the suggestion, also used as the message content. public Suggestion(string text) { this.Text = text; this.Message = new ChatMessage(ChatRole.User, text); } /// /// Gets the display text for the suggestion. /// public string Text { get; } /// /// Gets the message to send when the suggestion is selected. /// public ChatMessage Message { get; } /// public override bool Equals(object? obj) => obj is Suggestion other && this.Equals(other); /// public bool Equals(Suggestion other) => this.Text == other.Text; /// public override int GetHashCode() => this.Text?.GetHashCode() ?? 0; /// /// Determines whether two instances are equal. /// public static bool operator ==(Suggestion left, Suggestion right) => left.Equals(right); /// /// Determines whether two instances are not equal. /// public static bool operator !=(Suggestion left, Suggestion right) => !left.Equals(right); } public partial class AgentSuggestions : IComponent { private RenderHandle _renderHandle; private AgentBoundaryContext? _context; private IReadOnlyList? _suggestions; [CascadingParameter] public AgentBoundaryContext? AgentContext { get; set; } [Parameter] public IReadOnlyList? Suggestions { get; set; } public void Attach(RenderHandle renderHandle) { this._renderHandle = renderHandle; } public Task SetParametersAsync(ParameterView parameters) { parameters.SetParameterProperties(this); this._context = this.AgentContext; this._suggestions = this.Suggestions; this.Render(); return Task.CompletedTask; } private void Render() { this._renderHandle.Render(builder => { if (this._suggestions is null || this._suggestions.Count == 0) { return; } builder.OpenElement(0, "div"); builder.AddAttribute(1, "class", "agent-suggestions"); for (var i = 0; i < this._suggestions.Count; i++) { var suggestion = this._suggestions[i]; builder.OpenElement(2, "button"); builder.SetKey(suggestion.Text); builder.AddAttribute(3, "class", "suggestion-button"); builder.AddAttribute(4, "onclick", EventCallback.Factory.Create(this, () => this.SelectSuggestionAsync(suggestion))); builder.AddContent(5, suggestion.Text); builder.CloseElement(); } builder.CloseElement(); }); } private async Task SelectSuggestionAsync(Suggestion suggestion) { if (this._context != null) { await this._context.SendAsync(suggestion.Message); } } }