mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Merge branch 'main' into feat/durable_task
This commit is contained in:
@@ -86,11 +86,10 @@ jobs:
|
||||
run: docker pull mcr.microsoft.com/dotnet/sdk:${{ matrix.dotnet }}
|
||||
|
||||
# This step will run dotnet format on each of the unique csproj files and fail if any changes are made
|
||||
# exclude-diagnostics should be removed after fixes for IL2026 and IL3050 are out: https://github.com/dotnet/sdk/issues/51136
|
||||
- name: Run dotnet format
|
||||
if: steps.find-csproj.outputs.csproj_files != ''
|
||||
run: |
|
||||
for csproj in ${{ steps.find-csproj.outputs.csproj_files }}; do
|
||||
echo "Running dotnet format on $csproj"
|
||||
docker run --rm -v $(pwd):/app -w /app mcr.microsoft.com/dotnet/sdk:${{ matrix.dotnet }} /bin/sh -c "dotnet format $csproj --verify-no-changes --verbosity diagnostic --exclude-diagnostics IL2026 IL3050"
|
||||
docker run --rm -v $(pwd):/app -w /app mcr.microsoft.com/dotnet/sdk:${{ matrix.dotnet }} /bin/sh -c "dotnet format $csproj --verify-no-changes --verbosity diagnostic"
|
||||
done
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "10.0.100",
|
||||
"version": "10.0.200",
|
||||
"rollForward": "minor",
|
||||
"allowPrerelease": false
|
||||
},
|
||||
|
||||
@@ -127,6 +127,7 @@ public sealed class A2AAgent : AIAgent
|
||||
{
|
||||
AgentId = this.Id,
|
||||
ResponseId = message.MessageId,
|
||||
FinishReason = ChatFinishReason.Stop,
|
||||
RawRepresentation = message,
|
||||
Messages = [message.ToChatMessage()],
|
||||
AdditionalProperties = message.Metadata?.ToAdditionalProperties(),
|
||||
@@ -141,6 +142,7 @@ public sealed class A2AAgent : AIAgent
|
||||
{
|
||||
AgentId = this.Id,
|
||||
ResponseId = agentTask.Id,
|
||||
FinishReason = MapTaskStateToFinishReason(agentTask.Status.State),
|
||||
RawRepresentation = agentTask,
|
||||
Messages = agentTask.ToChatMessages() ?? [],
|
||||
ContinuationToken = CreateContinuationToken(agentTask.Id, agentTask.Status.State),
|
||||
@@ -328,6 +330,7 @@ public sealed class A2AAgent : AIAgent
|
||||
{
|
||||
AgentId = this.Id,
|
||||
ResponseId = message.MessageId,
|
||||
FinishReason = ChatFinishReason.Stop,
|
||||
RawRepresentation = message,
|
||||
Role = ChatRole.Assistant,
|
||||
MessageId = message.MessageId,
|
||||
@@ -342,6 +345,7 @@ public sealed class A2AAgent : AIAgent
|
||||
{
|
||||
AgentId = this.Id,
|
||||
ResponseId = task.Id,
|
||||
FinishReason = MapTaskStateToFinishReason(task.Status.State),
|
||||
RawRepresentation = task,
|
||||
Role = ChatRole.Assistant,
|
||||
Contents = task.ToAIContents(),
|
||||
@@ -365,7 +369,16 @@ public sealed class A2AAgent : AIAgent
|
||||
responseUpdate.Contents = artifactUpdateEvent.Artifact.ToAIContents();
|
||||
responseUpdate.RawRepresentation = artifactUpdateEvent;
|
||||
}
|
||||
else if (taskUpdateEvent is TaskStatusUpdateEvent statusUpdateEvent)
|
||||
{
|
||||
responseUpdate.FinishReason = MapTaskStateToFinishReason(statusUpdateEvent.Status.State);
|
||||
}
|
||||
|
||||
return responseUpdate;
|
||||
}
|
||||
|
||||
private static ChatFinishReason? MapTaskStateToFinishReason(TaskState state)
|
||||
{
|
||||
return state == TaskState.Completed ? ChatFinishReason.Stop : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ public class AgentResponse
|
||||
|
||||
this.AdditionalProperties = response.AdditionalProperties;
|
||||
this.CreatedAt = response.CreatedAt;
|
||||
this.FinishReason = response.FinishReason;
|
||||
this.Messages = response.Messages;
|
||||
this.RawRepresentation = response;
|
||||
this.ResponseId = response.ResponseId;
|
||||
@@ -84,6 +85,7 @@ public class AgentResponse
|
||||
|
||||
this.AdditionalProperties = response.AdditionalProperties;
|
||||
this.CreatedAt = response.CreatedAt;
|
||||
this.FinishReason = response.FinishReason;
|
||||
this.Messages = response.Messages;
|
||||
this.RawRepresentation = response;
|
||||
this.ResponseId = response.ResponseId;
|
||||
@@ -190,6 +192,21 @@ public class AgentResponse
|
||||
/// </remarks>
|
||||
public DateTimeOffset? CreatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the reason for the agent response finishing.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ChatFinishReason"/> value indicating why the response finished (e.g., stop, length, content filter, tool calls),
|
||||
/// or <see langword="null"/> if the finish reason is not available.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This property is particularly useful for detecting non-normal completions, such as content filtering
|
||||
/// or token limit truncation, which may require special handling by the caller.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public ChatFinishReason? FinishReason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the resource usage information for generating this response.
|
||||
/// </summary>
|
||||
@@ -276,6 +293,7 @@ public class AgentResponse
|
||||
RawRepresentation = message.RawRepresentation,
|
||||
Role = message.Role,
|
||||
|
||||
FinishReason = this.FinishReason,
|
||||
AgentId = this.AgentId,
|
||||
ResponseId = this.ResponseId,
|
||||
MessageId = message.MessageId,
|
||||
|
||||
@@ -38,6 +38,7 @@ public static class AgentResponseExtensions
|
||||
{
|
||||
AdditionalProperties = response.AdditionalProperties,
|
||||
CreatedAt = response.CreatedAt,
|
||||
FinishReason = response.FinishReason,
|
||||
Messages = response.Messages,
|
||||
RawRepresentation = response,
|
||||
ResponseId = response.ResponseId,
|
||||
@@ -71,6 +72,7 @@ public static class AgentResponseExtensions
|
||||
AuthorName = responseUpdate.AuthorName,
|
||||
Contents = responseUpdate.Contents,
|
||||
CreatedAt = responseUpdate.CreatedAt,
|
||||
FinishReason = responseUpdate.FinishReason,
|
||||
MessageId = responseUpdate.MessageId,
|
||||
RawRepresentation = responseUpdate,
|
||||
ResponseId = responseUpdate.ResponseId,
|
||||
|
||||
@@ -70,6 +70,7 @@ public class AgentResponseUpdate
|
||||
this.AuthorName = chatResponseUpdate.AuthorName;
|
||||
this.Contents = chatResponseUpdate.Contents;
|
||||
this.CreatedAt = chatResponseUpdate.CreatedAt;
|
||||
this.FinishReason = chatResponseUpdate.FinishReason;
|
||||
this.MessageId = chatResponseUpdate.MessageId;
|
||||
this.RawRepresentation = chatResponseUpdate;
|
||||
this.ResponseId = chatResponseUpdate.ResponseId;
|
||||
@@ -153,6 +154,15 @@ public class AgentResponseUpdate
|
||||
/// </remarks>
|
||||
public ResponseContinuationToken? ContinuationToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the reason for the agent response finishing.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ChatFinishReason"/> value indicating why the response finished (e.g., stop, length, content filter, tool calls),
|
||||
/// or <see langword="null"/> if the finish reason is not available or not yet determined (mid-stream).
|
||||
/// </value>
|
||||
public ChatFinishReason? FinishReason { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => this.Text;
|
||||
|
||||
|
||||
+1
-3
@@ -72,9 +72,7 @@ internal static class AIAgentChatCompletionsProcessor
|
||||
|
||||
await foreach (var agentResponseUpdate in agent.RunStreamingAsync(chatMessages, options: options, cancellationToken: cancellationToken).WithCancellation(cancellationToken))
|
||||
{
|
||||
var finishReason = (agentResponseUpdate.RawRepresentation is ChatResponseUpdate { FinishReason: not null } chatResponseUpdate)
|
||||
? chatResponseUpdate.FinishReason.ToString()
|
||||
: "stop";
|
||||
var finishReason = agentResponseUpdate.FinishReason?.ToString() ?? "stop";
|
||||
|
||||
var choiceChunks = new List<ChatCompletionChoiceChunk>();
|
||||
CompletionUsage? usageDetails = null;
|
||||
|
||||
+1
-3
@@ -34,9 +34,7 @@ internal static class AgentResponseExtensions
|
||||
var chatCompletionChoices = new List<ChatCompletionChoice>();
|
||||
var index = 0;
|
||||
|
||||
var finishReason = (agentResponse.RawRepresentation is ChatResponse { FinishReason: not null } chatResponse)
|
||||
? chatResponse.FinishReason.ToString()
|
||||
: "stop"; // "stop" is a natural stop point; returning this by-default
|
||||
var finishReason = agentResponse.FinishReason?.ToString() ?? ChatFinishReason.Stop.Value; // "stop" is a natural stop point; returning this by-default
|
||||
|
||||
foreach (var message in agentResponse.Messages)
|
||||
{
|
||||
|
||||
@@ -124,6 +124,7 @@ internal sealed class MessageMerger
|
||||
List<ChatMessage> messages = [];
|
||||
Dictionary<string, AgentResponse> responses = [];
|
||||
HashSet<string> agentIds = [];
|
||||
HashSet<ChatFinishReason> finishReasons = [];
|
||||
|
||||
foreach (string responseId in this._mergeStates.Keys)
|
||||
{
|
||||
@@ -156,6 +157,11 @@ internal sealed class MessageMerger
|
||||
createdTimes.Add(response.CreatedAt.Value);
|
||||
}
|
||||
|
||||
if (response.FinishReason.HasValue)
|
||||
{
|
||||
finishReasons.Add(response.FinishReason.Value);
|
||||
}
|
||||
|
||||
usage = MergeUsage(usage, response.Usage);
|
||||
additionalProperties = MergeProperties(additionalProperties, response.AdditionalProperties);
|
||||
}
|
||||
@@ -182,6 +188,7 @@ internal sealed class MessageMerger
|
||||
AgentId = primaryAgentId
|
||||
?? primaryAgentName
|
||||
?? (agentIds.Count == 1 ? agentIds.First() : null),
|
||||
FinishReason = finishReasons.Count == 1 ? finishReasons.First() : null,
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
Usage = usage,
|
||||
AdditionalProperties = additionalProperties
|
||||
@@ -207,6 +214,7 @@ internal sealed class MessageMerger
|
||||
AgentId = incoming.AgentId ?? current.AgentId,
|
||||
AdditionalProperties = MergeProperties(current.AdditionalProperties, incoming.AdditionalProperties),
|
||||
CreatedAt = incoming.CreatedAt ?? current.CreatedAt,
|
||||
FinishReason = incoming.FinishReason ?? current.FinishReason,
|
||||
Messages = current.Messages.Concat(incoming.Messages).ToList(),
|
||||
ResponseId = current.ResponseId,
|
||||
RawRepresentation = rawRepresentation,
|
||||
|
||||
@@ -126,6 +126,7 @@ public sealed class A2AAgentTests : IDisposable
|
||||
Assert.Single(result.Messages);
|
||||
Assert.Equal(ChatRole.Assistant, result.Messages[0].Role);
|
||||
Assert.Equal("Hello! How can I help you today?", result.Messages[0].Text);
|
||||
Assert.Equal(ChatFinishReason.Stop, result.FinishReason);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -249,8 +250,7 @@ public sealed class A2AAgentTests : IDisposable
|
||||
Assert.Equal("stream-1", updates[0].MessageId);
|
||||
Assert.Equal(this._agent.Id, updates[0].AgentId);
|
||||
Assert.Equal("stream-1", updates[0].ResponseId);
|
||||
|
||||
Assert.NotNull(updates[0].RawRepresentation);
|
||||
Assert.Equal(ChatFinishReason.Stop, updates[0].FinishReason);
|
||||
Assert.IsType<AgentMessage>(updates[0].RawRepresentation);
|
||||
Assert.Equal("stream-1", ((AgentMessage)updates[0].RawRepresentation!).MessageId);
|
||||
}
|
||||
@@ -501,8 +501,7 @@ public sealed class A2AAgentTests : IDisposable
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(this._agent.Id, result.AgentId);
|
||||
Assert.Equal("task-789", result.ResponseId);
|
||||
|
||||
Assert.NotNull(result.RawRepresentation);
|
||||
Assert.Null(result.FinishReason);
|
||||
Assert.IsType<AgentTask>(result.RawRepresentation);
|
||||
Assert.Equal("task-789", ((AgentTask)result.RawRepresentation).Id);
|
||||
|
||||
@@ -552,6 +551,15 @@ public sealed class A2AAgentTests : IDisposable
|
||||
{
|
||||
Assert.Null(result.ContinuationToken);
|
||||
}
|
||||
|
||||
if (taskState is TaskState.Completed)
|
||||
{
|
||||
Assert.Equal(ChatFinishReason.Stop, result.FinishReason);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Null(result.FinishReason);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -661,6 +669,7 @@ public sealed class A2AAgentTests : IDisposable
|
||||
Assert.Equal(MessageId, update0.ResponseId);
|
||||
Assert.Equal(this._agent.Id, update0.AgentId);
|
||||
Assert.Equal(MessageText, update0.Text);
|
||||
Assert.Equal(ChatFinishReason.Stop, update0.FinishReason);
|
||||
Assert.IsType<AgentMessage>(update0.RawRepresentation);
|
||||
Assert.Equal(MessageId, ((AgentMessage)update0.RawRepresentation!).MessageId);
|
||||
}
|
||||
@@ -702,6 +711,7 @@ public sealed class A2AAgentTests : IDisposable
|
||||
Assert.Equal(ChatRole.Assistant, update0.Role);
|
||||
Assert.Equal(TaskId, update0.ResponseId);
|
||||
Assert.Equal(this._agent.Id, update0.AgentId);
|
||||
Assert.Null(update0.FinishReason);
|
||||
Assert.IsType<AgentTask>(update0.RawRepresentation);
|
||||
Assert.Equal(TaskId, ((AgentTask)update0.RawRepresentation!).Id);
|
||||
|
||||
@@ -741,6 +751,7 @@ public sealed class A2AAgentTests : IDisposable
|
||||
Assert.Equal(ChatRole.Assistant, update0.Role);
|
||||
Assert.Equal(TaskId, update0.ResponseId);
|
||||
Assert.Equal(this._agent.Id, update0.AgentId);
|
||||
Assert.Null(update0.FinishReason);
|
||||
Assert.IsType<TaskStatusUpdateEvent>(update0.RawRepresentation);
|
||||
|
||||
// Assert - session should be updated with context and task IDs
|
||||
@@ -784,6 +795,7 @@ public sealed class A2AAgentTests : IDisposable
|
||||
Assert.Equal(ChatRole.Assistant, update0.Role);
|
||||
Assert.Equal(TaskId, update0.ResponseId);
|
||||
Assert.Equal(this._agent.Id, update0.AgentId);
|
||||
Assert.Null(update0.FinishReason);
|
||||
Assert.IsType<TaskArtifactUpdateEvent>(update0.RawRepresentation);
|
||||
|
||||
// Assert - artifact content should be in the update
|
||||
|
||||
@@ -53,6 +53,7 @@ public class AgentResponseTests
|
||||
{
|
||||
AdditionalProperties = [],
|
||||
CreatedAt = new DateTimeOffset(2022, 1, 1, 0, 0, 0, TimeSpan.Zero),
|
||||
FinishReason = ChatFinishReason.ContentFilter,
|
||||
Messages = [new(ChatRole.Assistant, "This is a test message.")],
|
||||
RawRepresentation = new object(),
|
||||
ResponseId = "responseId",
|
||||
@@ -63,6 +64,7 @@ public class AgentResponseTests
|
||||
AgentResponse response = new(chatResponse);
|
||||
Assert.Same(chatResponse.AdditionalProperties, response.AdditionalProperties);
|
||||
Assert.Equal(chatResponse.CreatedAt, response.CreatedAt);
|
||||
Assert.Equal(chatResponse.FinishReason, response.FinishReason);
|
||||
Assert.Same(chatResponse.Messages, response.Messages);
|
||||
Assert.Equal(chatResponse.ResponseId, response.ResponseId);
|
||||
Assert.Same(chatResponse, response.RawRepresentation as ChatResponse);
|
||||
@@ -105,6 +107,10 @@ public class AgentResponseTests
|
||||
Assert.Null(response.ContinuationToken);
|
||||
response.ContinuationToken = ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 });
|
||||
Assert.Equivalent(ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }), response.ContinuationToken);
|
||||
|
||||
Assert.Null(response.FinishReason);
|
||||
response.FinishReason = ChatFinishReason.Length;
|
||||
Assert.Equal(ChatFinishReason.Length, response.FinishReason);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -188,6 +194,7 @@ public class AgentResponseTests
|
||||
ResponseId = "12345",
|
||||
CreatedAt = new DateTimeOffset(2024, 11, 10, 9, 20, 0, TimeSpan.Zero),
|
||||
AdditionalProperties = new() { ["key1"] = "value1", ["key2"] = 42 },
|
||||
FinishReason = ChatFinishReason.ContentFilter,
|
||||
Usage = new UsageDetails
|
||||
{
|
||||
TotalTokenCount = 100
|
||||
@@ -205,6 +212,7 @@ public class AgentResponseTests
|
||||
Assert.Equal(new DateTimeOffset(2024, 11, 10, 9, 20, 0, TimeSpan.Zero), update0.CreatedAt);
|
||||
Assert.Equal("customRole", update0.Role?.Value);
|
||||
Assert.Equal("Text", update0.Text);
|
||||
Assert.Equal(ChatFinishReason.ContentFilter, update0.FinishReason);
|
||||
|
||||
AgentResponseUpdate update1 = updates[1];
|
||||
Assert.Equal("value1", update1.AdditionalProperties?["key1"]);
|
||||
|
||||
+4
@@ -334,6 +334,7 @@ public class AgentResponseUpdateExtensionsTests
|
||||
{
|
||||
ResponseId = "test-response-id",
|
||||
CreatedAt = new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero),
|
||||
FinishReason = ChatFinishReason.ContentFilter,
|
||||
Usage = new UsageDetails { TotalTokenCount = 50 },
|
||||
AdditionalProperties = new() { ["key"] = "value" },
|
||||
ContinuationToken = ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }),
|
||||
@@ -346,6 +347,7 @@ public class AgentResponseUpdateExtensionsTests
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal("test-response-id", result.ResponseId);
|
||||
Assert.Equal(new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero), result.CreatedAt);
|
||||
Assert.Equal(ChatFinishReason.ContentFilter, result.FinishReason);
|
||||
Assert.Same(agentResponse.Messages, result.Messages);
|
||||
Assert.Same(agentResponse, result.RawRepresentation);
|
||||
Assert.Same(agentResponse.Usage, result.Usage);
|
||||
@@ -392,6 +394,7 @@ public class AgentResponseUpdateExtensionsTests
|
||||
ResponseId = "update-id",
|
||||
MessageId = "message-id",
|
||||
CreatedAt = new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero),
|
||||
FinishReason = ChatFinishReason.ToolCalls,
|
||||
AdditionalProperties = new() { ["key"] = "value" },
|
||||
ContinuationToken = ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }),
|
||||
};
|
||||
@@ -405,6 +408,7 @@ public class AgentResponseUpdateExtensionsTests
|
||||
Assert.Equal("update-id", result.ResponseId);
|
||||
Assert.Equal("message-id", result.MessageId);
|
||||
Assert.Equal(new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero), result.CreatedAt);
|
||||
Assert.Equal(ChatFinishReason.ToolCalls, result.FinishReason);
|
||||
Assert.Equal(ChatRole.Assistant, result.Role);
|
||||
Assert.Same(agentResponseUpdate.Contents, result.Contents);
|
||||
Assert.Same(agentResponseUpdate, result.RawRepresentation);
|
||||
|
||||
@@ -24,6 +24,7 @@ public class AgentResponseUpdateTests
|
||||
Assert.Null(update.CreatedAt);
|
||||
Assert.Equal(string.Empty, update.ToString());
|
||||
Assert.Null(update.ContinuationToken);
|
||||
Assert.Null(update.FinishReason);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -50,6 +51,7 @@ public class AgentResponseUpdateTests
|
||||
Assert.Equal(chatResponseUpdate.AuthorName, response.AuthorName);
|
||||
Assert.Same(chatResponseUpdate.Contents, response.Contents);
|
||||
Assert.Equal(chatResponseUpdate.CreatedAt, response.CreatedAt);
|
||||
Assert.Equal(chatResponseUpdate.FinishReason, response.FinishReason);
|
||||
Assert.Equal(chatResponseUpdate.MessageId, response.MessageId);
|
||||
Assert.Same(chatResponseUpdate, response.RawRepresentation as ChatResponseUpdate);
|
||||
Assert.Equal(chatResponseUpdate.ResponseId, response.ResponseId);
|
||||
@@ -109,6 +111,10 @@ public class AgentResponseUpdateTests
|
||||
Assert.Null(update.ContinuationToken);
|
||||
update.ContinuationToken = ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 });
|
||||
Assert.Equivalent(ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }), update.ContinuationToken);
|
||||
|
||||
Assert.Null(update.FinishReason);
|
||||
update.FinishReason = ChatFinishReason.ToolCalls;
|
||||
Assert.Equal(ChatFinishReason.ToolCalls, update.FinishReason);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -37,5 +37,36 @@ public class MessageMergerTests
|
||||
response.CreatedAt.Should().NotBe(creationTime);
|
||||
response.Messages[0].CreatedAt.Should().Be(creationTime);
|
||||
response.Messages[0].Contents.Should().HaveCount(1);
|
||||
response.FinishReason.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test_MessageMerger_PropagatesFinishReasonFromUpdates()
|
||||
{
|
||||
// Arrange
|
||||
string responseId = Guid.NewGuid().ToString("N");
|
||||
string messageId = Guid.NewGuid().ToString("N");
|
||||
|
||||
MessageMerger merger = new();
|
||||
|
||||
foreach (AgentResponseUpdate update in "Hello".ToAgentRunStream(agentId: TestAgentId1, messageId: messageId, responseId: responseId))
|
||||
{
|
||||
merger.AddUpdate(update);
|
||||
}
|
||||
|
||||
// Add a final update with FinishReason set
|
||||
merger.AddUpdate(new AgentResponseUpdate
|
||||
{
|
||||
ResponseId = responseId,
|
||||
MessageId = messageId,
|
||||
FinishReason = ChatFinishReason.ContentFilter,
|
||||
Role = ChatRole.Assistant,
|
||||
});
|
||||
|
||||
// Act
|
||||
AgentResponse response = merger.ComputeMerged(responseId);
|
||||
|
||||
// Assert - FinishReason from the update should propagate through
|
||||
response.FinishReason.Should().Be(ChatFinishReason.ContentFilter);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user