diff --git a/dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/Program.cs b/dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/Program.cs
index 0a57de892e..0118ac1d60 100644
--- a/dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/Program.cs
+++ b/dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/Program.cs
@@ -47,7 +47,7 @@ PipelineCompactionStrategy compactionPipeline =
new SummarizationCompactionStrategy(summarizerChatClient, CompactionTriggers.TokensExceed(0x500)),
// 3. Aggressive: keep only the last N user turns and their responses
- new SlidingWindowCompactionStrategy(maximumTurns: 4),
+ new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(4)),
// 4. Emergency: drop oldest groups until under the token budget
new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(0x8000)));
diff --git a/dotnet/src/Microsoft.Agents.AI/Compaction/SlidingWindowCompactionStrategy.cs b/dotnet/src/Microsoft.Agents.AI/Compaction/SlidingWindowCompactionStrategy.cs
index a811da19f7..6a7f2e5c73 100644
--- a/dotnet/src/Microsoft.Agents.AI/Compaction/SlidingWindowCompactionStrategy.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Compaction/SlidingWindowCompactionStrategy.cs
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
+using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -7,20 +8,18 @@ using System.Threading.Tasks;
namespace Microsoft.Agents.AI.Compaction;
///
-/// A compaction strategy that keeps only the most recent user turns and their
-/// associated response groups, removing older turns to bound conversation length.
+/// A compaction strategy that removes the oldest user turns and their associated response groups
+/// to bound conversation length.
///
///
///
/// This strategy always preserves system messages. It identifies user turns in the
-/// conversation (via ) and keeps the last
-/// turns along with all response groups (assistant replies,
-/// tool call groups) that belong to each kept turn.
+/// conversation (via ) and excludes the oldest turns
+/// one at a time until the condition is met.
///
///
-/// The predicate controls when compaction proceeds.
-/// When , a default trigger of
-/// with is used.
+/// is a hard floor: even if the
+/// has not been reached, compaction will not touch the last non-system groups.
///
///
/// This strategy is more predictable than token-based truncation for bounding conversation
@@ -30,62 +29,87 @@ namespace Microsoft.Agents.AI.Compaction;
public sealed class SlidingWindowCompactionStrategy : CompactionStrategy
{
///
- /// The default maximum number of user turns to retain before compaction occurs. This default is a reasonable starting point
- /// for many conversations, but should be tuned based on the expected conversation length and token budget.
+ /// The default minimum number of most-recent non-system groups to preserve.
///
- public const int DefaultMaximumTurns = 32;
+ public const int DefaultMinimumPreserved = 1;
///
/// Initializes a new instance of the class.
///
- ///
- /// The maximum number of user turns to keep. Older turns and their associated responses are removed.
+ ///
+ /// The that controls when compaction proceeds.
+ /// Use for turn-based thresholds.
+ ///
+ ///
+ /// The minimum number of most-recent non-system message groups to preserve.
+ /// This is a hard floor — compaction will not exclude groups beyond this limit,
+ /// regardless of the target condition.
///
///
/// An optional target condition that controls when compaction stops. When ,
- /// defaults to the inverse of the auto-derived trigger — compaction stops as soon as the turn count is within bounds.
+ /// defaults to the inverse of the — compaction stops as soon as the trigger would no longer fire.
///
- public SlidingWindowCompactionStrategy(int maximumTurns = DefaultMaximumTurns, CompactionTrigger? target = null)
- : base(CompactionTriggers.TurnsExceed(maximumTurns), target)
+ public SlidingWindowCompactionStrategy(CompactionTrigger trigger, int minimumPreserved = DefaultMinimumPreserved, CompactionTrigger? target = null)
+ : base(trigger, target)
{
- this.MaxTurns = maximumTurns;
+ this.MinimumPreserved = minimumPreserved;
}
///
- /// Gets the maximum number of user turns to retain after compaction.
+ /// Gets the minimum number of most-recent non-system groups that are always preserved.
+ /// This is a hard floor that compaction cannot exceed, regardless of the target condition.
///
- public int MaxTurns { get; }
+ public int MinimumPreserved { get; }
///
protected override Task ApplyCompactionAsync(MessageIndex index, CancellationToken cancellationToken)
{
- // Collect distinct included turn indices in order
- List includedTurns = [];
+ // Identify protected groups: the N most-recent non-system, non-excluded groups
+ List nonSystemIncludedIndices = [];
foreach (MessageGroup group in index.Groups)
{
- if (!group.IsExcluded && group.TurnIndex is int turnIndex && !includedTurns.Contains(turnIndex))
+ if (!group.IsExcluded && group.Kind != MessageGroupKind.System)
{
- includedTurns.Add(turnIndex);
+ nonSystemIncludedIndices.Add(index.Groups.IndexOf(group));
}
}
- if (includedTurns.Count <= this.MaxTurns)
+ int protectedStart = Math.Max(0, nonSystemIncludedIndices.Count - this.MinimumPreserved);
+ HashSet protectedGroupIndices = [];
+ for (int i = protectedStart; i < nonSystemIncludedIndices.Count; i++)
{
- return Task.FromResult(false);
+ protectedGroupIndices.Add(nonSystemIncludedIndices[i]);
+ }
+
+ // Collect distinct included turn indices in order (oldest first), excluding protected groups
+ List excludableTurns = [];
+ for (int i = 0; i < index.Groups.Count; i++)
+ {
+ MessageGroup group = index.Groups[i];
+ if (!group.IsExcluded
+ && group.Kind != MessageGroupKind.System
+ && !protectedGroupIndices.Contains(i)
+ && group.TurnIndex is int turnIndex
+ && !excludableTurns.Contains(turnIndex))
+ {
+ excludableTurns.Add(turnIndex);
+ }
}
// Exclude one turn at a time from oldest, re-checking target after each
- int turnsToRemove = includedTurns.Count - this.MaxTurns;
bool compacted = false;
- for (int t = 0; t < turnsToRemove; t++)
+ for (int t = 0; t < excludableTurns.Count; t++)
{
- int turnToExclude = includedTurns[t];
+ int turnToExclude = excludableTurns[t];
for (int i = 0; i < index.Groups.Count; i++)
{
MessageGroup group = index.Groups[i];
- if (!group.IsExcluded && group.Kind != MessageGroupKind.System && group.TurnIndex == turnToExclude)
+ if (!group.IsExcluded
+ && group.Kind != MessageGroupKind.System
+ && !protectedGroupIndices.Contains(i)
+ && group.TurnIndex == turnToExclude)
{
group.IsExcluded = true;
group.ExcludeReason = $"Excluded by {nameof(SlidingWindowCompactionStrategy)}";
diff --git a/dotnet/src/Microsoft.Agents.AI/Compaction/SummarizationCompactionStrategy.cs b/dotnet/src/Microsoft.Agents.AI/Compaction/SummarizationCompactionStrategy.cs
index 3ec645e372..0e7c01719c 100644
--- a/dotnet/src/Microsoft.Agents.AI/Compaction/SummarizationCompactionStrategy.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Compaction/SummarizationCompactionStrategy.cs
@@ -16,12 +16,16 @@ namespace Microsoft.Agents.AI.Compaction;
///
///
///
-/// This strategy protects system messages and the most recent
+/// This strategy protects system messages and the most recent
/// non-system groups. All older groups are collected and sent to the
/// for summarization. The resulting summary replaces those messages as a single assistant message
/// with .
///
///
+/// is a hard floor: even if the
+/// has not been reached, compaction will not touch the last non-system groups.
+///
+///
/// The predicate controls when compaction proceeds.
/// When , the strategy compacts whenever there are groups older than the preserve window.
/// Use for common trigger conditions such as token thresholds.
@@ -50,9 +54,10 @@ public sealed class SummarizationCompactionStrategy : CompactionStrategy
///
/// The that controls when compaction proceeds.
///
- ///
- /// The number of most-recent non-system message groups to protect from summarization.
- /// Defaults to 4, preserving the current and recent exchanges.
+ ///
+ /// The minimum number of most-recent non-system message groups to preserve.
+ /// This is a hard floor — compaction will not summarize groups beyond this limit,
+ /// regardless of the target condition. Defaults to 4, preserving the current and recent exchanges.
///
///
/// An optional custom system prompt for the summarization LLM call. When ,
@@ -65,13 +70,13 @@ public sealed class SummarizationCompactionStrategy : CompactionStrategy
public SummarizationCompactionStrategy(
IChatClient chatClient,
CompactionTrigger trigger,
- int preserveRecentGroups = 4,
+ int minimumPreserved = 4,
string? summarizationPrompt = null,
CompactionTrigger? target = null)
: base(trigger, target)
{
this.ChatClient = Throw.IfNull(chatClient);
- this.PreserveRecentGroups = preserveRecentGroups;
+ this.MinimumPreserved = minimumPreserved;
this.SummarizationPrompt = summarizationPrompt ?? DefaultSummarizationPrompt;
}
@@ -81,9 +86,10 @@ public sealed class SummarizationCompactionStrategy : CompactionStrategy
public IChatClient ChatClient { get; }
///
- /// Gets the number of most-recent non-system groups to protect from summarization.
+ /// Gets the minimum number of most-recent non-system groups that are always preserved.
+ /// This is a hard floor that compaction cannot exceed, regardless of the target condition.
///
- public int PreserveRecentGroups { get; }
+ public int MinimumPreserved { get; }
///
/// Gets the prompt used when requesting summaries from the chat client.
@@ -104,7 +110,7 @@ public sealed class SummarizationCompactionStrategy : CompactionStrategy
}
}
- int protectedFromEnd = Math.Min(this.PreserveRecentGroups, nonSystemIncludedCount);
+ int protectedFromEnd = Math.Min(this.MinimumPreserved, nonSystemIncludedCount);
int maxSummarizable = nonSystemIncludedCount - protectedFromEnd;
if (maxSummarizable <= 0)
diff --git a/dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultCompactionStrategy.cs b/dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultCompactionStrategy.cs
index 8692e47159..a54c096cd2 100644
--- a/dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultCompactionStrategy.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultCompactionStrategy.cs
@@ -21,6 +21,10 @@ namespace Microsoft.Agents.AI.Compaction;
/// [Tool calls: get_weather, search_docs].
///
///
+/// is a hard floor: even if the
+/// has not been reached, compaction will not touch the last non-system groups.
+///
+///
/// The predicate controls when compaction proceeds.
/// When , a default compound trigger of
/// AND
@@ -30,9 +34,9 @@ namespace Microsoft.Agents.AI.Compaction;
public sealed class ToolResultCompactionStrategy : CompactionStrategy
{
///
- /// The default number of most-recent non-system groups to protect from collapsing.
+ /// The default minimum number of most-recent non-system groups to preserve.
///
- public const int DefaultPreserveRecentGroups = 2;
+ public const int DefaultMinimumPreserved = 2;
///
/// Initializes a new instance of the class.
@@ -40,24 +44,27 @@ public sealed class ToolResultCompactionStrategy : CompactionStrategy
///
/// The that controls when compaction proceeds.
///
- ///
- /// The number of most-recent non-system message groups to protect from collapsing.
- /// Defaults to , ensuring the current turn's tool interactions remain visible.
+ ///
+ /// The minimum number of most-recent non-system message groups to preserve.
+ /// This is a hard floor — compaction will not collapse groups beyond this limit,
+ /// regardless of the target condition.
+ /// Defaults to , ensuring the current turn's tool interactions remain visible.
///
///
/// An optional target condition that controls when compaction stops. When ,
/// defaults to the inverse of the — compaction stops as soon as the trigger would no longer fire.
///
- public ToolResultCompactionStrategy(CompactionTrigger trigger, int preserveRecentGroups = DefaultPreserveRecentGroups, CompactionTrigger? target = null)
+ public ToolResultCompactionStrategy(CompactionTrigger trigger, int minimumPreserved = DefaultMinimumPreserved, CompactionTrigger? target = null)
: base(trigger, target)
{
- this.PreserveRecentGroups = preserveRecentGroups;
+ this.MinimumPreserved = minimumPreserved;
}
///
- /// Gets the number of most-recent non-system groups to protect from collapsing.
+ /// Gets the minimum number of most-recent non-system groups that are always preserved.
+ /// This is a hard floor that compaction cannot exceed, regardless of the target condition.
///
- public int PreserveRecentGroups { get; }
+ public int MinimumPreserved { get; }
///
protected override Task ApplyCompactionAsync(MessageIndex index, CancellationToken cancellationToken)
@@ -73,7 +80,7 @@ public sealed class ToolResultCompactionStrategy : CompactionStrategy
}
}
- int protectedStart = Math.Max(0, nonSystemIncludedIndices.Count - this.PreserveRecentGroups);
+ int protectedStart = Math.Max(0, nonSystemIncludedIndices.Count - this.MinimumPreserved);
HashSet protectedGroupIndices = [];
for (int i = protectedStart; i < nonSystemIncludedIndices.Count; i++)
{
diff --git a/dotnet/src/Microsoft.Agents.AI/Compaction/TruncationCompactionStrategy.cs b/dotnet/src/Microsoft.Agents.AI/Compaction/TruncationCompactionStrategy.cs
index 57a0eea528..3c7d8890f2 100644
--- a/dotnet/src/Microsoft.Agents.AI/Compaction/TruncationCompactionStrategy.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Compaction/TruncationCompactionStrategy.cs
@@ -7,7 +7,7 @@ namespace Microsoft.Agents.AI.Compaction;
///
/// A compaction strategy that removes the oldest non-system message groups,
-/// keeping the most recent groups up to .
+/// keeping at least most-recent groups intact.
///
///
///
@@ -16,6 +16,10 @@ namespace Microsoft.Agents.AI.Compaction;
/// corresponding tool result messages are always removed together.
///
///
+/// is a hard floor: even if the
+/// has not been reached, compaction will not touch the last non-system groups.
+///
+///
/// The controls when compaction proceeds.
/// Use for common trigger conditions such as token or group thresholds.
///
@@ -23,9 +27,9 @@ namespace Microsoft.Agents.AI.Compaction;
public sealed class TruncationCompactionStrategy : CompactionStrategy
{
///
- /// The default number of most-recent non-system groups to protect from collapsing.
+ /// The default minimum number of most-recent non-system groups to preserve.
///
- public const int DefaultPreserveRecentGroups = 32;
+ public const int DefaultMinimumPreserved = 32;
///
/// Initializes a new instance of the class.
@@ -33,24 +37,26 @@ public sealed class TruncationCompactionStrategy : CompactionStrategy
///
/// The that controls when compaction proceeds.
///
- ///
- /// The minimum number of most-recent non-system message groups to keep.
- /// Defaults to 1 so that at least the latest exchange is always preserved.
+ ///
+ /// The minimum number of most-recent non-system message groups to preserve.
+ /// This is a hard floor — compaction will not remove groups beyond this limit,
+ /// regardless of the target condition.
///
///
/// An optional target condition that controls when compaction stops. When ,
/// defaults to the inverse of the — compaction stops as soon as the trigger would no longer fire.
///
- public TruncationCompactionStrategy(CompactionTrigger trigger, int preserveRecentGroups = DefaultPreserveRecentGroups, CompactionTrigger? target = null)
+ public TruncationCompactionStrategy(CompactionTrigger trigger, int minimumPreserved = DefaultMinimumPreserved, CompactionTrigger? target = null)
: base(trigger, target)
{
- this.PreserveRecentGroups = preserveRecentGroups;
+ this.MinimumPreserved = minimumPreserved;
}
///
- /// Gets the minimum number of most-recent non-system message groups to retain after compaction.
+ /// Gets the minimum number of most-recent non-system message groups that are always preserved.
+ /// This is a hard floor that compaction cannot exceed, regardless of the target condition.
///
- public int PreserveRecentGroups { get; }
+ public int MinimumPreserved { get; }
///
protected override Task ApplyCompactionAsync(MessageIndex index, CancellationToken cancellationToken)
@@ -66,7 +72,7 @@ public sealed class TruncationCompactionStrategy : CompactionStrategy
}
}
- int maxRemovable = removableCount - this.PreserveRecentGroups;
+ int maxRemovable = removableCount - this.MinimumPreserved;
if (maxRemovable <= 0)
{
return Task.FromResult(false);
diff --git a/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/SlidingWindowCompactionStrategyTests.cs b/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/SlidingWindowCompactionStrategyTests.cs
index 74d057e9f0..2d78c2e720 100644
--- a/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/SlidingWindowCompactionStrategyTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/SlidingWindowCompactionStrategyTests.cs
@@ -15,8 +15,8 @@ public class SlidingWindowCompactionStrategyTests
[Fact]
public async Task CompactAsyncBelowMaxTurnsReturnsFalseAsync()
{
- // Arrange
- SlidingWindowCompactionStrategy strategy = new(maximumTurns: 3);
+ // Arrange — trigger requires > 3 turns, conversation has 2
+ SlidingWindowCompactionStrategy strategy = new(CompactionTriggers.TurnsExceed(3));
MessageIndex groups = MessageIndex.Create(
[
new ChatMessage(ChatRole.User, "Q1"),
@@ -35,8 +35,8 @@ public class SlidingWindowCompactionStrategyTests
[Fact]
public async Task CompactAsyncExceedsMaxTurnsExcludesOldestTurnsAsync()
{
- // Arrange — keep 2 turns, conversation has 3
- SlidingWindowCompactionStrategy strategy = new(maximumTurns: 2);
+ // Arrange — trigger on > 2 turns, conversation has 3
+ SlidingWindowCompactionStrategy strategy = new(CompactionTriggers.TurnsExceed(2));
MessageIndex groups = MessageIndex.Create(
[
new ChatMessage(ChatRole.User, "Q1"),
@@ -65,8 +65,8 @@ public class SlidingWindowCompactionStrategyTests
[Fact]
public async Task CompactAsyncPreservesSystemMessagesAsync()
{
- // Arrange
- SlidingWindowCompactionStrategy strategy = new(maximumTurns: 1);
+ // Arrange — trigger on > 1 turn
+ SlidingWindowCompactionStrategy strategy = new(CompactionTriggers.TurnsExceed(1));
MessageIndex groups = MessageIndex.Create(
[
new ChatMessage(ChatRole.System, "You are helpful."),
@@ -89,8 +89,8 @@ public class SlidingWindowCompactionStrategyTests
[Fact]
public async Task CompactAsyncPreservesToolCallGroupsInKeptTurnsAsync()
{
- // Arrange
- SlidingWindowCompactionStrategy strategy = new(maximumTurns: 1);
+ // Arrange — trigger on > 1 turn
+ SlidingWindowCompactionStrategy strategy = new(CompactionTriggers.TurnsExceed(1));
MessageIndex groups = MessageIndex.Create(
[
new ChatMessage(ChatRole.User, "Q1"),
@@ -114,10 +114,10 @@ public class SlidingWindowCompactionStrategyTests
}
[Fact]
- public async Task CompactAsyncCustomTriggerOverridesDefaultAsync()
+ public async Task CompactAsyncTriggerNotMetReturnsFalseAsync()
{
- // Arrange — custom trigger: only compact when tokens exceed threshold
- SlidingWindowCompactionStrategy strategy = new(maximumTurns: 99);
+ // Arrange — trigger requires > 99 turns
+ SlidingWindowCompactionStrategy strategy = new(CompactionTriggers.TurnsExceed(99));
MessageIndex groups = MessageIndex.Create(
[
@@ -126,7 +126,7 @@ public class SlidingWindowCompactionStrategyTests
new ChatMessage(ChatRole.User, "Q3"),
]);
- // Act — tokens are tiny, trigger not met
+ // Act
bool result = await strategy.CompactAsync(groups);
// Assert
@@ -136,8 +136,8 @@ public class SlidingWindowCompactionStrategyTests
[Fact]
public async Task CompactAsyncIncludedMessagesContainOnlyKeptTurnsAsync()
{
- // Arrange
- SlidingWindowCompactionStrategy strategy = new(maximumTurns: 1);
+ // Arrange — trigger on > 1 turn
+ SlidingWindowCompactionStrategy strategy = new(CompactionTriggers.TurnsExceed(1));
MessageIndex groups = MessageIndex.Create(
[
new ChatMessage(ChatRole.System, "System"),
@@ -161,13 +161,13 @@ public class SlidingWindowCompactionStrategyTests
[Fact]
public async Task CompactAsyncCustomTargetStopsExcludingEarlyAsync()
{
- // Arrange — 4 turns, maxTurns=1 means 3 should be excluded
- // But custom target stops after removing 1 turn
+ // Arrange — trigger on > 1 turn, custom target stops after removing 1 turn
int removeCount = 0;
CompactionTrigger targetAfterOne = _ => ++removeCount >= 1;
SlidingWindowCompactionStrategy strategy = new(
- maximumTurns: 1,
+ CompactionTriggers.TurnsExceed(1),
+ minimumPreserved: 0,
target: targetAfterOne);
MessageIndex index = MessageIndex.Create(
@@ -191,4 +191,34 @@ public class SlidingWindowCompactionStrategyTests
Assert.False(index.Groups[2].IsExcluded); // Q2 (turn 2) — kept
Assert.False(index.Groups[3].IsExcluded); // A2 (turn 2)
}
+
+ [Fact]
+ public async Task CompactAsyncMinimumPreservedStopsCompactionAsync()
+ {
+ // Arrange — always trigger with never-satisfied target, but MinimumPreserved = 2 is hard floor
+ SlidingWindowCompactionStrategy strategy = new(
+ CompactionTriggers.TurnsExceed(1),
+ minimumPreserved: 2,
+ target: _ => false);
+
+ MessageIndex index = MessageIndex.Create(
+ [
+ new ChatMessage(ChatRole.User, "Q1"),
+ new ChatMessage(ChatRole.Assistant, "A1"),
+ new ChatMessage(ChatRole.User, "Q2"),
+ new ChatMessage(ChatRole.Assistant, "A2"),
+ new ChatMessage(ChatRole.User, "Q3"),
+ new ChatMessage(ChatRole.Assistant, "A3"),
+ ]);
+
+ // Act
+ bool result = await strategy.CompactAsync(index);
+
+ // Assert — target never says stop, but MinimumPreserved=2 prevents removing the last 2 groups
+ Assert.True(result);
+ Assert.Equal(2, index.IncludedGroupCount);
+ // Last 2 non-system groups must be preserved
+ Assert.False(index.Groups[4].IsExcluded); // Q3
+ Assert.False(index.Groups[5].IsExcluded); // A3
+ }
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/SummarizationCompactionStrategyTests.cs b/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/SummarizationCompactionStrategyTests.cs
index a71fc4697f..d12d490dd4 100644
--- a/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/SummarizationCompactionStrategyTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/SummarizationCompactionStrategyTests.cs
@@ -38,7 +38,7 @@ public class SummarizationCompactionStrategyTests
SummarizationCompactionStrategy strategy = new(
CreateMockChatClient(),
CompactionTriggers.TokensExceed(100000),
- preserveRecentGroups: 1);
+ minimumPreserved: 1);
MessageIndex index = MessageIndex.Create(
[
@@ -61,7 +61,7 @@ public class SummarizationCompactionStrategyTests
SummarizationCompactionStrategy strategy = new(
CreateMockChatClient("Key facts from earlier."),
AlwaysTrigger,
- preserveRecentGroups: 1);
+ minimumPreserved: 1);
MessageIndex index = MessageIndex.Create(
[
@@ -92,7 +92,7 @@ public class SummarizationCompactionStrategyTests
SummarizationCompactionStrategy strategy = new(
CreateMockChatClient(),
AlwaysTrigger,
- preserveRecentGroups: 1);
+ minimumPreserved: 1);
MessageIndex index = MessageIndex.Create(
[
@@ -119,7 +119,7 @@ public class SummarizationCompactionStrategyTests
SummarizationCompactionStrategy strategy = new(
CreateMockChatClient("Summary text."),
AlwaysTrigger,
- preserveRecentGroups: 1);
+ minimumPreserved: 1);
MessageIndex index = MessageIndex.Create(
[
@@ -146,7 +146,7 @@ public class SummarizationCompactionStrategyTests
SummarizationCompactionStrategy strategy = new(
CreateMockChatClient(" "),
AlwaysTrigger,
- preserveRecentGroups: 1);
+ minimumPreserved: 1);
MessageIndex index = MessageIndex.Create(
[
@@ -169,7 +169,7 @@ public class SummarizationCompactionStrategyTests
SummarizationCompactionStrategy strategy = new(
CreateMockChatClient(),
AlwaysTrigger,
- preserveRecentGroups: 5);
+ minimumPreserved: 5);
MessageIndex index = MessageIndex.Create(
[
@@ -202,7 +202,7 @@ public class SummarizationCompactionStrategyTests
SummarizationCompactionStrategy strategy = new(
mockClient.Object,
AlwaysTrigger,
- preserveRecentGroups: 1,
+ minimumPreserved: 1,
summarizationPrompt: customPrompt);
MessageIndex index = MessageIndex.Create(
@@ -226,7 +226,7 @@ public class SummarizationCompactionStrategyTests
SummarizationCompactionStrategy strategy = new(
CreateMockChatClient(),
AlwaysTrigger,
- preserveRecentGroups: 1);
+ minimumPreserved: 1);
MessageIndex index = MessageIndex.Create(
[
@@ -253,7 +253,7 @@ public class SummarizationCompactionStrategyTests
SummarizationCompactionStrategy strategy = new(
CreateMockChatClient("Partial summary."),
AlwaysTrigger,
- preserveRecentGroups: 1,
+ minimumPreserved: 1,
target: targetAfterOne);
MessageIndex index = MessageIndex.Create(
@@ -279,7 +279,7 @@ public class SummarizationCompactionStrategyTests
SummarizationCompactionStrategy strategy = new(
CreateMockChatClient("Summary."),
AlwaysTrigger,
- preserveRecentGroups: 2);
+ minimumPreserved: 2);
MessageIndex index = MessageIndex.Create(
[
diff --git a/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/ToolResultCompactionStrategyTests.cs b/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/ToolResultCompactionStrategyTests.cs
index 39c03f2631..66300e69f0 100644
--- a/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/ToolResultCompactionStrategyTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/ToolResultCompactionStrategyTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft. All rights reserved.
+// Copyright (c) Microsoft. All rights reserved.
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -41,7 +41,7 @@ public class ToolResultCompactionStrategyTests
// Arrange — always trigger
ToolResultCompactionStrategy strategy = new(
trigger: _ => true,
- preserveRecentGroups: 1);
+ minimumPreserved: 1);
MessageIndex groups = MessageIndex.Create(
[
@@ -71,7 +71,7 @@ public class ToolResultCompactionStrategyTests
// Arrange — protect 2 recent non-system groups (the tool group + Q2)
ToolResultCompactionStrategy strategy = new(
trigger: _ => true,
- preserveRecentGroups: 3);
+ minimumPreserved: 3);
MessageIndex groups = MessageIndex.Create(
[
@@ -94,7 +94,7 @@ public class ToolResultCompactionStrategyTests
// Arrange
ToolResultCompactionStrategy strategy = new(
trigger: _ => true,
- preserveRecentGroups: 1);
+ minimumPreserved: 1);
MessageIndex groups = MessageIndex.Create(
[
@@ -119,7 +119,7 @@ public class ToolResultCompactionStrategyTests
// Arrange — assistant calls two tools
ToolResultCompactionStrategy strategy = new(
trigger: _ => true,
- preserveRecentGroups: 1);
+ minimumPreserved: 1);
ChatMessage multiToolCall = new(ChatRole.Assistant,
[
@@ -152,7 +152,7 @@ public class ToolResultCompactionStrategyTests
// Arrange — trigger fires but no tool groups to collapse
ToolResultCompactionStrategy strategy = new(
trigger: _ => true,
- preserveRecentGroups: 0);
+ minimumPreserved: 0);
MessageIndex groups = MessageIndex.Create(
[
@@ -175,7 +175,7 @@ public class ToolResultCompactionStrategyTests
CompactionTriggers.All(
CompactionTriggers.TokensExceed(0),
CompactionTriggers.HasToolCalls()),
- preserveRecentGroups: 1);
+ minimumPreserved: 1);
MessageIndex groups = MessageIndex.Create(
[
@@ -201,7 +201,7 @@ public class ToolResultCompactionStrategyTests
ToolResultCompactionStrategy strategy = new(
trigger: _ => true,
- preserveRecentGroups: 1,
+ minimumPreserved: 1,
target: targetAfterOne);
MessageIndex index = MessageIndex.Create(
diff --git a/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/TruncationCompactionStrategyTests.cs b/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/TruncationCompactionStrategyTests.cs
index 1799758ddd..ee08611653 100644
--- a/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/TruncationCompactionStrategyTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/TruncationCompactionStrategyTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft. All rights reserved.
+// Copyright (c) Microsoft. All rights reserved.
using System.Linq;
using System.Threading.Tasks;
@@ -18,7 +18,7 @@ public class TruncationCompactionStrategyTests
public async Task CompactAsyncAlwaysTriggerCompactsToPreserveRecentAsync()
{
// Arrange — always-trigger means always compact
- TruncationCompactionStrategy strategy = new(s_alwaysTrigger, preserveRecentGroups: 1);
+ TruncationCompactionStrategy strategy = new(s_alwaysTrigger, minimumPreserved: 1);
MessageIndex groups = MessageIndex.Create(
[
new ChatMessage(ChatRole.User, "First"),
@@ -39,7 +39,7 @@ public class TruncationCompactionStrategyTests
{
// Arrange — trigger requires > 1000 tokens, conversation is tiny
TruncationCompactionStrategy strategy = new(
- preserveRecentGroups: 1,
+ minimumPreserved: 1,
trigger: CompactionTriggers.TokensExceed(1000));
MessageIndex groups = MessageIndex.Create(
@@ -61,7 +61,7 @@ public class TruncationCompactionStrategyTests
{
// Arrange — trigger on groups > 2
TruncationCompactionStrategy strategy = new(
- preserveRecentGroups: 1,
+ minimumPreserved: 1,
trigger: CompactionTriggers.GroupsExceed(2));
MessageIndex groups = MessageIndex.Create(
@@ -89,7 +89,7 @@ public class TruncationCompactionStrategyTests
public async Task CompactAsyncPreservesSystemMessagesAsync()
{
// Arrange
- TruncationCompactionStrategy strategy = new(s_alwaysTrigger, preserveRecentGroups: 1);
+ TruncationCompactionStrategy strategy = new(s_alwaysTrigger, minimumPreserved: 1);
MessageIndex groups = MessageIndex.Create(
[
new ChatMessage(ChatRole.System, "You are helpful."),
@@ -117,7 +117,7 @@ public class TruncationCompactionStrategyTests
public async Task CompactAsyncPreservesToolCallGroupAtomicityAsync()
{
// Arrange
- TruncationCompactionStrategy strategy = new(s_alwaysTrigger, preserveRecentGroups: 1);
+ TruncationCompactionStrategy strategy = new(s_alwaysTrigger, minimumPreserved: 1);
ChatMessage assistantToolCall= new(ChatRole.Assistant, [new FunctionCallContent("call1", "get_weather")]);
ChatMessage toolResult = new(ChatRole.Tool, "Sunny");
@@ -141,7 +141,7 @@ public class TruncationCompactionStrategyTests
public async Task CompactAsyncSetsExcludeReasonAsync()
{
// Arrange
- TruncationCompactionStrategy strategy = new(s_alwaysTrigger, preserveRecentGroups: 1);
+ TruncationCompactionStrategy strategy = new(s_alwaysTrigger, minimumPreserved: 1);
MessageIndex groups = MessageIndex.Create(
[
new ChatMessage(ChatRole.User, "Old"),
@@ -160,7 +160,7 @@ public class TruncationCompactionStrategyTests
public async Task CompactAsyncSkipsAlreadyExcludedGroupsAsync()
{
// Arrange
- TruncationCompactionStrategy strategy = new(s_alwaysTrigger, preserveRecentGroups: 1);
+ TruncationCompactionStrategy strategy = new(s_alwaysTrigger, minimumPreserved: 1);
MessageIndex groups = MessageIndex.Create(
[
new ChatMessage(ChatRole.User, "Already excluded"),
@@ -180,10 +180,10 @@ public class TruncationCompactionStrategyTests
}
[Fact]
- public async Task CompactAsyncPreserveRecentGroupsKeepsMultipleAsync()
+ public async Task CompactAsyncMinimumPreservedKeepsMultipleAsync()
{
// Arrange — keep 2 most recent
- TruncationCompactionStrategy strategy = new(s_alwaysTrigger, preserveRecentGroups: 2);
+ TruncationCompactionStrategy strategy = new(s_alwaysTrigger, minimumPreserved: 2);
MessageIndex groups = MessageIndex.Create(
[
new ChatMessage(ChatRole.User, "Q1"),
@@ -207,7 +207,7 @@ public class TruncationCompactionStrategyTests
public async Task CompactAsyncNothingToRemoveReturnsFalseAsync()
{
// Arrange — preserve 5 but only 2 groups
- TruncationCompactionStrategy strategy = new(s_alwaysTrigger, preserveRecentGroups: 5);
+ TruncationCompactionStrategy strategy = new(s_alwaysTrigger, minimumPreserved: 5);
MessageIndex groups = MessageIndex.Create(
[
new ChatMessage(ChatRole.User, "Hello"),
@@ -230,7 +230,7 @@ public class TruncationCompactionStrategyTests
TruncationCompactionStrategy strategy = new(
s_alwaysTrigger,
- preserveRecentGroups: 1,
+ minimumPreserved: 1,
target: targetAfterOne);
MessageIndex groups = MessageIndex.Create(
@@ -258,7 +258,7 @@ public class TruncationCompactionStrategyTests
// Arrange — trigger on groups > 2, target is default (inverse of trigger: groups <= 2)
TruncationCompactionStrategy strategy = new(
CompactionTriggers.GroupsExceed(2),
- preserveRecentGroups: 1);
+ minimumPreserved: 1);
MessageIndex groups = MessageIndex.Create(
[