mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
254 lines
8.6 KiB
C#
254 lines
8.6 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System;
|
|
using Microsoft.Extensions.AI;
|
|
using Microsoft.Extensions.AI.Agents;
|
|
using Moq;
|
|
|
|
namespace Microsoft.Agents.Orchestration.UnitTest;
|
|
|
|
public class HandoffsTests
|
|
{
|
|
[Fact]
|
|
public void EmptyConstructorsCreateEmptyCollections()
|
|
{
|
|
AgentHandoffs agentHandoffs = [];
|
|
Assert.Empty(agentHandoffs);
|
|
|
|
OrchestrationHandoffs orchestrationHandoffs = new("first");
|
|
Assert.Empty(orchestrationHandoffs);
|
|
Assert.Equal("first", orchestrationHandoffs.FirstAgentName);
|
|
}
|
|
|
|
[Fact]
|
|
public void DictionaryConstructorsInvalidFirstAgent()
|
|
{
|
|
Assert.Throws<ArgumentNullException>(() => new OrchestrationHandoffs((string)null!));
|
|
Assert.Throws<ArgumentException>(() => new OrchestrationHandoffs(string.Empty));
|
|
Assert.Throws<ArgumentException>(() => new OrchestrationHandoffs(" "));
|
|
}
|
|
|
|
[Fact]
|
|
public void AddWithAgentObjectsCreatesHandoffRelationships()
|
|
{
|
|
// Arrange
|
|
OrchestrationHandoffs handoffs = new("source");
|
|
|
|
AIAgent sourceAgent = CreateAgent("source", "Source Agent");
|
|
AIAgent targetAgent1 = CreateAgent("target1", "Target Agent 1");
|
|
AIAgent targetAgent2 = CreateAgent("target2", "Target Agent 2");
|
|
|
|
// Act
|
|
handoffs.Add(sourceAgent, targetAgent1, targetAgent2);
|
|
|
|
// Assert
|
|
Assert.Single(handoffs);
|
|
Assert.Equal("source", handoffs.FirstAgentName);
|
|
Assert.True(handoffs.ContainsKey("source"));
|
|
|
|
AgentHandoffs sourceHandoffs = handoffs["source"];
|
|
Assert.Equal(2, sourceHandoffs.Count);
|
|
Assert.Equal("Target Agent 1", sourceHandoffs["target1"]);
|
|
Assert.Equal("Target Agent 2", sourceHandoffs["target2"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void AddWithAgentAndCustomDescriptionUsesCustomDescription()
|
|
{
|
|
// Arrange
|
|
OrchestrationHandoffs handoffs = new("source");
|
|
|
|
AIAgent sourceAgent = CreateAgent("source", "Source Agent");
|
|
AIAgent targetAgent = CreateAgent("target", "Target Agent");
|
|
string customDescription = "Custom handoff description";
|
|
|
|
// Act
|
|
handoffs.Add(sourceAgent, targetAgent, customDescription);
|
|
|
|
// Assert
|
|
Assert.Single(handoffs);
|
|
Assert.Equal("source", handoffs.FirstAgentName);
|
|
AgentHandoffs sourceHandoffs = handoffs["source"];
|
|
Assert.Single(sourceHandoffs);
|
|
Assert.Equal(customDescription, sourceHandoffs["target"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void AddWithAgentAndTargetNameAddsHandoffWithDescription()
|
|
{
|
|
// Arrange
|
|
OrchestrationHandoffs handoffs = new("source");
|
|
|
|
AIAgent sourceAgent = CreateAgent("source", "Source Agent");
|
|
string targetName = "targetName";
|
|
string description = "Target description";
|
|
|
|
// Act
|
|
handoffs.Add(sourceAgent, targetName, description);
|
|
|
|
// Assert
|
|
Assert.Single(handoffs);
|
|
Assert.Equal("source", handoffs.FirstAgentName);
|
|
AgentHandoffs sourceHandoffs = handoffs["source"];
|
|
Assert.Single(sourceHandoffs);
|
|
Assert.Equal(description, sourceHandoffs[targetName]);
|
|
}
|
|
|
|
[Fact]
|
|
public void AddWithSourceNameAndTargetNameAddsHandoffWithDescription()
|
|
{
|
|
// Arrange
|
|
OrchestrationHandoffs handoffs = new("sourceName");
|
|
|
|
string sourceName = "sourceName";
|
|
string targetName = "targetName";
|
|
string description = "Target description";
|
|
|
|
// Act
|
|
handoffs.Add(sourceName, targetName, description);
|
|
|
|
// Assert
|
|
Assert.Single(handoffs);
|
|
Assert.Equal("sourceName", handoffs.FirstAgentName);
|
|
AgentHandoffs sourceHandoffs = handoffs[sourceName];
|
|
Assert.Single(sourceHandoffs);
|
|
Assert.Equal(description, sourceHandoffs[targetName]);
|
|
}
|
|
|
|
[Fact]
|
|
public void AddWithMultipleSourcesAndTargetsCreatesCorrectStructure()
|
|
{
|
|
// Arrange
|
|
OrchestrationHandoffs handoffs = new("source1");
|
|
|
|
AIAgent source1 = CreateAgent("source1", "Source Agent 1");
|
|
AIAgent source2 = CreateAgent("source2", "Source Agent 2");
|
|
|
|
AIAgent target1 = CreateAgent("target1", "Target Agent 1");
|
|
AIAgent target2 = CreateAgent("target2", "Target Agent 2");
|
|
AIAgent target3 = CreateAgent("target3", "Target Agent 3");
|
|
|
|
// Act
|
|
handoffs.Add(source1, target1, target2);
|
|
handoffs.Add(source2, target2, target3);
|
|
handoffs.Add(source1, target3, "Custom description");
|
|
|
|
// Assert
|
|
Assert.Equal(2, handoffs.Count);
|
|
Assert.Equal("source1", handoffs.FirstAgentName);
|
|
|
|
// Check source1's targets
|
|
AgentHandoffs source1Handoffs = handoffs["source1"];
|
|
Assert.Equal(3, source1Handoffs.Count);
|
|
Assert.Equal("Target Agent 1", source1Handoffs["target1"]);
|
|
Assert.Equal("Target Agent 2", source1Handoffs["target2"]);
|
|
Assert.Equal("Custom description", source1Handoffs["target3"]);
|
|
|
|
// Check source2's targets
|
|
AgentHandoffs source2Handoffs = handoffs["source2"];
|
|
Assert.Equal(2, source2Handoffs.Count);
|
|
Assert.Equal("Target Agent 2", source2Handoffs["target2"]);
|
|
Assert.Equal("Target Agent 3", source2Handoffs["target3"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void StaticAddCreatesNewOrchestrationHandoffs()
|
|
{
|
|
// Arrange
|
|
AIAgent source = CreateAgent("source", "Source Agent");
|
|
AIAgent target1 = CreateAgent("target1", "Target Agent 1");
|
|
AIAgent target2 = CreateAgent("target2", "Target Agent 2");
|
|
|
|
// Act
|
|
OrchestrationHandoffs handoffs =
|
|
OrchestrationHandoffs
|
|
.StartWith(source)
|
|
.Add(source, target1, target2);
|
|
|
|
// Assert
|
|
Assert.NotNull(handoffs);
|
|
Assert.Equal(source.Id, handoffs.FirstAgentName);
|
|
Assert.Single(handoffs);
|
|
Assert.True(handoffs.ContainsKey("source"));
|
|
|
|
AgentHandoffs sourceHandoffs = handoffs["source"];
|
|
Assert.Equal(2, sourceHandoffs.Count);
|
|
Assert.Equal("Target Agent 1", sourceHandoffs["target1"]);
|
|
Assert.Equal("Target Agent 2", sourceHandoffs["target2"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void AddWithAgentsWithNoNameUsesId()
|
|
{
|
|
// Arrange
|
|
OrchestrationHandoffs handoffs = new("source-id");
|
|
|
|
AIAgent sourceAgent = CreateAgent(id: "source-id", name: null);
|
|
AIAgent targetAgent = CreateAgent(id: "target-id", name: null, description: "Target Description");
|
|
|
|
// Act
|
|
handoffs.Add(sourceAgent, targetAgent);
|
|
|
|
// Assert
|
|
Assert.Single(handoffs);
|
|
Assert.Equal("source-id", handoffs.FirstAgentName);
|
|
Assert.True(handoffs.ContainsKey("source-id"));
|
|
|
|
AgentHandoffs sourceHandoffs = handoffs["source-id"];
|
|
Assert.Single(sourceHandoffs);
|
|
Assert.Equal("Target Description", sourceHandoffs["target-id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void AddWithAgentWithNoDescriptionUsesName()
|
|
{
|
|
// Arrange
|
|
OrchestrationHandoffs handoffs = new("source");
|
|
|
|
AIAgent sourceAgent = CreateAgent("source", "Source Agent");
|
|
AIAgent targetAgent1 = CreateAgent("target1", name: "target 1");
|
|
|
|
// Act
|
|
handoffs.Add(sourceAgent, targetAgent1);
|
|
|
|
// Assert
|
|
Assert.Single(handoffs);
|
|
Assert.Equal("source", handoffs.FirstAgentName);
|
|
Assert.True(handoffs.ContainsKey("source"));
|
|
|
|
AgentHandoffs sourceHandoffs = handoffs["source"];
|
|
Assert.Single(sourceHandoffs);
|
|
Assert.Equal("target 1", sourceHandoffs["target 1"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void AddWithAgentWithNoDescriptionOrNameThrows()
|
|
{
|
|
// Arrange
|
|
OrchestrationHandoffs handoffs = new("source");
|
|
|
|
AIAgent sourceAgent = CreateAgent("source", "Source Agent");
|
|
AIAgent targetAgent1 = CreateAgent("target1");
|
|
|
|
// Act
|
|
InvalidOperationException ex = Assert.Throws<InvalidOperationException>(() => handoffs.Add(sourceAgent, targetAgent1));
|
|
|
|
// Assert
|
|
Assert.Equal("The provided target agent with Id 'target1' has no description or name, and no handoff description has been provided. At least one of these are required to register a handoff so that the appropriate target agent can be chosen.", ex.Message);
|
|
}
|
|
|
|
private static ChatClientAgent CreateAgent(string id, string? description = null, string? name = null)
|
|
{
|
|
Mock<IChatClient> mockClient = new(MockBehavior.Loose);
|
|
ChatClientAgentOptions options =
|
|
new()
|
|
{
|
|
Id = id,
|
|
Name = name,
|
|
Description = description,
|
|
};
|
|
ChatClientAgent mockAgent = new(mockClient.Object, options);
|
|
return mockAgent;
|
|
}
|
|
}
|