// Copyright (c) Microsoft. All rights reserved. using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace Microsoft.Extensions.AI.Agents.Runtime; /// /// Internal implementation of that manages actor type registrations /// and their associated factory methods for the actor runtime system. /// internal sealed class ActorRuntimeBuilder : IActorRuntimeBuilder { private readonly IHostApplicationBuilder _builder; /// /// Gets the collection of registered actor types and their corresponding factory methods. /// /// /// A dictionary where keys are instances and values are factory functions /// that create instances given an and . /// public Dictionary> ActorFactories { get; } = new(); /// /// Gets or creates an instance for the specified host application builder. /// If an instance already exists in the service collection, it returns the existing instance. /// Otherwise, it creates a new instance and registers it as a singleton service. /// /// The host application builder to associate with the actor runtime builder. /// /// An instance that can be used to configure actor types. /// /// Thrown when is null. public static ActorRuntimeBuilder GetOrAdd(IHostApplicationBuilder builder) { Microsoft.Shared.Diagnostics.Throw.IfNull(builder); var services = builder.Services; var descriptor = services.FirstOrDefault(s => s.ImplementationInstance is ActorRuntimeBuilder); if (descriptor?.ImplementationInstance is not ActorRuntimeBuilder instance) { instance = new ActorRuntimeBuilder(builder); services.Add(ServiceDescriptor.Singleton(instance)); instance.ConfigureServices(services); } return instance; } /// /// Initializes a new instance of the class. /// /// The host application builder to associate with this actor runtime builder. private ActorRuntimeBuilder(IHostApplicationBuilder builder) { this._builder = builder; } /// /// Registers an actor type with its factory method in the actor runtime. /// /// The actor type to register. /// /// The factory method that creates instances of the actor. This function receives an /// for dependency injection and an /// for the actor's runtime context, and returns an instance. /// /// /// Thrown when an actor type with the same name is already registered. /// /// /// Each actor type can only be registered once. Attempting to register the same actor type /// multiple times will result in an exception being thrown by the underlying dictionary. /// public void AddActorType(ActorType type, Func activator) { this.ActorFactories.Add(type, activator); } private void ConfigureServices(IServiceCollection services) { services.AddSingleton(this); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(sp => { var jsonSerializerOptions = sp.GetService() ?? new(); var actorStateStorage = sp.GetRequiredService(); return new InProcessActorRuntime(sp, this.ActorFactories, actorStateStorage, jsonSerializerOptions); }); } }