mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
fix: Address PR Comments
This commit is contained in:
@@ -99,9 +99,11 @@ public class MagenticWorkflowBuilder(AIAgent managerAgent)
|
||||
|
||||
private WorkflowBuilder ReduceToWorkflowBuilder()
|
||||
{
|
||||
ExecutorFactoryFunc factory = this.CreateOrchestratorAsync;
|
||||
ExecutorBinding orchestrator = factory.BindExecutor(nameof(MagenticOrchestrator));
|
||||
// Create a copy of the team so that improper modifications by using the builder after .Build() do not affect the
|
||||
// workflow in unexpected ways.
|
||||
List<AIAgent> team = [.. this._team];
|
||||
|
||||
ExecutorBinding orchestrator = CreateOrchestratorBinding(managerAgent, team, this.Limits, this._requirePlanSignoff);
|
||||
WorkflowBuilder result = new(orchestrator);
|
||||
|
||||
AIAgentHostOptions options = new()
|
||||
@@ -111,7 +113,7 @@ public class MagenticWorkflowBuilder(AIAgent managerAgent)
|
||||
};
|
||||
|
||||
List<ExecutorBinding> teamBindings = [];
|
||||
foreach (AIAgent agent in this._team)
|
||||
foreach (AIAgent agent in team)
|
||||
{
|
||||
ExecutorBinding binding = agent.BindAsExecutor(options);
|
||||
teamBindings.Add(binding);
|
||||
@@ -143,8 +145,14 @@ public class MagenticWorkflowBuilder(AIAgent managerAgent)
|
||||
MaxResetCount: this._maxResets,
|
||||
MaxStallCount: this._maxStalls);
|
||||
|
||||
private ValueTask<MagenticOrchestrator> CreateOrchestratorAsync(ExecutorConfig<ExecutorOptions> options, string sessionId)
|
||||
private static ExecutorBinding CreateOrchestratorBinding(AIAgent managerAgent, List<AIAgent> team, TaskLimits limits, bool requirePlanSignoff)
|
||||
{
|
||||
return new(new MagenticOrchestrator(managerAgent, this._team, this.Limits, this._requirePlanSignoff));
|
||||
ExecutorFactoryFunc factory = CreateOrchestratorAsync;
|
||||
return factory.BindExecutor(nameof(MagenticOrchestrator));
|
||||
|
||||
ValueTask<MagenticOrchestrator> CreateOrchestratorAsync(ExecutorConfig<ExecutorOptions> options, string sessionId)
|
||||
{
|
||||
return new(new MagenticOrchestrator(managerAgent, team, limits, requirePlanSignoff));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-4
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
@@ -112,9 +113,8 @@ internal static partial class ChatMessageExtensions
|
||||
new(FencedJsonRegexPattern, RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
|
||||
#endif
|
||||
|
||||
public static JsonElement ExtractJson(this ChatMessage message)
|
||||
internal static JsonElement ExtractJson(string messageText)
|
||||
{
|
||||
string messageText = message.Text;
|
||||
Match match = FencedJsonRegex().Match(messageText);
|
||||
if (match.Success)
|
||||
{
|
||||
@@ -130,20 +130,35 @@ internal static partial class ChatMessageExtensions
|
||||
}
|
||||
|
||||
int depth = 0;
|
||||
bool inQuotes = false, inEscape = false;
|
||||
for (; scanHead < messageText.Length && end is null; scanHead++)
|
||||
{
|
||||
if (inEscape)
|
||||
{
|
||||
inEscape = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (messageText[scanHead])
|
||||
{
|
||||
case '{':
|
||||
case '{' when !inQuotes:
|
||||
depth++;
|
||||
break;
|
||||
case '}':
|
||||
case '}' when !inQuotes:
|
||||
depth--;
|
||||
if (depth == 0)
|
||||
{
|
||||
end = scanHead;
|
||||
}
|
||||
|
||||
break;
|
||||
case '\"':
|
||||
// We already handled inEscape, so we can always flip inQuotes here
|
||||
inQuotes = !inQuotes;
|
||||
break;
|
||||
case '\\':
|
||||
Debug.Assert(!inEscape);
|
||||
inEscape = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -155,4 +170,6 @@ internal static partial class ChatMessageExtensions
|
||||
|
||||
return JsonElement.Parse(messageText.Substring(start, end.Value - start + 1));
|
||||
}
|
||||
|
||||
public static JsonElement ExtractJson(this ChatMessage message) => ExtractJson(message.Text);
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ internal static partial class WorkflowsJsonUtilities
|
||||
[JsonSerializable(typeof(MagenticPlanReviewRequest))]
|
||||
[JsonSerializable(typeof(MagenticPlanReviewResponse))]
|
||||
[JsonSerializable(typeof(MagenticTaskState))]
|
||||
[JsonSerializable(typeof(ResetChatSignal))]
|
||||
|
||||
// Event Types
|
||||
//[JsonSerializable(typeof(WorkflowEvent))]
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Microsoft.Agents.AI.Workflows.UnitTests;
|
||||
public class MagenticProgressLedgerTests
|
||||
{
|
||||
public record KVPair(string key);
|
||||
public record AnswerReasonPair(bool answer, string reason);
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
@@ -92,6 +93,26 @@ public class MagenticProgressLedgerTests
|
||||
action.Should().Throw();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test_ExtractJson_SuceedsWithQuotesBrackets()
|
||||
{
|
||||
// Arrange
|
||||
ChatMessage message = new(ChatRole.Assistant,
|
||||
"""
|
||||
{"reason":"the output contained }", "answer": false}
|
||||
""");
|
||||
|
||||
// Act
|
||||
JsonElement element = message.ExtractJson();
|
||||
|
||||
// Assert
|
||||
AnswerReasonPair? result = element.Deserialize<AnswerReasonPair>();
|
||||
|
||||
result.Should().NotBeNull();
|
||||
result.reason.Should().Be("the output contained }");
|
||||
result.answer.Should().BeFalse();
|
||||
}
|
||||
|
||||
public static readonly string TestTeamNames = string.Join(", ", ["CodingAgent", "CodeExecutor", "WebSurferAgent", "FileSurferAgent"]);
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user