2025-01-27 13:00:05 -05:00
|
|
|
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
2025-01-27 13:05:25 -05:00
|
|
|
// BaseAgent.cs
|
2025-01-27 13:00:05 -05:00
|
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.Reflection;
|
2025-02-06 17:09:26 -05:00
|
|
|
using System.Text.Json;
|
2025-01-27 15:35:06 -05:00
|
|
|
using Microsoft.AutoGen.Contracts;
|
2025-01-27 13:00:05 -05:00
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
2025-01-27 15:35:06 -05:00
|
|
|
namespace Microsoft.AutoGen.Core;
|
2025-01-27 17:33:40 -05:00
|
|
|
|
2025-01-27 13:00:05 -05:00
|
|
|
/// <summary>
|
|
|
|
/// Represents the base class for an agent in the AutoGen system.
|
|
|
|
/// </summary>
|
|
|
|
public abstract class BaseAgent : IAgent, IHostableAgent
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// The activity source for tracing.
|
|
|
|
/// </summary>
|
|
|
|
public static readonly ActivitySource s_source = new("Microsoft.AutoGen.Core.Agent");
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the unique identifier of the agent.
|
|
|
|
/// </summary>
|
|
|
|
public AgentId Id { get; private set; }
|
2025-01-27 14:35:19 -05:00
|
|
|
protected internal ILogger<BaseAgent> _logger;
|
2025-01-27 13:00:05 -05:00
|
|
|
|
|
|
|
protected IAgentRuntime Runtime { get; private set; }
|
2025-01-27 17:57:25 -05:00
|
|
|
private readonly Dictionary<Type, HandlerInvoker> handlerInvokers;
|
2025-01-27 13:00:05 -05:00
|
|
|
|
|
|
|
protected string Description { get; private set; }
|
|
|
|
|
2025-01-27 17:57:25 -05:00
|
|
|
public AgentMetadata Metadata
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2025-01-27 13:00:05 -05:00
|
|
|
return new AgentMetadata
|
|
|
|
{
|
|
|
|
Type = Id.Type,
|
|
|
|
Key = Id.Key,
|
|
|
|
Description = Description
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected BaseAgent(
|
|
|
|
AgentId id,
|
|
|
|
IAgentRuntime runtime,
|
|
|
|
string description,
|
2025-01-27 14:35:19 -05:00
|
|
|
ILogger<BaseAgent>? logger = null)
|
2025-01-27 13:00:05 -05:00
|
|
|
{
|
|
|
|
Id = id;
|
2025-01-27 14:35:19 -05:00
|
|
|
_logger = logger ?? LoggerFactory.Create(builder => { }).CreateLogger<BaseAgent>();
|
2025-01-27 13:00:05 -05:00
|
|
|
Description = description;
|
|
|
|
Runtime = runtime;
|
2025-01-27 17:57:25 -05:00
|
|
|
|
|
|
|
this.handlerInvokers = this.ReflectInvokers();
|
|
|
|
}
|
|
|
|
|
|
|
|
private Dictionary<Type, HandlerInvoker> ReflectInvokers()
|
|
|
|
{
|
|
|
|
Type realType = this.GetType();
|
|
|
|
|
|
|
|
IEnumerable<Type> candidateInterfaces =
|
|
|
|
realType.GetInterfaces()
|
|
|
|
.Where(i => i.IsGenericType &&
|
|
|
|
(i.GetGenericTypeDefinition() == typeof(IHandle<>) ||
|
|
|
|
(i.GetGenericTypeDefinition() == typeof(IHandle<,>))));
|
|
|
|
|
|
|
|
Dictionary<Type, HandlerInvoker> invokers = new();
|
|
|
|
foreach (Type interface_ in candidateInterfaces)
|
|
|
|
{
|
2025-01-28 16:17:11 -05:00
|
|
|
MethodInfo handleAsync = interface_.GetMethod(nameof(IHandle<object>.HandleAsync), BindingFlags.Instance | BindingFlags.Public)
|
|
|
|
?? throw new InvalidOperationException($"No handler method found for interface {interface_.FullName}");
|
2025-01-27 17:57:25 -05:00
|
|
|
|
2025-01-28 16:17:11 -05:00
|
|
|
HandlerInvoker invoker = new(handleAsync, this);
|
2025-01-27 17:57:25 -05:00
|
|
|
invokers.Add(interface_.GetGenericArguments()[0], invoker);
|
|
|
|
}
|
|
|
|
|
|
|
|
return invokers;
|
2025-01-27 13:00:05 -05:00
|
|
|
}
|
|
|
|
|
2025-01-27 15:35:06 -05:00
|
|
|
public async ValueTask<object?> OnMessageAsync(object message, MessageContext messageContext)
|
2025-01-27 13:00:05 -05:00
|
|
|
{
|
|
|
|
// Determine type of message, then get handler method and invoke it
|
|
|
|
var messageType = message.GetType();
|
2025-01-27 17:57:25 -05:00
|
|
|
if (this.handlerInvokers.TryGetValue(messageType, out var handlerInvoker))
|
2025-01-27 13:00:05 -05:00
|
|
|
{
|
2025-01-27 17:57:25 -05:00
|
|
|
return await handlerInvoker.InvokeAsync(message, messageContext);
|
2025-01-27 13:00:05 -05:00
|
|
|
}
|
2025-01-27 18:14:34 -05:00
|
|
|
|
|
|
|
return null;
|
2025-01-27 13:00:05 -05:00
|
|
|
}
|
|
|
|
|
2025-02-06 17:09:26 -05:00
|
|
|
public virtual ValueTask<IDictionary<string, JsonElement>> SaveStateAsync()
|
2025-01-27 13:00:05 -05:00
|
|
|
{
|
2025-02-06 17:09:26 -05:00
|
|
|
return ValueTask.FromResult<IDictionary<string, JsonElement>>(new Dictionary<string, JsonElement>());
|
2025-01-27 13:00:05 -05:00
|
|
|
}
|
2025-02-06 17:09:26 -05:00
|
|
|
public virtual ValueTask LoadStateAsync(IDictionary<string, JsonElement> state)
|
2025-01-27 13:00:05 -05:00
|
|
|
{
|
2025-01-27 14:35:19 -05:00
|
|
|
return ValueTask.CompletedTask;
|
2025-01-27 13:00:05 -05:00
|
|
|
}
|
|
|
|
|
2025-01-28 15:28:05 -05:00
|
|
|
public ValueTask<object?> SendMessageAsync(object message, AgentId recepient, string? messageId = null, CancellationToken cancellationToken = default)
|
2025-01-27 13:00:05 -05:00
|
|
|
{
|
|
|
|
return this.Runtime.SendMessageAsync(message, recepient, sender: this.Id, messageId: messageId, cancellationToken: cancellationToken);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2025-01-28 15:28:05 -05:00
|
|
|
public ValueTask PublishMessageAsync(object message, TopicId topic, string? messageId = null, CancellationToken cancellationToken = default)
|
2025-01-27 13:00:05 -05:00
|
|
|
{
|
|
|
|
return this.Runtime.PublishMessageAsync(message, topic, sender: this.Id, messageId: messageId, cancellationToken: cancellationToken);
|
|
|
|
}
|
|
|
|
}
|