You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

BaseAgent.cs 3.9 kB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // BaseAgent.cs
  3. using System.Diagnostics;
  4. using System.Reflection;
  5. using Microsoft.AutoGen.Contracts;
  6. using Microsoft.Extensions.Logging;
  7. namespace Microsoft.AutoGen.Core;
  8. /// <summary>
  9. /// Represents the base class for an agent in the AutoGen system.
  10. /// </summary>
  11. public abstract class BaseAgent : IAgent, IHostableAgent
  12. {
  13. /// <summary>
  14. /// The activity source for tracing.
  15. /// </summary>
  16. public static readonly ActivitySource s_source = new("Microsoft.AutoGen.Core.Agent");
  17. /// <summary>
  18. /// Gets the unique identifier of the agent.
  19. /// </summary>
  20. public AgentId Id { get; private set; }
  21. protected internal ILogger<BaseAgent> _logger;
  22. protected IAgentRuntime Runtime { get; private set; }
  23. private readonly Dictionary<Type, HandlerInvoker> handlerInvokers;
  24. protected string Description { get; private set; }
  25. public AgentMetadata Metadata
  26. {
  27. get
  28. {
  29. return new AgentMetadata
  30. {
  31. Type = Id.Type,
  32. Key = Id.Key,
  33. Description = Description
  34. };
  35. }
  36. }
  37. protected BaseAgent(
  38. AgentId id,
  39. IAgentRuntime runtime,
  40. string description,
  41. ILogger<BaseAgent>? logger = null)
  42. {
  43. Id = id;
  44. _logger = logger ?? LoggerFactory.Create(builder => { }).CreateLogger<BaseAgent>();
  45. Description = description;
  46. Runtime = runtime;
  47. this.handlerInvokers = this.ReflectInvokers();
  48. }
  49. private Dictionary<Type, HandlerInvoker> ReflectInvokers()
  50. {
  51. Type realType = this.GetType();
  52. IEnumerable<Type> candidateInterfaces =
  53. realType.GetInterfaces()
  54. .Where(i => i.IsGenericType &&
  55. (i.GetGenericTypeDefinition() == typeof(IHandle<>) ||
  56. (i.GetGenericTypeDefinition() == typeof(IHandle<,>))));
  57. Dictionary<Type, HandlerInvoker> invokers = new();
  58. foreach (Type interface_ in candidateInterfaces)
  59. {
  60. MethodInfo handleAsync = interface_.GetMethod(nameof(IHandle<object>.HandleAsync), BindingFlags.Instance | BindingFlags.Public)
  61. ?? throw new InvalidOperationException($"No handler method found for interface {interface_.FullName}");
  62. HandlerInvoker invoker = new(handleAsync, this);
  63. invokers.Add(interface_.GetGenericArguments()[0], invoker);
  64. }
  65. return invokers;
  66. }
  67. public async ValueTask<object?> OnMessageAsync(object message, MessageContext messageContext)
  68. {
  69. // Determine type of message, then get handler method and invoke it
  70. var messageType = message.GetType();
  71. if (this.handlerInvokers.TryGetValue(messageType, out var handlerInvoker))
  72. {
  73. return await handlerInvoker.InvokeAsync(message, messageContext);
  74. }
  75. return null;
  76. }
  77. public virtual ValueTask<IDictionary<string, object>> SaveStateAsync()
  78. {
  79. return ValueTask.FromResult<IDictionary<string, object>>(new Dictionary<string, object>());
  80. }
  81. public virtual ValueTask LoadStateAsync(IDictionary<string, object> state)
  82. {
  83. return ValueTask.CompletedTask;
  84. }
  85. public ValueTask<object?> SendMessageAsync(object message, AgentId recepient, string? messageId = null, CancellationToken cancellationToken = default)
  86. {
  87. return this.Runtime.SendMessageAsync(message, recepient, sender: this.Id, messageId: messageId, cancellationToken: cancellationToken);
  88. }
  89. public ValueTask PublishMessageAsync(object message, TopicId topic, string? messageId = null, CancellationToken cancellationToken = default)
  90. {
  91. return this.Runtime.PublishMessageAsync(message, topic, sender: this.Id, messageId: messageId, cancellationToken: cancellationToken);
  92. }
  93. }