| File: Pipeline\StateMapperContext.cs | Web Access |
| Project: src\aspnetcore\src\Components\AI\src\Microsoft.AspNetCore.Components.AI.csproj (Microsoft.AspNetCore.Components.AI) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Extensions.AI; namespace Microsoft.AspNetCore.Components.AI; /// <summary> /// Carries a model update through typed state mapping and tracks content consumed as state. /// </summary> public class StateMapperContext { private readonly bool[] _handled; private int _handledCount; internal StateMapperContext(ChatResponseUpdate update) { Update = update; _handled = new bool[update.Contents.Count]; } /// <summary> /// Gets the update being mapped. /// </summary> public ChatResponseUpdate Update { get; } /// <summary> /// Gets content items that have not been consumed by the state mapper. /// </summary> public IEnumerable<AIContent> UnhandledContents { get { var contents = Update.Contents; for (var i = 0; i < contents.Count; i++) { if (!_handled[i]) { yield return contents[i]; } } } } /// <summary> /// Marks a content item as consumed by the state mapper. /// </summary> /// <param name="content">The content item that was handled.</param> public void MarkHandled(AIContent content) { ArgumentNullException.ThrowIfNull(content); var contents = Update.Contents; for (var i = 0; i < contents.Count; i++) { if (ReferenceEquals(contents[i], content)) { if (!_handled[i]) { _handled[i] = true; _handledCount++; } return; } } } internal object? StateValue { get; private set; } /// <summary> /// Sets the next typed state value. /// </summary> /// <param name="value">The next state value.</param> public void SetState(object value) { ArgumentNullException.ThrowIfNull(value); StateValue = value; } internal bool HasHandledContent => _handledCount > 0; internal ChatResponseUpdate GetFilteredUpdate() { if (_handledCount == 0) { return Update; } var filtered = new List<AIContent>(); var contents = Update.Contents; for (var i = 0; i < contents.Count; i++) { if (!_handled[i]) { filtered.Add(contents[i]); } } return new ChatResponseUpdate { Role = Update.Role, AuthorName = Update.AuthorName, MessageId = Update.MessageId, ResponseId = Update.ResponseId, ConversationId = Update.ConversationId, CreatedAt = Update.CreatedAt, FinishReason = Update.FinishReason, ModelId = Update.ModelId, ContinuationToken = Update.ContinuationToken, RawRepresentation = Update.RawRepresentation, AdditionalProperties = Update.AdditionalProperties, Contents = filtered, }; } }