From 7dccf3a07bc5fd76004b85305f5121712e188b15 Mon Sep 17 00:00:00 2001
From: westey <164392973+westey-m@users.noreply.github.com>
Date: Tue, 10 Feb 2026 19:21:18 +0000
Subject: [PATCH] .NET: [BREAKING] Update message source code to match python.
(#3805)
* Update message source code to match python.
* Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Address PR comment
* Move setting of source information to extension method
* Add underscore for attribution key to indicate internal usage
* Stick to version 102 of the SDK since 103 is causing issues.
* Revert global.json change
* Fix unit test
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
.../AIContextProvider.cs | 36 +-
.../AgentRequestMessageSource.cs | 16 -
.../AgentRequestMessageSourceAttribution.cs | 102 ++++
.../AgentRequestMessageSourceType.cs | 35 +-
.../ChatHistoryProvider.cs | 34 +-
.../ChatHistoryProviderExtensions.cs | 2 +-
.../ChatMessageExtensions.cs | 60 ++-
.../Microsoft.Agents.AI.Mem0/Mem0Provider.cs | 4 +-
.../Memory/ChatHistoryMemoryProvider.cs | 4 +-
.../Microsoft.Agents.AI/TextSearchProvider.cs | 4 +-
.../AIContextProviderTests.cs | 45 +-
...entRequestMessageSourceAttributionTests.cs | 466 ++++++++++++++++++
.../AgentRequestMessageSourceTypeTests.cs | 103 +---
.../ChatHistoryProviderExtensionsTests.cs | 6 +-
.../ChatHistoryProviderMessageFilterTests.cs | 4 +-
.../ChatHistoryProviderTests.cs | 45 +-
.../ChatMessageExtensionsTests.cs | 390 +++++++++++++--
.../InMemoryChatHistoryProviderTests.cs | 2 +-
.../CosmosChatHistoryProviderTests.cs | 2 +-
19 files changed, 1084 insertions(+), 276 deletions(-)
delete mode 100644 dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSource.cs
create mode 100644 dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSourceAttribution.cs
create mode 100644 dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentRequestMessageSourceAttributionTests.cs
diff --git a/dotnet/src/Microsoft.Agents.AI.Abstractions/AIContextProvider.cs b/dotnet/src/Microsoft.Agents.AI.Abstractions/AIContextProvider.cs
index a4b606e6a1..76ff8752b9 100644
--- a/dotnet/src/Microsoft.Agents.AI.Abstractions/AIContextProvider.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Abstractions/AIContextProvider.cs
@@ -32,23 +32,23 @@ namespace Microsoft.Agents.AI;
///
public abstract class AIContextProvider
{
- private readonly string _sourceName;
+ private readonly string _sourceId;
///
/// Initializes a new instance of the class.
///
protected AIContextProvider()
{
- this._sourceName = this.GetType().FullName!;
+ this._sourceId = this.GetType().FullName!;
}
///
- /// Initializes a new instance of the class with the specified source name.
+ /// Initializes a new instance of the class with the specified source id.
///
- /// The source name to stamp on for each messages produced by the .
- protected AIContextProvider(string sourceName)
+ /// The source id to stamp on for each messages produced by the .
+ protected AIContextProvider(string sourceId)
{
- this._sourceName = sourceName;
+ this._sourceId = sourceId;
}
///
@@ -76,27 +76,9 @@ public abstract class AIContextProvider
return aiContext;
}
- aiContext.Messages = aiContext.Messages.Select(message =>
- {
- if (message.AdditionalProperties != null
- // Check if the message was already tagged with this provider's source type
- && message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceType.AdditionalPropertiesKey, out var messageSourceType)
- && messageSourceType is AgentRequestMessageSourceType typedMessageSourceType
- && typedMessageSourceType == AgentRequestMessageSourceType.AIContextProvider
- // Check if the message was already tagged with this provider's source
- && message.AdditionalProperties.TryGetValue(AgentRequestMessageSource.AdditionalPropertiesKey, out var messageSource)
- && messageSource is string typedMessageSource
- && typedMessageSource == this._sourceName)
- {
- return message;
- }
-
- message = message.Clone();
- message.AdditionalProperties ??= new();
- message.AdditionalProperties[AgentRequestMessageSourceType.AdditionalPropertiesKey] = AgentRequestMessageSourceType.AIContextProvider;
- message.AdditionalProperties[AgentRequestMessageSource.AdditionalPropertiesKey] = this._sourceName;
- return message;
- }).ToList();
+ aiContext.Messages = aiContext.Messages
+ .Select(message => message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.AIContextProvider, this._sourceId))
+ .ToList();
return aiContext;
}
diff --git a/dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSource.cs b/dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSource.cs
deleted file mode 100644
index 127f1c1b8d..0000000000
--- a/dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSource.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using Microsoft.Extensions.AI;
-
-namespace Microsoft.Agents.AI;
-
-///
-/// Provides a constant for the key used to store the source of the agent request message.
-///
-public static class AgentRequestMessageSource
-{
- ///
- /// Provides the key used in to store the source of the agent request message.
- ///
- public static readonly string AdditionalPropertiesKey = "Agent.RequestMessageSource";
-}
diff --git a/dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSourceAttribution.cs b/dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSourceAttribution.cs
new file mode 100644
index 0000000000..2c606814ce
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSourceAttribution.cs
@@ -0,0 +1,102 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using Microsoft.Extensions.AI;
+
+namespace Microsoft.Agents.AI;
+
+///
+/// Represents attribution information for the source of an agent request message for a specific run, including the component type and
+/// identifier.
+///
+///
+/// Use this struct to identify which component provided a message during an agent run.
+/// This is useful to allow filtering of messages based on their source, such as distinguishing between user input, middleware-generated messages, and chat history.
+///
+public readonly struct AgentRequestMessageSourceAttribution : IEquatable
+{
+ ///
+ /// Provides the key used in to store the
+ /// associated with the agent request message.
+ ///
+ public static readonly string AdditionalPropertiesKey = "_attribution";
+
+ ///
+ /// Initializes a new instance of the struct with the specified source type and identifier.
+ ///
+ /// The of the component that provided the message.
+ /// The unique identifier of the component that provided the message.
+ public AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType sourceType, string? sourceId)
+ {
+ this.SourceType = sourceType;
+ this.SourceId = sourceId;
+ }
+
+ ///
+ /// Gets the type of component that provided the message for the current agent run.
+ ///
+ public AgentRequestMessageSourceType SourceType { get; }
+
+ ///
+ /// Gets the unique identifier of the component that provided the message for the current agent run.
+ ///
+ public string? SourceId { get; }
+
+ ///
+ /// Determines whether the specified is equal to the current instance.
+ ///
+ /// The to compare with the current instance.
+ /// if the specified instance is equal to the current instance; otherwise, .
+ public bool Equals(AgentRequestMessageSourceAttribution other)
+ {
+ return this.SourceType == other.SourceType &&
+ string.Equals(this.SourceId, other.SourceId, StringComparison.Ordinal);
+ }
+
+ ///
+ /// Determines whether the specified object is equal to the current instance.
+ ///
+ /// The object to compare with the current instance.
+ /// if the specified object is equal to the current instance; otherwise, .
+ public override bool Equals(object? obj)
+ {
+ return obj is AgentRequestMessageSourceAttribution other && this.Equals(other);
+ }
+
+ ///
+ /// Returns a hash code for the current instance.
+ ///
+ /// A hash code for the current instance.
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 17;
+ hash = (hash * 31) + this.SourceType.GetHashCode();
+ hash = (hash * 31) + (this.SourceId?.GetHashCode() ?? 0);
+ return hash;
+ }
+ }
+
+ ///
+ /// Determines whether two instances are equal.
+ ///
+ /// The first instance to compare.
+ /// The second instance to compare.
+ /// if the instances are equal; otherwise, .
+ public static bool operator ==(AgentRequestMessageSourceAttribution left, AgentRequestMessageSourceAttribution right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Determines whether two instances are not equal.
+ ///
+ /// The first instance to compare.
+ /// The second instance to compare.
+ /// if the instances are not equal; otherwise, .
+ public static bool operator !=(AgentRequestMessageSourceAttribution left, AgentRequestMessageSourceAttribution right)
+ {
+ return !left.Equals(right);
+ }
+}
diff --git a/dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSourceType.cs b/dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSourceType.cs
index 1cca747906..14bbbe3388 100644
--- a/dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSourceType.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRequestMessageSourceType.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
-using Microsoft.Extensions.AI;
using Microsoft.Shared.Diagnostics;
namespace Microsoft.Agents.AI;
@@ -14,15 +13,10 @@ namespace Microsoft.Agents.AI;
/// This type helps to identify whether a message came from outside the agent pipeline,
/// whether it was produced by middleware, or came from chat history.
///
-public sealed class AgentRequestMessageSourceType : IEquatable
+public readonly struct AgentRequestMessageSourceType : IEquatable
{
///
- /// Provides the key used in to store the source type of the agent request message.
- ///
- public static readonly string AdditionalPropertiesKey = "Agent.RequestMessageSourceType";
-
- ///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the struct.
///
/// The string value representing the source of the agent request message.
public AgentRequestMessageSourceType(string value) => this.Value = Throw.IfNullOrWhitespace(value);
@@ -30,7 +24,7 @@ public sealed class AgentRequestMessageSourceType : IEquatable
/// Get the string value representing the source of the agent request message.
///
- public string Value { get; }
+ public string Value { get { return field ?? External.Value; } }
///
/// The message came from outside the agent pipeline (e.g., user input).
@@ -52,18 +46,8 @@ public sealed class AgentRequestMessageSourceType : IEquatable
/// The to compare to this instance.
/// if the value of the parameter is the same as the value of this instance; otherwise, .
- public bool Equals(AgentRequestMessageSourceType? other)
+ public bool Equals(AgentRequestMessageSourceType other)
{
- if (other is null)
- {
- return false;
- }
-
- if (ReferenceEquals(this, other))
- {
- return true;
- }
-
return string.Equals(this.Value, other.Value, StringComparison.Ordinal);
}
@@ -72,7 +56,7 @@ public sealed class AgentRequestMessageSourceType : IEquatable
/// The object to compare to this instance.
/// if is a and its value is the same as this instance; otherwise, .
- public override bool Equals(object? obj) => this.Equals(obj as AgentRequestMessageSourceType);
+ public override bool Equals(object? obj) => obj is AgentRequestMessageSourceType other && this.Equals(other);
///
/// Returns the hash code for this instance.
@@ -86,13 +70,8 @@ public sealed class AgentRequestMessageSourceType : IEquatableThe first to compare.
/// The second to compare.
/// if the value of is the same as the value of ; otherwise, .
- public static bool operator ==(AgentRequestMessageSourceType? left, AgentRequestMessageSourceType? right)
+ public static bool operator ==(AgentRequestMessageSourceType left, AgentRequestMessageSourceType right)
{
- if (left is null)
- {
- return right is null;
- }
-
return left.Equals(right);
}
@@ -102,5 +81,5 @@ public sealed class AgentRequestMessageSourceType : IEquatableThe first to compare.
/// The second to compare.
/// if the value of is different from the value of ; otherwise, .
- public static bool operator !=(AgentRequestMessageSourceType? left, AgentRequestMessageSourceType? right) => !(left == right);
+ public static bool operator !=(AgentRequestMessageSourceType left, AgentRequestMessageSourceType right) => !(left == right);
}
diff --git a/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatHistoryProvider.cs b/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatHistoryProvider.cs
index f49c5d46a7..086ad02061 100644
--- a/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatHistoryProvider.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatHistoryProvider.cs
@@ -37,23 +37,23 @@ namespace Microsoft.Agents.AI;
///
public abstract class ChatHistoryProvider
{
- private readonly string _sourceName;
+ private readonly string _sourceId;
///
/// Initializes a new instance of the class.
///
protected ChatHistoryProvider()
{
- this._sourceName = this.GetType().FullName!;
+ this._sourceId = this.GetType().FullName!;
}
///
- /// Initializes a new instance of the class with the specified source name.
+ /// Initializes a new instance of the class with the specified source id.
///
- /// The source name to stamp on for each messages produced by the .
- protected ChatHistoryProvider(string sourceName)
+ /// The source id to stamp on for each messages produced by the .
+ protected ChatHistoryProvider(string sourceId)
{
- this._sourceName = sourceName;
+ this._sourceId = sourceId;
}
///
@@ -89,27 +89,7 @@ public abstract class ChatHistoryProvider
{
var messages = await this.InvokingCoreAsync(context, cancellationToken).ConfigureAwait(false);
- return messages.Select(message =>
- {
- if (message.AdditionalProperties != null
- // Check if the message was already tagged with this provider's source type
- && message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceType.AdditionalPropertiesKey, out var messageSourceType)
- && messageSourceType is AgentRequestMessageSourceType typedMessageSourceType
- && typedMessageSourceType == AgentRequestMessageSourceType.ChatHistory
- // Check if the message was already tagged with this provider's source
- && message.AdditionalProperties.TryGetValue(AgentRequestMessageSource.AdditionalPropertiesKey, out var messageSource)
- && messageSource is string typedMessageSource
- && typedMessageSource == this._sourceName)
- {
- return message;
- }
-
- message = message.Clone();
- message.AdditionalProperties ??= new();
- message.AdditionalProperties[AgentRequestMessageSourceType.AdditionalPropertiesKey] = AgentRequestMessageSourceType.ChatHistory;
- message.AdditionalProperties[AgentRequestMessageSource.AdditionalPropertiesKey] = this._sourceName;
- return message;
- });
+ return messages.Select(message => message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.ChatHistory, this._sourceId));
}
///
diff --git a/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatHistoryProviderExtensions.cs b/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatHistoryProviderExtensions.cs
index c2ff8bf3e5..4c8ef2489f 100644
--- a/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatHistoryProviderExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatHistoryProviderExtensions.cs
@@ -45,7 +45,7 @@ public static class ChatHistoryProviderExtensions
innerProvider: provider,
invokedMessagesFilter: (ctx) =>
{
- ctx.RequestMessages = ctx.RequestMessages.Where(x => x.GetAgentRequestMessageSource() != AgentRequestMessageSourceType.AIContextProvider);
+ ctx.RequestMessages = ctx.RequestMessages.Where(x => x.GetAgentRequestMessageSourceType() != AgentRequestMessageSourceType.AIContextProvider);
return ctx;
});
}
diff --git a/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatMessageExtensions.cs b/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatMessageExtensions.cs
index 01edcb4eff..052e48ce56 100644
--- a/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatMessageExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Abstractions/ChatMessageExtensions.cs
@@ -10,18 +10,66 @@ namespace Microsoft.Agents.AI;
public static class ChatMessageExtensions
{
///
- /// Gets the source of the provided in the context of messages passed into an agent run.
+ /// Gets the source type of the provided in the context of messages passed into an agent run.
///
- /// The for which we need the source.
- /// An value indicating the source of the . Defaults to The for which we need the source type.
+ /// An value indicating the source type of the . Defaults to if no explicit source is defined.
- public static AgentRequestMessageSourceType GetAgentRequestMessageSource(this ChatMessage message)
+ public static AgentRequestMessageSourceType GetAgentRequestMessageSourceType(this ChatMessage message)
{
- if (message.AdditionalProperties?.TryGetValue(AgentRequestMessageSourceType.AdditionalPropertiesKey, out var source) is true && source is AgentRequestMessageSourceType typedSource)
+ if (message.AdditionalProperties?.TryGetValue(AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, out var attribution) is true
+ && attribution is AgentRequestMessageSourceAttribution typedAttribution)
{
- return typedSource;
+ return typedAttribution.SourceType;
}
return AgentRequestMessageSourceType.External;
}
+
+ ///
+ /// Gets the source id of the provided in the context of messages passed into an agent run.
+ ///
+ /// The for which we need the source id.
+ /// An value indicating the source id of the . Defaults to
+ /// if no explicit source id is defined.
+ public static string? GetAgentRequestMessageSourceId(this ChatMessage message)
+ {
+ if (message.AdditionalProperties?.TryGetValue(AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, out var attribution) is true
+ && attribution is AgentRequestMessageSourceAttribution typedAttribution)
+ {
+ return typedAttribution.SourceId;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Ensure that the provided message is tagged with the provided source type and source id in the context of a specific agent run.
+ ///
+ /// The message to tag.
+ /// The source type to tag the message with.
+ /// The source id to tag the message with.
+ /// The tagged message.
+ ///
+ /// If the message is already tagged with the provided source type and source id, it is returned as is.
+ /// Otherwise, a cloned message is returned with the appropriate tagging in the AdditionalProperties.
+ ///
+ public static ChatMessage AsAgentRequestMessageSourcedMessage(this ChatMessage message, AgentRequestMessageSourceType sourceType, string? sourceId = null)
+ {
+ if (message.AdditionalProperties != null
+ // Check if the message was already tagged with the required source type and source id
+ && message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, out var messageSourceAttribution)
+ && messageSourceAttribution is AgentRequestMessageSourceAttribution typedMessageSourceAttribution
+ && typedMessageSourceAttribution.SourceType == sourceType
+ && typedMessageSourceAttribution.SourceId == sourceId)
+ {
+ return message;
+ }
+
+ message = message.Clone();
+ message.AdditionalProperties ??= new();
+ message.AdditionalProperties[AgentRequestMessageSourceAttribution.AdditionalPropertiesKey] =
+ new AgentRequestMessageSourceAttribution(sourceType, sourceId);
+ return message;
+ }
}
diff --git a/dotnet/src/Microsoft.Agents.AI.Mem0/Mem0Provider.cs b/dotnet/src/Microsoft.Agents.AI.Mem0/Mem0Provider.cs
index 8a0c016f07..a230eb0e4e 100644
--- a/dotnet/src/Microsoft.Agents.AI.Mem0/Mem0Provider.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Mem0/Mem0Provider.cs
@@ -138,7 +138,7 @@ public sealed class Mem0Provider : AIContextProvider
string queryText = string.Join(
Environment.NewLine,
context.RequestMessages
- .Where(m => m.GetAgentRequestMessageSource() == AgentRequestMessageSourceType.External)
+ .Where(m => m.GetAgentRequestMessageSourceType() == AgentRequestMessageSourceType.External)
.Where(m => !string.IsNullOrWhiteSpace(m.Text))
.Select(m => m.Text));
@@ -217,7 +217,7 @@ public sealed class Mem0Provider : AIContextProvider
// Persist request and response messages after invocation.
await this.PersistMessagesAsync(
context.RequestMessages
- .Where(m => m.GetAgentRequestMessageSource() == AgentRequestMessageSourceType.External)
+ .Where(m => m.GetAgentRequestMessageSourceType() == AgentRequestMessageSourceType.External)
.Concat(context.ResponseMessages ?? []),
cancellationToken).ConfigureAwait(false);
}
diff --git a/dotnet/src/Microsoft.Agents.AI/Memory/ChatHistoryMemoryProvider.cs b/dotnet/src/Microsoft.Agents.AI/Memory/ChatHistoryMemoryProvider.cs
index c63e8ac682..b8e495152c 100644
--- a/dotnet/src/Microsoft.Agents.AI/Memory/ChatHistoryMemoryProvider.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Memory/ChatHistoryMemoryProvider.cs
@@ -189,7 +189,7 @@ public sealed class ChatHistoryMemoryProvider : AIContextProvider, IDisposable
{
// Get the text from the current request messages
var requestText = string.Join("\n", context.RequestMessages
- .Where(m => m.GetAgentRequestMessageSource() == AgentRequestMessageSourceType.External)
+ .Where(m => m.GetAgentRequestMessageSourceType() == AgentRequestMessageSourceType.External)
.Where(m => m != null && !string.IsNullOrWhiteSpace(m.Text))
.Select(m => m.Text));
@@ -245,7 +245,7 @@ public sealed class ChatHistoryMemoryProvider : AIContextProvider, IDisposable
var collection = await this.EnsureCollectionExistsAsync(cancellationToken).ConfigureAwait(false);
List> itemsToStore = context.RequestMessages
- .Where(m => m.GetAgentRequestMessageSource() == AgentRequestMessageSourceType.External)
+ .Where(m => m.GetAgentRequestMessageSourceType() == AgentRequestMessageSourceType.External)
.Concat(context.ResponseMessages ?? [])
.Select(message => new Dictionary
{
diff --git a/dotnet/src/Microsoft.Agents.AI/TextSearchProvider.cs b/dotnet/src/Microsoft.Agents.AI/TextSearchProvider.cs
index ee87d4f00c..f29aadf808 100644
--- a/dotnet/src/Microsoft.Agents.AI/TextSearchProvider.cs
+++ b/dotnet/src/Microsoft.Agents.AI/TextSearchProvider.cs
@@ -118,7 +118,7 @@ public sealed class TextSearchProvider : AIContextProvider
// Aggregate text from memory + current request messages.
var sbInput = new StringBuilder();
var requestMessagesText = context.RequestMessages
- .Where(m => m.GetAgentRequestMessageSource() == AgentRequestMessageSourceType.External)
+ .Where(m => m.GetAgentRequestMessageSourceType() == AgentRequestMessageSourceType.External)
.Where(x => !string.IsNullOrWhiteSpace(x?.Text)).Select(x => x.Text);
foreach (var messageText in this._recentMessagesText.Concat(requestMessagesText))
{
@@ -182,7 +182,7 @@ public sealed class TextSearchProvider : AIContextProvider
}
var messagesText = context.RequestMessages
- .Where(m => m.GetAgentRequestMessageSource() == AgentRequestMessageSourceType.External)
+ .Where(m => m.GetAgentRequestMessageSourceType() == AgentRequestMessageSourceType.External)
.Concat(context.ResponseMessages ?? [])
.Where(m =>
this._recentMessageRolesIncluded.Contains(m.Role) &&
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIContextProviderTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIContextProviderTests.cs
index 44d1be2e74..aa41a03efc 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIContextProviderTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIContextProviderTests.cs
@@ -19,7 +19,7 @@ public class AIContextProviderTests
#region InvokingAsync Message Stamping Tests
[Fact]
- public async Task InvokingAsync_StampsMessagesWithSourceTypeAndSourceAsync()
+ public async Task InvokingAsync_StampsMessagesWithSourceTypeAndSourceIdAsync()
{
// Arrange
var provider = new TestAIContextProviderWithMessages();
@@ -32,18 +32,18 @@ public class AIContextProviderTests
Assert.NotNull(aiContext.Messages);
ChatMessage message = aiContext.Messages.Single();
Assert.NotNull(message.AdditionalProperties);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceType.AdditionalPropertiesKey, out object? sourceType));
- Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, sourceType);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSource.AdditionalPropertiesKey, out object? source));
- Assert.Equal(typeof(TestAIContextProviderWithMessages).FullName, source);
+ Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, out object? attribution));
+ var typedAttribution = Assert.IsType(attribution);
+ Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, typedAttribution.SourceType);
+ Assert.Equal(typeof(TestAIContextProviderWithMessages).FullName, typedAttribution.SourceId);
}
[Fact]
- public async Task InvokingAsync_WithCustomSourceName_StampsMessagesWithCustomSourceAsync()
+ public async Task InvokingAsync_WithCustomSourceId_StampsMessagesWithCustomSourceIdAsync()
{
// Arrange
- const string CustomSourceName = "CustomContextSource";
- var provider = new TestAIContextProviderWithCustomSource(CustomSourceName);
+ const string CustomSourceId = "CustomContextSource";
+ var provider = new TestAIContextProviderWithCustomSource(CustomSourceId);
var context = new AIContextProvider.InvokingContext(s_mockAgent, s_mockSession, [new ChatMessage(ChatRole.User, "Request")]);
// Act
@@ -53,10 +53,10 @@ public class AIContextProviderTests
Assert.NotNull(aiContext.Messages);
ChatMessage message = aiContext.Messages.Single();
Assert.NotNull(message.AdditionalProperties);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceType.AdditionalPropertiesKey, out object? sourceType));
- Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, sourceType);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSource.AdditionalPropertiesKey, out object? source));
- Assert.Equal(CustomSourceName, source);
+ Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, out object? attribution));
+ var typedAttribution = Assert.IsType(attribution);
+ Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, typedAttribution.SourceType);
+ Assert.Equal(CustomSourceId, typedAttribution.SourceId);
}
[Fact]
@@ -73,10 +73,10 @@ public class AIContextProviderTests
Assert.NotNull(aiContext.Messages);
ChatMessage message = aiContext.Messages.Single();
Assert.NotNull(message.AdditionalProperties);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceType.AdditionalPropertiesKey, out object? sourceType));
- Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, sourceType);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSource.AdditionalPropertiesKey, out object? source));
- Assert.Equal(typeof(TestAIContextProviderWithPreStampedMessages).FullName, source);
+ Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, out object? attribution));
+ var typedAttribution = Assert.IsType(attribution);
+ Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, typedAttribution.SourceType);
+ Assert.Equal(typeof(TestAIContextProviderWithPreStampedMessages).FullName, typedAttribution.SourceId);
}
[Fact]
@@ -97,10 +97,10 @@ public class AIContextProviderTests
foreach (ChatMessage message in messageList)
{
Assert.NotNull(message.AdditionalProperties);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceType.AdditionalPropertiesKey, out object? sourceType));
- Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, sourceType);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSource.AdditionalPropertiesKey, out object? source));
- Assert.Equal(typeof(TestAIContextProviderWithMultipleMessages).FullName, source);
+ Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, out object? attribution));
+ var typedAttribution = Assert.IsType(attribution);
+ Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, typedAttribution.SourceType);
+ Assert.Equal(typeof(TestAIContextProviderWithMultipleMessages).FullName, typedAttribution.SourceId);
}
}
@@ -486,7 +486,7 @@ public class AIContextProviderTests
private sealed class TestAIContextProviderWithCustomSource : AIContextProvider
{
- public TestAIContextProviderWithCustomSource(string sourceName) : base(sourceName)
+ public TestAIContextProviderWithCustomSource(string sourceId) : base(sourceId)
{
}
@@ -504,8 +504,7 @@ public class AIContextProviderTests
var message = new ChatMessage(ChatRole.System, "Pre-stamped Message");
message.AdditionalProperties = new AdditionalPropertiesDictionary
{
- [AgentRequestMessageSourceType.AdditionalPropertiesKey] = AgentRequestMessageSourceType.AIContextProvider,
- [AgentRequestMessageSource.AdditionalPropertiesKey] = this.GetType().FullName!
+ [AgentRequestMessageSourceAttribution.AdditionalPropertiesKey] = new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.AIContextProvider, this.GetType().FullName!)
};
return new(new AIContext
{
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentRequestMessageSourceAttributionTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentRequestMessageSourceAttributionTests.cs
new file mode 100644
index 0000000000..5aee121097
--- /dev/null
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentRequestMessageSourceAttributionTests.cs
@@ -0,0 +1,466 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+namespace Microsoft.Agents.AI.Abstractions.UnitTests;
+
+///
+/// Contains tests for the struct.
+///
+public sealed class AgentRequestMessageSourceAttributionTests
+{
+ #region Constructor Tests
+
+ [Fact]
+ public void Constructor_SetsSourceTypeAndSourceId()
+ {
+ // Arrange
+ AgentRequestMessageSourceType expectedType = AgentRequestMessageSourceType.AIContextProvider;
+ const string ExpectedId = "MyProvider";
+
+ // Act
+ AgentRequestMessageSourceAttribution attribution = new(expectedType, ExpectedId);
+
+ // Assert
+ Assert.Equal(expectedType, attribution.SourceType);
+ Assert.Equal(ExpectedId, attribution.SourceId);
+ }
+
+ [Fact]
+ public void Constructor_WithNullSourceId_SetsNullSourceId()
+ {
+ // Arrange
+ AgentRequestMessageSourceType sourceType = AgentRequestMessageSourceType.ChatHistory;
+
+ // Act
+ AgentRequestMessageSourceAttribution attribution = new(sourceType, null);
+
+ // Assert
+ Assert.Equal(sourceType, attribution.SourceType);
+ Assert.Null(attribution.SourceId);
+ }
+
+ #endregion
+
+ #region AdditionalPropertiesKey Tests
+
+ [Fact]
+ public void AdditionalPropertiesKey_IsAttribution()
+ {
+ // Assert
+ Assert.Equal("_attribution", AgentRequestMessageSourceAttribution.AdditionalPropertiesKey);
+ }
+
+ #endregion
+
+ #region Default Value Tests
+
+ [Fact]
+ public void Default_HasDefaultSourceTypeAndNullSourceId()
+ {
+ // Arrange & Act
+ AgentRequestMessageSourceAttribution attribution = default;
+
+ // Assert
+ Assert.Equal(default, attribution.SourceType);
+ Assert.Null(attribution.SourceId);
+ }
+
+ #endregion
+
+ #region Equals (IEquatable) Tests
+
+ [Fact]
+ public void Equals_WithSameSourceTypeAndSourceId_ReturnsTrue()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider1");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider1");
+
+ // Act
+ bool result = attribution1.Equals(attribution2);
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Fact]
+ public void Equals_WithDifferentSourceType_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider1");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.ChatHistory, "Provider1");
+
+ // Act
+ bool result = attribution1.Equals(attribution2);
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Fact]
+ public void Equals_WithDifferentSourceId_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider1");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider2");
+
+ // Act
+ bool result = attribution1.Equals(attribution2);
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Fact]
+ public void Equals_WithDifferentSourceTypeAndSourceId_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider1");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.ChatHistory, "Provider2");
+
+ // Act
+ bool result = attribution1.Equals(attribution2);
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Fact]
+ public void Equals_WithDifferentCaseSourceId_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.AIContextProvider, "provider");
+
+ // Act
+ bool result = attribution1.Equals(attribution2);
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Fact]
+ public void Equals_BothDefaultValues_ReturnsTrue()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = default;
+ AgentRequestMessageSourceAttribution attribution2 = default;
+
+ // Act
+ bool result = attribution1.Equals(attribution2);
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Fact]
+ public void Equals_WithBothNullSourceIds_ReturnsTrue()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.External, null!);
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.External, null!);
+
+ // Act
+ bool result = attribution1.Equals(attribution2);
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Fact]
+ public void Equals_WithOneNullSourceId_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.External, "Provider1");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.External, null!);
+
+ // Act
+ bool result = attribution1.Equals(attribution2);
+
+ // Assert
+ Assert.False(result);
+ }
+
+ #endregion
+
+ #region Object.Equals Tests
+
+ [Fact]
+ public void ObjectEquals_WithEqualAttribution_ReturnsTrue()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.ChatHistory, "Provider");
+ object attribution2 = new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.ChatHistory, "Provider");
+
+ // Act
+ bool result = attribution1.Equals(attribution2);
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Fact]
+ public void ObjectEquals_WithDifferentType_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution = new(AgentRequestMessageSourceType.ChatHistory, "Provider");
+ object other = "NotAnAttribution";
+
+ // Act
+ bool result = attribution.Equals(other);
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Fact]
+ public void ObjectEquals_WithNullObject_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution = new(AgentRequestMessageSourceType.ChatHistory, "Provider");
+ object? other = null;
+
+ // Act
+ bool result = attribution.Equals(other);
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Fact]
+ public void ObjectEquals_WithBoxedDifferentAttribution_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.ChatHistory, "Provider1");
+ object attribution2 = new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.ChatHistory, "Provider2");
+
+ // Act
+ bool result = attribution1.Equals(attribution2);
+
+ // Assert
+ Assert.False(result);
+ }
+
+ #endregion
+
+ #region GetHashCode Tests
+
+ [Fact]
+ public void GetHashCode_WithSameValues_ReturnsSameHashCode()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider");
+
+ // Act
+ int hashCode1 = attribution1.GetHashCode();
+ int hashCode2 = attribution2.GetHashCode();
+
+ // Assert
+ Assert.Equal(hashCode1, hashCode2);
+ }
+
+ [Fact]
+ public void GetHashCode_WithDifferentSourceType_ReturnsDifferentHashCode()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.ChatHistory, "Provider");
+
+ // Act
+ int hashCode1 = attribution1.GetHashCode();
+ int hashCode2 = attribution2.GetHashCode();
+
+ // Assert
+ Assert.NotEqual(hashCode1, hashCode2);
+ }
+
+ [Fact]
+ public void GetHashCode_WithDifferentSourceId_ReturnsDifferentHashCode()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider1");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider2");
+
+ // Act
+ int hashCode1 = attribution1.GetHashCode();
+ int hashCode2 = attribution2.GetHashCode();
+
+ // Assert
+ Assert.NotEqual(hashCode1, hashCode2);
+ }
+
+ [Fact]
+ public void GetHashCode_ConsistentWithEquals()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.External, "Provider");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.External, "Provider");
+
+ // Act & Assert
+ Assert.True(attribution1.Equals(attribution2));
+ Assert.Equal(attribution1.GetHashCode(), attribution2.GetHashCode());
+ }
+
+ [Fact]
+ public void GetHashCode_WithNullSourceId_DoesNotThrow()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution = new(AgentRequestMessageSourceType.External, null!);
+
+ // Act
+ int hashCode = attribution.GetHashCode();
+
+ // Assert
+ Assert.IsType(hashCode);
+ }
+
+ #endregion
+
+ #region Equality Operator Tests
+
+ [Fact]
+ public void EqualityOperator_WithEqualValues_ReturnsTrue()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider");
+
+ // Act
+ bool result = attribution1 == attribution2;
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Fact]
+ public void EqualityOperator_WithDifferentValues_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider1");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.ChatHistory, "Provider2");
+
+ // Act
+ bool result = attribution1 == attribution2;
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Fact]
+ public void EqualityOperator_WithBothDefault_ReturnsTrue()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = default;
+ AgentRequestMessageSourceAttribution attribution2 = default;
+
+ // Act
+ bool result = attribution1 == attribution2;
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Fact]
+ public void EqualityOperator_WithDifferentSourceTypeOnly_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.External, "Provider");
+
+ // Act
+ bool result = attribution1 == attribution2;
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Fact]
+ public void EqualityOperator_WithDifferentSourceIdOnly_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider1");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider2");
+
+ // Act
+ bool result = attribution1 == attribution2;
+
+ // Assert
+ Assert.False(result);
+ }
+
+ #endregion
+
+ #region Inequality Operator Tests
+
+ [Fact]
+ public void InequalityOperator_WithEqualValues_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider");
+
+ // Act
+ bool result = attribution1 != attribution2;
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Fact]
+ public void InequalityOperator_WithDifferentValues_ReturnsTrue()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider1");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.ChatHistory, "Provider2");
+
+ // Act
+ bool result = attribution1 != attribution2;
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Fact]
+ public void InequalityOperator_WithBothDefault_ReturnsFalse()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = default;
+ AgentRequestMessageSourceAttribution attribution2 = default;
+
+ // Act
+ bool result = attribution1 != attribution2;
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Fact]
+ public void InequalityOperator_WithDifferentSourceTypeOnly_ReturnsTrue()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.External, "Provider");
+
+ // Act
+ bool result = attribution1 != attribution2;
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Fact]
+ public void InequalityOperator_WithDifferentSourceIdOnly_ReturnsTrue()
+ {
+ // Arrange
+ AgentRequestMessageSourceAttribution attribution1 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider1");
+ AgentRequestMessageSourceAttribution attribution2 = new(AgentRequestMessageSourceType.AIContextProvider, "Provider2");
+
+ // Act
+ bool result = attribution1 != attribution2;
+
+ // Assert
+ Assert.True(result);
+ }
+
+ #endregion
+}
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentRequestMessageSourceTypeTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentRequestMessageSourceTypeTests.cs
index f6149092f3..000505fe32 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentRequestMessageSourceTypeTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentRequestMessageSourceTypeTests.cs
@@ -5,7 +5,7 @@ using System;
namespace Microsoft.Agents.AI.Abstractions.UnitTests;
///
-/// Contains tests for the class.
+/// Contains tests for the struct.
///
public sealed class AgentRequestMessageSourceTypeTests
{
@@ -38,6 +38,16 @@ public sealed class AgentRequestMessageSourceTypeTests
Assert.Throws(() => new AgentRequestMessageSourceType(string.Empty));
}
+ [Fact]
+ public void Default_DefaultsToExternal()
+ {
+ // Act
+ AgentRequestMessageSourceType defaultSource = default;
+
+ // Assert
+ Assert.Equal(AgentRequestMessageSourceType.External, defaultSource);
+ }
+
#endregion
#region Static Properties Tests
@@ -49,7 +59,6 @@ public sealed class AgentRequestMessageSourceTypeTests
AgentRequestMessageSourceType source = AgentRequestMessageSourceType.External;
// Assert
- Assert.NotNull(source);
Assert.Equal("External", source.Value);
}
@@ -60,7 +69,6 @@ public sealed class AgentRequestMessageSourceTypeTests
AgentRequestMessageSourceType source = AgentRequestMessageSourceType.AIContextProvider;
// Assert
- Assert.NotNull(source);
Assert.Equal("AIContextProvider", source.Value);
}
@@ -71,22 +79,11 @@ public sealed class AgentRequestMessageSourceTypeTests
AgentRequestMessageSourceType source = AgentRequestMessageSourceType.ChatHistory;
// Assert
- Assert.NotNull(source);
Assert.Equal("ChatHistory", source.Value);
}
[Fact]
- public void AdditionalPropertiesKey_ReturnsExpectedValue()
- {
- // Arrange & Act
- string key = AgentRequestMessageSourceType.AdditionalPropertiesKey;
-
- // Assert
- Assert.Equal("Agent.RequestMessageSourceType", key);
- }
-
- [Fact]
- public void StaticProperties_ReturnSameInstanceOnMultipleCalls()
+ public void StaticProperties_ReturnEqualValuesOnMultipleCalls()
{
// Arrange & Act
AgentRequestMessageSourceType external1 = AgentRequestMessageSourceType.External;
@@ -97,9 +94,9 @@ public sealed class AgentRequestMessageSourceTypeTests
AgentRequestMessageSourceType chatHistory2 = AgentRequestMessageSourceType.ChatHistory;
// Assert
- Assert.Same(external1, external2);
- Assert.Same(aiContextProvider1, aiContextProvider2);
- Assert.Same(chatHistory1, chatHistory2);
+ Assert.Equal(external1, external2);
+ Assert.Equal(aiContextProvider1, aiContextProvider2);
+ Assert.Equal(chatHistory1, chatHistory2);
}
#endregion
@@ -148,7 +145,7 @@ public sealed class AgentRequestMessageSourceTypeTests
}
[Fact]
- public void Equals_WithNull_ReturnsFalse()
+ public void Equals_WithNullObject_ReturnsFalse()
{
// Arrange
AgentRequestMessageSourceType source = new("Test");
@@ -314,11 +311,11 @@ public sealed class AgentRequestMessageSourceTypeTests
}
[Fact]
- public void EqualityOperator_WithBothNull_ReturnsTrue()
+ public void EqualityOperator_WithDefaultValues_ReturnsTrue()
{
// Arrange
- AgentRequestMessageSourceType? source1 = null;
- AgentRequestMessageSourceType? source2 = null;
+ AgentRequestMessageSourceType source1 = default;
+ AgentRequestMessageSourceType source2 = default;
// Act
bool result = source1 == source2;
@@ -327,34 +324,6 @@ public sealed class AgentRequestMessageSourceTypeTests
Assert.True(result);
}
- [Fact]
- public void EqualityOperator_WithLeftNull_ReturnsFalse()
- {
- // Arrange
- AgentRequestMessageSourceType? source1 = null;
- AgentRequestMessageSourceType source2 = new("Test");
-
- // Act
- bool result = source1 == source2;
-
- // Assert
- Assert.False(result);
- }
-
- [Fact]
- public void EqualityOperator_WithRightNull_ReturnsFalse()
- {
- // Arrange
- AgentRequestMessageSourceType source1 = new("Test");
- AgentRequestMessageSourceType? source2 = null;
-
- // Act
- bool result = source1 == source2;
-
- // Assert
- Assert.False(result);
- }
-
[Fact]
public void EqualityOperator_WithStaticInstances_ReturnsTrue()
{
@@ -416,11 +385,11 @@ public sealed class AgentRequestMessageSourceTypeTests
}
[Fact]
- public void InequalityOperator_WithBothNull_ReturnsFalse()
+ public void InequalityOperator_WithBothDefault_ReturnsFalse()
{
// Arrange
- AgentRequestMessageSourceType? source1 = null;
- AgentRequestMessageSourceType? source2 = null;
+ AgentRequestMessageSourceType source1 = default;
+ AgentRequestMessageSourceType source2 = default;
// Act
bool result = source1 != source2;
@@ -429,34 +398,6 @@ public sealed class AgentRequestMessageSourceTypeTests
Assert.False(result);
}
- [Fact]
- public void InequalityOperator_WithLeftNull_ReturnsTrue()
- {
- // Arrange
- AgentRequestMessageSourceType? source1 = null;
- AgentRequestMessageSourceType source2 = new("Test");
-
- // Act
- bool result = source1 != source2;
-
- // Assert
- Assert.True(result);
- }
-
- [Fact]
- public void InequalityOperator_WithRightNull_ReturnsTrue()
- {
- // Arrange
- AgentRequestMessageSourceType source1 = new("Test");
- AgentRequestMessageSourceType? source2 = null;
-
- // Act
- bool result = source1 != source2;
-
- // Assert
- Assert.True(result);
- }
-
[Fact]
public void InequalityOperator_DifferentStaticInstances_ReturnsTrue()
{
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderExtensionsTests.cs
index 1244209a97..1fcbe37e25 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderExtensionsTests.cs
@@ -64,7 +64,7 @@ public sealed class ChatHistoryProviderExtensionsTests
Mock providerMock = new();
List requestMessages =
[
- new(ChatRole.System, "System") { AdditionalProperties = new() { { AgentRequestMessageSourceType.AdditionalPropertiesKey, AgentRequestMessageSourceType.ChatHistory } } },
+ new(ChatRole.System, "System") { AdditionalProperties = new() { { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.ChatHistory, "TestSource") } } },
new(ChatRole.User, "Hello")
];
ChatHistoryProvider.InvokedContext context = new(s_mockAgent, s_mockSession, requestMessages)
@@ -114,9 +114,9 @@ public sealed class ChatHistoryProviderExtensionsTests
Mock providerMock = new();
List requestMessages =
[
- new(ChatRole.System, "System") { AdditionalProperties = new() { { AgentRequestMessageSourceType.AdditionalPropertiesKey, AgentRequestMessageSourceType.ChatHistory } } },
+ new(ChatRole.System, "System") { AdditionalProperties = new() { { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.ChatHistory, "TestSource") } } },
new(ChatRole.User, "Hello"),
- new(ChatRole.System, "Context") { AdditionalProperties = new() { { AgentRequestMessageSourceType.AdditionalPropertiesKey, AgentRequestMessageSourceType.AIContextProvider } } }
+ new(ChatRole.System, "Context") { AdditionalProperties = new() { { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.AIContextProvider, "TestContextSource") } } }
];
ChatHistoryProvider.InvokedContext context = new(s_mockAgent, s_mockSession, requestMessages);
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderMessageFilterTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderMessageFilterTests.cs
index 5b48d025be..75d8f554c5 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderMessageFilterTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderMessageFilterTests.cs
@@ -157,7 +157,7 @@ public sealed class ChatHistoryProviderMessageFilterTests
var innerProviderMock = new Mock();
List requestMessages =
[
- new(ChatRole.System, "System") { AdditionalProperties = new() { { AgentRequestMessageSourceType.AdditionalPropertiesKey, AgentRequestMessageSourceType.ChatHistory } } },
+ new(ChatRole.System, "System") { AdditionalProperties = new() { { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.ChatHistory, "TestSource") } } },
new(ChatRole.User, "Hello"),
];
var responseMessages = new List { new(ChatRole.Assistant, "Response") };
@@ -176,7 +176,7 @@ public sealed class ChatHistoryProviderMessageFilterTests
// Filter that modifies the context
ChatHistoryProvider.InvokedContext InvokedFilter(ChatHistoryProvider.InvokedContext ctx)
{
- var modifiedRequestMessages = ctx.RequestMessages.Where(x => x.GetAgentRequestMessageSource() == AgentRequestMessageSourceType.External).Select(m => new ChatMessage(m.Role, $"[FILTERED] {m.Text}")).ToList();
+ var modifiedRequestMessages = ctx.RequestMessages.Where(x => x.GetAgentRequestMessageSourceType() == AgentRequestMessageSourceType.External).Select(m => new ChatMessage(m.Role, $"[FILTERED] {m.Text}")).ToList();
return new ChatHistoryProvider.InvokedContext(s_mockAgent, s_mockSession, modifiedRequestMessages)
{
ResponseMessages = ctx.ResponseMessages,
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderTests.cs
index e158b159ca..8b07366b03 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderTests.cs
@@ -22,7 +22,7 @@ public class ChatHistoryProviderTests
#region InvokingAsync Message Stamping Tests
[Fact]
- public async Task InvokingAsync_StampsMessagesWithSourceTypeAndSourceAsync()
+ public async Task InvokingAsync_StampsMessagesWithSourceTypeAndSourceIdAsync()
{
// Arrange
var provider = new TestChatHistoryProvider();
@@ -34,18 +34,18 @@ public class ChatHistoryProviderTests
// Assert
ChatMessage message = messages.Single();
Assert.NotNull(message.AdditionalProperties);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceType.AdditionalPropertiesKey, out object? sourceType));
- Assert.Equal(AgentRequestMessageSourceType.ChatHistory, sourceType);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSource.AdditionalPropertiesKey, out object? source));
- Assert.Equal(typeof(TestChatHistoryProvider).FullName, source);
+ Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, out object? attribution));
+ var typedAttribution = Assert.IsType(attribution);
+ Assert.Equal(AgentRequestMessageSourceType.ChatHistory, typedAttribution.SourceType);
+ Assert.Equal(typeof(TestChatHistoryProvider).FullName, typedAttribution.SourceId);
}
[Fact]
- public async Task InvokingAsync_WithCustomSourceName_StampsMessagesWithCustomSourceAsync()
+ public async Task InvokingAsync_WithCustomSourceId_StampsMessagesWithCustomSourceIdAsync()
{
// Arrange
- const string CustomSourceName = "CustomHistorySource";
- var provider = new TestChatHistoryProviderWithCustomSource(CustomSourceName);
+ const string CustomSourceId = "CustomHistorySource";
+ var provider = new TestChatHistoryProviderWithCustomSource(CustomSourceId);
var context = new ChatHistoryProvider.InvokingContext(s_mockAgent, s_mockSession, [new ChatMessage(ChatRole.User, "Request")]);
// Act
@@ -54,10 +54,10 @@ public class ChatHistoryProviderTests
// Assert
ChatMessage message = messages.Single();
Assert.NotNull(message.AdditionalProperties);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceType.AdditionalPropertiesKey, out object? sourceType));
- Assert.Equal(AgentRequestMessageSourceType.ChatHistory, sourceType);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSource.AdditionalPropertiesKey, out object? source));
- Assert.Equal(CustomSourceName, source);
+ Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, out object? attribution));
+ var typedAttribution = Assert.IsType(attribution);
+ Assert.Equal(AgentRequestMessageSourceType.ChatHistory, typedAttribution.SourceType);
+ Assert.Equal(CustomSourceId, typedAttribution.SourceId);
}
[Fact]
@@ -73,10 +73,10 @@ public class ChatHistoryProviderTests
// Assert
ChatMessage message = messages.Single();
Assert.NotNull(message.AdditionalProperties);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceType.AdditionalPropertiesKey, out object? sourceType));
- Assert.Equal(AgentRequestMessageSourceType.ChatHistory, sourceType);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSource.AdditionalPropertiesKey, out object? source));
- Assert.Equal(typeof(TestChatHistoryProviderWithPreStampedMessages).FullName, source);
+ Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, out object? attribution));
+ var typedAttribution = Assert.IsType(attribution);
+ Assert.Equal(AgentRequestMessageSourceType.ChatHistory, typedAttribution.SourceType);
+ Assert.Equal(typeof(TestChatHistoryProviderWithPreStampedMessages).FullName, typedAttribution.SourceId);
}
[Fact]
@@ -96,10 +96,10 @@ public class ChatHistoryProviderTests
foreach (ChatMessage message in messageList)
{
Assert.NotNull(message.AdditionalProperties);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceType.AdditionalPropertiesKey, out object? sourceType));
- Assert.Equal(AgentRequestMessageSourceType.ChatHistory, sourceType);
- Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSource.AdditionalPropertiesKey, out object? source));
- Assert.Equal(typeof(TestChatHistoryProviderWithMultipleMessages).FullName, source);
+ Assert.True(message.AdditionalProperties.TryGetValue(AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, out object? attribution));
+ var typedAttribution = Assert.IsType(attribution);
+ Assert.Equal(AgentRequestMessageSourceType.ChatHistory, typedAttribution.SourceType);
+ Assert.Equal(typeof(TestChatHistoryProviderWithMultipleMessages).FullName, typedAttribution.SourceId);
}
}
@@ -383,7 +383,7 @@ public class ChatHistoryProviderTests
private sealed class TestChatHistoryProviderWithCustomSource : ChatHistoryProvider
{
- public TestChatHistoryProviderWithCustomSource(string sourceName) : base(sourceName)
+ public TestChatHistoryProviderWithCustomSource(string sourceId) : base(sourceId)
{
}
@@ -404,8 +404,7 @@ public class ChatHistoryProviderTests
var message = new ChatMessage(ChatRole.User, "Pre-stamped Message");
message.AdditionalProperties = new AdditionalPropertiesDictionary
{
- [AgentRequestMessageSourceType.AdditionalPropertiesKey] = AgentRequestMessageSourceType.ChatHistory,
- [AgentRequestMessageSource.AdditionalPropertiesKey] = this.GetType().FullName!
+ [AgentRequestMessageSourceAttribution.AdditionalPropertiesKey] = new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.ChatHistory, this.GetType().FullName!)
};
return new([message]);
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatMessageExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatMessageExtensionsTests.cs
index f389c567d2..97050c3071 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatMessageExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatMessageExtensionsTests.cs
@@ -9,23 +9,23 @@ namespace Microsoft.Agents.AI.Abstractions.UnitTests;
///
public sealed class ChatMessageExtensionsTests
{
- #region GetAgentRequestMessageSource Tests
+ #region GetAgentRequestMessageSourceType Tests
[Fact]
- public void GetAgentRequestMessageSource_WithNoAdditionalProperties_ReturnsExternal()
+ public void GetAgentRequestMessageSourceType_WithNoAdditionalProperties_ReturnsExternal()
{
// Arrange
ChatMessage message = new(ChatRole.User, "Hello");
// Act
- AgentRequestMessageSourceType result = message.GetAgentRequestMessageSource();
+ AgentRequestMessageSourceType result = message.GetAgentRequestMessageSourceType();
// Assert
Assert.Equal(AgentRequestMessageSourceType.External, result);
}
[Fact]
- public void GetAgentRequestMessageSource_WithNullAdditionalProperties_ReturnsExternal()
+ public void GetAgentRequestMessageSourceType_WithNullAdditionalProperties_ReturnsExternal()
{
// Arrange
ChatMessage message = new(ChatRole.User, "Hello")
@@ -34,14 +34,14 @@ public sealed class ChatMessageExtensionsTests
};
// Act
- AgentRequestMessageSourceType result = message.GetAgentRequestMessageSource();
+ AgentRequestMessageSourceType result = message.GetAgentRequestMessageSourceType();
// Assert
Assert.Equal(AgentRequestMessageSourceType.External, result);
}
[Fact]
- public void GetAgentRequestMessageSource_WithEmptyAdditionalProperties_ReturnsExternal()
+ public void GetAgentRequestMessageSourceType_WithEmptyAdditionalProperties_ReturnsExternal()
{
// Arrange
ChatMessage message = new(ChatRole.User, "Hello")
@@ -50,130 +50,130 @@ public sealed class ChatMessageExtensionsTests
};
// Act
- AgentRequestMessageSourceType result = message.GetAgentRequestMessageSource();
+ AgentRequestMessageSourceType result = message.GetAgentRequestMessageSourceType();
// Assert
Assert.Equal(AgentRequestMessageSourceType.External, result);
}
[Fact]
- public void GetAgentRequestMessageSource_WithExternalSource_ReturnsExternal()
+ public void GetAgentRequestMessageSourceType_WithExternalSourceType_ReturnsExternal()
{
// Arrange
ChatMessage message = new(ChatRole.User, "Hello")
{
AdditionalProperties = new AdditionalPropertiesDictionary
{
- { AgentRequestMessageSourceType.AdditionalPropertiesKey, AgentRequestMessageSourceType.External }
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.External, "TestSourceId") }
}
};
// Act
- AgentRequestMessageSourceType result = message.GetAgentRequestMessageSource();
+ AgentRequestMessageSourceType result = message.GetAgentRequestMessageSourceType();
// Assert
Assert.Equal(AgentRequestMessageSourceType.External, result);
}
[Fact]
- public void GetAgentRequestMessageSource_WithAIContextProviderSource_ReturnsAIContextProvider()
+ public void GetAgentRequestMessageSourceType_WithAIContextProviderSourceType_ReturnsAIContextProvider()
{
// Arrange
ChatMessage message = new(ChatRole.User, "Hello")
{
AdditionalProperties = new AdditionalPropertiesDictionary
{
- { AgentRequestMessageSourceType.AdditionalPropertiesKey, AgentRequestMessageSourceType.AIContextProvider }
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.AIContextProvider, "TestSourceId") }
}
};
// Act
- AgentRequestMessageSourceType result = message.GetAgentRequestMessageSource();
+ AgentRequestMessageSourceType result = message.GetAgentRequestMessageSourceType();
// Assert
Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, result);
}
[Fact]
- public void GetAgentRequestMessageSource_WithChatHistorySource_ReturnsChatHistory()
+ public void GetAgentRequestMessageSourceType_WithChatHistorySourceType_ReturnsChatHistory()
{
// Arrange
ChatMessage message = new(ChatRole.User, "Hello")
{
AdditionalProperties = new AdditionalPropertiesDictionary
{
- { AgentRequestMessageSourceType.AdditionalPropertiesKey, AgentRequestMessageSourceType.ChatHistory }
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.ChatHistory, "TestSourceId") }
}
};
// Act
- AgentRequestMessageSourceType result = message.GetAgentRequestMessageSource();
+ AgentRequestMessageSourceType result = message.GetAgentRequestMessageSourceType();
// Assert
Assert.Equal(AgentRequestMessageSourceType.ChatHistory, result);
}
[Fact]
- public void GetAgentRequestMessageSource_WithCustomSource_ReturnsCustomSource()
+ public void GetAgentRequestMessageSourceType_WithCustomSourceType_ReturnsCustomSourceType()
{
// Arrange
- AgentRequestMessageSourceType customSource = new("CustomSource");
+ AgentRequestMessageSourceType customSourceType = new("CustomSourceType");
ChatMessage message = new(ChatRole.User, "Hello")
{
AdditionalProperties = new AdditionalPropertiesDictionary
{
- { AgentRequestMessageSourceType.AdditionalPropertiesKey, customSource }
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(customSourceType, "TestSourceId") }
}
};
// Act
- AgentRequestMessageSourceType result = message.GetAgentRequestMessageSource();
+ AgentRequestMessageSourceType result = message.GetAgentRequestMessageSourceType();
// Assert
- Assert.Equal(customSource, result);
- Assert.Equal("CustomSource", result.Value);
+ Assert.Equal(customSourceType, result);
+ Assert.Equal("CustomSourceType", result.Value);
}
[Fact]
- public void GetAgentRequestMessageSource_WithWrongKeyType_ReturnsExternal()
+ public void GetAgentRequestMessageSourceType_WithWrongAttributionType_ReturnsExternal()
{
// Arrange
ChatMessage message = new(ChatRole.User, "Hello")
{
AdditionalProperties = new AdditionalPropertiesDictionary
{
- { AgentRequestMessageSourceType.AdditionalPropertiesKey, "NotAnAgentRequestMessageSource" }
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, "NotAnAgentRequestMessageSourceAttribution" }
}
};
// Act
- AgentRequestMessageSourceType result = message.GetAgentRequestMessageSource();
+ AgentRequestMessageSourceType result = message.GetAgentRequestMessageSourceType();
// Assert
Assert.Equal(AgentRequestMessageSourceType.External, result);
}
[Fact]
- public void GetAgentRequestMessageSource_WithNullValue_ReturnsExternal()
+ public void GetAgentRequestMessageSourceType_WithNullAttributionValue_ReturnsExternal()
{
// Arrange
ChatMessage message = new(ChatRole.User, "Hello")
{
AdditionalProperties = new AdditionalPropertiesDictionary
{
- { AgentRequestMessageSourceType.AdditionalPropertiesKey, null! }
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, null! }
}
};
// Act
- AgentRequestMessageSourceType result = message.GetAgentRequestMessageSource();
+ AgentRequestMessageSourceType result = message.GetAgentRequestMessageSourceType();
// Assert
Assert.Equal(AgentRequestMessageSourceType.External, result);
}
[Fact]
- public void GetAgentRequestMessageSource_WithMultipleProperties_ReturnsCorrectSource()
+ public void GetAgentRequestMessageSourceType_WithMultipleProperties_ReturnsCorrectSourceType()
{
// Arrange
ChatMessage message = new(ChatRole.User, "Hello")
@@ -181,17 +181,345 @@ public sealed class ChatMessageExtensionsTests
AdditionalProperties = new AdditionalPropertiesDictionary
{
{ "OtherProperty", "SomeValue" },
- { AgentRequestMessageSourceType.AdditionalPropertiesKey, AgentRequestMessageSourceType.ChatHistory },
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.ChatHistory, "TestSourceId") },
{ "AnotherProperty", 123 }
}
};
// Act
- AgentRequestMessageSourceType result = message.GetAgentRequestMessageSource();
+ AgentRequestMessageSourceType result = message.GetAgentRequestMessageSourceType();
// Assert
Assert.Equal(AgentRequestMessageSourceType.ChatHistory, result);
}
#endregion
+
+ #region GetAgentRequestMessageSourceId Tests
+
+ [Fact]
+ public void GetAgentRequestMessageSourceId_WithNoAdditionalProperties_ReturnsNull()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello");
+
+ // Act
+ string? result = message.GetAgentRequestMessageSourceId();
+
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void GetAgentRequestMessageSourceId_WithNullAdditionalProperties_ReturnsNull()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = null
+ };
+
+ // Act
+ string? result = message.GetAgentRequestMessageSourceId();
+
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void GetAgentRequestMessageSourceId_WithEmptyAdditionalProperties_ReturnsNull()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = new AdditionalPropertiesDictionary()
+ };
+
+ // Act
+ string? result = message.GetAgentRequestMessageSourceId();
+
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void GetAgentRequestMessageSourceId_WithAttribution_ReturnsSourceId()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.AIContextProvider, "MyProvider.FullName") }
+ }
+ };
+
+ // Act
+ string? result = message.GetAgentRequestMessageSourceId();
+
+ // Assert
+ Assert.Equal("MyProvider.FullName", result);
+ }
+
+ [Fact]
+ public void GetAgentRequestMessageSourceId_WithDifferentSourceIds_ReturnsCorrectSourceId()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.ChatHistory, "CustomHistorySourceId") }
+ }
+ };
+
+ // Act
+ string? result = message.GetAgentRequestMessageSourceId();
+
+ // Assert
+ Assert.Equal("CustomHistorySourceId", result);
+ }
+
+ [Fact]
+ public void GetAgentRequestMessageSourceId_WithWrongAttributionType_ReturnsNull()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, "NotAnAgentRequestMessageSourceAttribution" }
+ }
+ };
+
+ // Act
+ string? result = message.GetAgentRequestMessageSourceId();
+
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void GetAgentRequestMessageSourceId_WithNullAttributionValue_ReturnsNull()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, null! }
+ }
+ };
+
+ // Act
+ string? result = message.GetAgentRequestMessageSourceId();
+
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void GetAgentRequestMessageSourceId_WithMultipleProperties_ReturnsCorrectSourceId()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { "OtherProperty", "SomeValue" },
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.External, "ExpectedSourceId") },
+ { "AnotherProperty", 123 }
+ }
+ };
+
+ // Act
+ string? result = message.GetAgentRequestMessageSourceId();
+
+ // Assert
+ Assert.Equal("ExpectedSourceId", result);
+ }
+
+ #endregion
+
+ #region AsAgentRequestMessageSourcedMessage Tests
+
+ [Fact]
+ public void AsAgentRequestMessageSourcedMessage_WithNoAdditionalProperties_ReturnsClonesMessageWithAttribution()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello");
+
+ // Act
+ ChatMessage result = message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.External, "TestSourceId");
+
+ // Assert
+ Assert.NotSame(message, result);
+ Assert.Equal(AgentRequestMessageSourceType.External, result.GetAgentRequestMessageSourceType());
+ Assert.Equal("TestSourceId", result.GetAgentRequestMessageSourceId());
+ }
+
+ [Fact]
+ public void AsAgentRequestMessageSourcedMessage_WithNullAdditionalProperties_ReturnsClonesMessageWithAttribution()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = null
+ };
+
+ // Act
+ ChatMessage result = message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.AIContextProvider, "ProviderSourceId");
+
+ // Assert
+ Assert.NotSame(message, result);
+ Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, result.GetAgentRequestMessageSourceType());
+ Assert.Equal("ProviderSourceId", result.GetAgentRequestMessageSourceId());
+ }
+
+ [Fact]
+ public void AsAgentRequestMessageSourcedMessage_WithMatchingSourceTypeAndSourceId_ReturnsSameInstance()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.ChatHistory, "HistoryId") }
+ }
+ };
+
+ // Act
+ ChatMessage result = message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.ChatHistory, "HistoryId");
+
+ // Assert
+ Assert.Same(message, result);
+ }
+
+ [Fact]
+ public void AsAgentRequestMessageSourcedMessage_WithDifferentSourceType_ReturnsClonesMessageWithNewAttribution()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.External, "SourceId") }
+ }
+ };
+
+ // Act
+ ChatMessage result = message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.AIContextProvider, "SourceId");
+
+ // Assert
+ Assert.NotSame(message, result);
+ Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, result.GetAgentRequestMessageSourceType());
+ Assert.Equal("SourceId", result.GetAgentRequestMessageSourceId());
+ }
+
+ [Fact]
+ public void AsAgentRequestMessageSourcedMessage_WithDifferentSourceId_ReturnsClonesMessageWithNewAttribution()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.External, "OriginalId") }
+ }
+ };
+
+ // Act
+ ChatMessage result = message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.External, "NewId");
+
+ // Assert
+ Assert.NotSame(message, result);
+ Assert.Equal(AgentRequestMessageSourceType.External, result.GetAgentRequestMessageSourceType());
+ Assert.Equal("NewId", result.GetAgentRequestMessageSourceId());
+ }
+
+ [Fact]
+ public void AsAgentRequestMessageSourcedMessage_WithDefaultNullSourceId_ReturnsClonesMessageWithNullSourceId()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello");
+
+ // Act
+ ChatMessage result = message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.ChatHistory);
+
+ // Assert
+ Assert.NotSame(message, result);
+ Assert.Equal(AgentRequestMessageSourceType.ChatHistory, result.GetAgentRequestMessageSourceType());
+ Assert.Null(result.GetAgentRequestMessageSourceId());
+ }
+
+ [Fact]
+ public void AsAgentRequestMessageSourcedMessage_WithMatchingSourceTypeAndNullSourceId_ReturnsSameInstance()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.External, null) }
+ }
+ };
+
+ // Act
+ ChatMessage result = message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.External);
+
+ // Assert
+ Assert.Same(message, result);
+ }
+
+ [Fact]
+ public void AsAgentRequestMessageSourcedMessage_DoesNotModifyOriginalMessage()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello");
+
+ // Act
+ ChatMessage result = message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.AIContextProvider, "ProviderId");
+
+ // Assert
+ Assert.Null(message.AdditionalProperties);
+ Assert.NotNull(result.AdditionalProperties);
+ Assert.Equal(AgentRequestMessageSourceType.AIContextProvider, result.GetAgentRequestMessageSourceType());
+ }
+
+ [Fact]
+ public void AsAgentRequestMessageSourcedMessage_WithWrongAttributionType_ReturnsClonesMessageWithNewAttribution()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.User, "Hello")
+ {
+ AdditionalProperties = new AdditionalPropertiesDictionary
+ {
+ { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, "NotAnAttribution" }
+ }
+ };
+
+ // Act
+ ChatMessage result = message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.External, "SourceId");
+
+ // Assert
+ Assert.NotSame(message, result);
+ Assert.Equal(AgentRequestMessageSourceType.External, result.GetAgentRequestMessageSourceType());
+ Assert.Equal("SourceId", result.GetAgentRequestMessageSourceId());
+ }
+
+ [Fact]
+ public void AsAgentRequestMessageSourcedMessage_PreservesMessageContent()
+ {
+ // Arrange
+ ChatMessage message = new(ChatRole.Assistant, "Test content");
+
+ // Act
+ ChatMessage result = message.AsAgentRequestMessageSourcedMessage(AgentRequestMessageSourceType.ChatHistory, "HistoryId");
+
+ // Assert
+ Assert.Equal(ChatRole.Assistant, result.Role);
+ Assert.Equal("Test content", result.Text);
+ }
+
+ #endregion
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/InMemoryChatHistoryProviderTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/InMemoryChatHistoryProviderTests.cs
index 75232073a6..cecce5bea1 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/InMemoryChatHistoryProviderTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/InMemoryChatHistoryProviderTests.cs
@@ -55,7 +55,7 @@ public class InMemoryChatHistoryProviderTests
var requestMessages = new List
{
new(ChatRole.User, "Hello"),
- new(ChatRole.System, "additional context") { AdditionalProperties = new() { { AgentRequestMessageSourceType.AdditionalPropertiesKey, AgentRequestMessageSourceType.ChatHistory } } },
+ new(ChatRole.System, "additional context") { AdditionalProperties = new() { { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.ChatHistory, "TestSource") } } },
};
var responseMessages = new List
{
diff --git a/dotnet/tests/Microsoft.Agents.AI.CosmosNoSql.UnitTests/CosmosChatHistoryProviderTests.cs b/dotnet/tests/Microsoft.Agents.AI.CosmosNoSql.UnitTests/CosmosChatHistoryProviderTests.cs
index e1d3c612c8..e7276f70b1 100644
--- a/dotnet/tests/Microsoft.Agents.AI.CosmosNoSql.UnitTests/CosmosChatHistoryProviderTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.CosmosNoSql.UnitTests/CosmosChatHistoryProviderTests.cs
@@ -286,7 +286,7 @@ public sealed class CosmosChatHistoryProviderTests : IAsyncLifetime, IDisposable
new ChatMessage(ChatRole.User, "First message"),
new ChatMessage(ChatRole.Assistant, "Second message"),
new ChatMessage(ChatRole.User, "Third message"),
- new ChatMessage(ChatRole.System, "System context message") { AdditionalProperties = new() { { AgentRequestMessageSourceType.AdditionalPropertiesKey, AgentRequestMessageSourceType.AIContextProvider } } }
+ new ChatMessage(ChatRole.System, "System context message") { AdditionalProperties = new() { { AgentRequestMessageSourceAttribution.AdditionalPropertiesKey, new AgentRequestMessageSourceAttribution(AgentRequestMessageSourceType.AIContextProvider, "TestSource") } } }
};
var responseMessages = new[]
{