.NET Compaction - Add AsChatReducer() extension to expose CompactionStrategy as IChatReducer (#4664)

* Initial plan

* Add ChatStrategyExtensions.cs with AsChatReducer() extension method and tests

Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>

* Refactor message list creation in ReduceAsync method

* Remove unnecessary blank line in AsChatReducer method

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Fix test

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Chris Rickman <crickman@microsoft.com>
This commit is contained in:
Copilot
2026-03-18 17:25:54 +00:00
committed by GitHub
co-authored by crickman Copilot Autofix powered by AI copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Chris Rickman
parent acaf6b7054
commit d3d0100822
2 changed files with 218 additions and 0 deletions
@@ -0,0 +1,59 @@
// Copyright (c) Microsoft. All rights reserved.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using Microsoft.Shared.DiagnosticIds;
using Microsoft.Shared.Diagnostics;
namespace Microsoft.Agents.AI.Compaction;
/// <summary>
/// Provides extension methods for <see cref="CompactionStrategy"/>.
/// </summary>
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
public static class ChatStrategyExtensions
{
/// <summary>
/// Returns an <see cref="IChatReducer"/> that applies this <see cref="CompactionStrategy"/> to reduce a list of messages.
/// </summary>
/// <param name="strategy">The compaction strategy to wrap as an <see cref="IChatReducer"/>.</param>
/// <returns>
/// An <see cref="IChatReducer"/> that, on each call to <see cref="IChatReducer.ReduceAsync"/>, builds a
/// <see cref="CompactionMessageIndex"/> from the supplied messages and applies the strategy's compaction logic,
/// returning the resulting included messages.
/// </returns>
/// <remarks>
/// This allows any <see cref="CompactionStrategy"/> to be used wherever an <see cref="IChatReducer"/> is expected,
/// bridging the compaction pipeline into systems bound to the <c>Microsoft.Extensions.AI</c> <see cref="IChatReducer"/> contract.
/// </remarks>
public static IChatReducer AsChatReducer(this CompactionStrategy strategy)
{
Throw.IfNull(strategy);
return new CompactionStrategyChatReducer(strategy);
}
/// <summary>
/// An <see cref="IChatReducer"/> adapter that delegates to a <see cref="CompactionStrategy"/>.
/// </summary>
private sealed class CompactionStrategyChatReducer : IChatReducer
{
private readonly CompactionStrategy _strategy;
public CompactionStrategyChatReducer(CompactionStrategy strategy)
{
this._strategy = strategy;
}
/// <inheritdoc/>
public async Task<IEnumerable<ChatMessage>> ReduceAsync(IEnumerable<ChatMessage> messages, CancellationToken cancellationToken = default)
{
CompactionMessageIndex index = CompactionMessageIndex.Create([.. messages]);
await this._strategy.CompactAsync(index, cancellationToken: cancellationToken).ConfigureAwait(false);
return index.GetIncludedMessages();
}
}
}