Skip to content

Commit

Permalink
fix bugs in ioagents and add extensions for AgentTypes
Browse files Browse the repository at this point in the history
  • Loading branch information
rysweet committed Oct 8, 2024
1 parent 8b12b77 commit 48856d5
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 34 deletions.
6 changes: 1 addition & 5 deletions dotnet/samples/Hello/Program.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
using Microsoft.Extensions.Hosting;
using Microsoft.AutoGen.Agents.Abstractions;
using Microsoft.AutoGen.Agents.Client;
using Runtime = Microsoft.AutoGen.Agents.Runtime;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;

// start the server runtime
var app = await Runtime.Host.StartAsync(true);
// start the client worker
var clientApp = await App.StartAsync<HelloAgent>("HelloAgent");
var clientApp = await App.StartAsync(local: true);
// get the client
var client = clientApp.Services.GetRequiredService<AgentClient>();

Expand All @@ -23,7 +20,6 @@
await client.PublishEventAsync(evt);

await clientApp.WaitForShutdownAsync();
await app.WaitForShutdownAsync();

[TopicSubscription("HelloAgents")]
public class HelloAgent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Microsoft.AutoGen.Agents.Client;

public class ConsoleAgent : IOAgent<AgentState>,
public abstract class ConsoleAgent : IOAgent<AgentState>,
IUseConsole,
IHandle<Input>,
IHandle<Output>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
using Microsoft.AutoGen.Agents.Abstractions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace Microsoft.AutoGen.Agents.Client;

[TopicSubscription("FileIO")]
public class FileAgent : IOAgent<AgentState>,
public abstract class FileAgent(
IAgentContext context,
[FromKeyedServices("EventTypes")] EventTypes typeRegistry,
string inputPath = "input.txt",
string outputPath = "output.txt"
) : IOAgent<AgentState>(context, typeRegistry),
IUseFiles,
IHandle<Input>,
IHandle<Output>
{
public FileAgent(IAgentContext context, EventTypes typeRegistry, string filePath) : base(context, typeRegistry)
{
_filePath = filePath;
}
private readonly string _filePath;

public override async Task Handle(Input item)
{

// validate that the file exists
if (!File.Exists(_filePath))
if (!File.Exists(inputPath))
{
string errorMessage = $"File not found: {_filePath}";
var errorMessage = $"File not found: {inputPath}";
Logger.LogError(errorMessage);
//publish IOError event
var err = new IOError
Expand All @@ -31,36 +30,30 @@ public override async Task Handle(Input item)
await PublishEvent(err);
return;
}

string content;
using (var reader = new StreamReader(item.Message))
{
content = await reader.ReadToEndAsync();
}

await ProcessInput(content);

var evt = new InputProcessed
{
Route = _route
}.ToCloudEvent(this.AgentId.Key);
await PublishEvent(evt);
}

public override async Task Handle(Output item)
{
using (var writer = new StreamWriter(_filePath, append: true))
using (var writer = new StreamWriter(outputPath, append: true))
{
await writer.WriteLineAsync(item.Message);
}

var evt = new OutputWritten
{
Route = _route
}.ToCloudEvent(this.AgentId.Key);
await PublishEvent(evt);
}

public override async Task<string> ProcessInput(string message)
{
var evt = new InputProcessed
Expand All @@ -70,14 +63,12 @@ public override async Task<string> ProcessInput(string message)
await PublishEvent(evt);
return message;
}

public override Task ProcessOutput(string message)
{
// Implement your output processing logic here
return Task.CompletedTask;
}
}

public interface IUseFiles
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Microsoft.AutoGen.Agents.Client;

public class WebAPIAgent : IOAgent<AgentState>,
public abstract class WebAPIAgent : IOAgent<AgentState>,
IUseWebAPI,
IHandle<Input>,
IHandle<Output>
Expand All @@ -16,8 +16,8 @@ public class WebAPIAgent : IOAgent<AgentState>,
public WebAPIAgent(
IAgentContext context,
[FromKeyedServices("EventTypes")] EventTypes typeRegistry,
string url,
ILogger<WebAPIAgent> logger) : base(
ILogger<WebAPIAgent> logger,
string url = "/agents/webio") : base(
context,
typeRegistry)
{
Expand Down
17 changes: 15 additions & 2 deletions dotnet/src/Microsoft.AutoGen.Agents.Client/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,23 @@ namespace Microsoft.AutoGen.Agents.Client;

public static class App
{
public static async Task<WebApplication> StartAsync<T>(string name) where T : AgentBase
// need a variable to store the runtime instance
public static WebApplication? RuntimeApp { get; set; }
public static async Task<WebApplication> StartAsync(AgentTypes? agentTypes = null, bool local = false)
{
if (RuntimeApp == null)
{
// start the server runtime
RuntimeApp = await Runtime.Host.StartAsync(local);
}
var clientBuilder = WebApplication.CreateBuilder();
clientBuilder.AddAgentWorker().AddAgent<T>(name);
var appBuilder = clientBuilder.AddAgentWorker();
agentTypes ??= AgentTypes.GetAgentTypesFromAssembly()
?? throw new InvalidOperationException("No agent types found in the assembly");
foreach (var type in agentTypes.Types)
{
appBuilder.AddAgent(type.Key, type.Value);
}
var clientApp = clientBuilder.Build();
await clientApp.StartAsync().ConfigureAwait(false);
return clientApp;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Microsoft.AutoGen.Agents.Client;
public static class HostBuilderExtensions
{
private const string _defaultAgentServiceAddress = "https://localhost:5001";
public static AgentApplicationBuilder AddAgentWorker(this IHostApplicationBuilder builder, string agentServiceAddress =_defaultAgentServiceAddress, bool local = false)
public static AgentApplicationBuilder AddAgentWorker(this IHostApplicationBuilder builder, string agentServiceAddress = _defaultAgentServiceAddress, bool local = false)
{
builder.Services.AddGrpcClient<AgentRpc.AgentRpcClient>(options =>
{
Expand Down Expand Up @@ -66,7 +66,7 @@ public static AgentApplicationBuilder AddAgentWorker(this IHostApplicationBuilde

var eventsMap = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => IsSubclassOfGeneric(type, typeof(AgentBase)) && !type.IsAbstract)
.Where(type => ReflectionHelper.IsSubclassOfGeneric(type, typeof(AgentBase)) && !type.IsAbstract)
.Select(t => (t, t.GetInterfaces()
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IHandle<>))
.Select(i => (GetMessageDescriptor(i.GetGenericArguments().First())?.FullName ?? "")).ToHashSet()))
Expand All @@ -82,8 +82,10 @@ public static AgentApplicationBuilder AddAgentWorker(this IHostApplicationBuilde
var property = type.GetProperty("Descriptor", BindingFlags.Static | BindingFlags.Public);
return property?.GetValue(null) as MessageDescriptor;
}

private static bool IsSubclassOfGeneric(Type type, Type genericBaseType)
}
public sealed class ReflectionHelper
{
public static bool IsSubclassOfGeneric(Type type, Type genericBaseType)
{
while (type != null && type != typeof(object))
{
Expand All @@ -100,7 +102,21 @@ private static bool IsSubclassOfGeneric(Type type, Type genericBaseType)
return false;
}
}
public sealed class AgentTypes(Dictionary<string, Type> types)
{
public Dictionary<string, Type> Types { get; } = types;
public static AgentTypes? GetAgentTypesFromAssembly()
{
var agents = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => ReflectionHelper.IsSubclassOfGeneric(type, typeof(AgentBase))
&& !type.IsAbstract
&& !type.Name.Equals("AgentClient"))
.ToDictionary(type => type.Name, type => type);

return new AgentTypes(agents);
}
}
public sealed class EventTypes(TypeRegistry typeRegistry, Dictionary<string, Type> types, Dictionary<Type, HashSet<string>> eventsMap)
{
public TypeRegistry TypeRegistry { get; } = typeRegistry;
Expand All @@ -116,5 +132,10 @@ public AgentApplicationBuilder AddAgent<
builder.Services.AddKeyedSingleton("AgentTypes", (sp, key) => Tuple.Create(typeName, typeof(TAgent)));
return this;
}
public AgentApplicationBuilder AddAgent(string typeName, Type agentType)
{
builder.Services.AddKeyedSingleton("AgentTypes", (sp, key) => Tuple.Create(typeName, agentType));
return this;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

<ItemGroup>
<ProjectReference Include="../Microsoft.AutoGen.Agents/Microsoft.AutoGen.Agents.csproj" />
<ProjectReference Include="..\Microsoft.AutoGen.Agents.Runtime\Microsoft.AutoGen.Agents.Runtime.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit 48856d5

Please sign in to comment.