From 7c639fa4eca07e17dd2521c0496b650b9dc84f48 Mon Sep 17 00:00:00 2001 From: Kosta Petan Date: Mon, 9 Dec 2024 23:48:23 +0100 Subject: [PATCH] Add samples resources back --- dotnet/AutoGen.sln | 7 + .../Hello/Hello.ServiceDefaults/Extensions.cs | 120 ++++++++++++++++++ .../Hello.ServiceDefaults.csproj | 22 ++++ .../samples/Hello/Hello.Shared/AgentsApp.cs | 88 +++++++++++++ .../Hello/Hello.Shared/Hello.Shared.csproj | 16 +++ .../Hello.Shared/MEAIHostingExtensions.cs | 34 +++++ .../ServiceCollectionChatClientExtensions.cs | 120 ++++++++++++++++++ .../Hello/HelloAIAgents/HelloAIAgent.cs | 1 + dotnet/samples/Hello/HelloAIAgents/Program.cs | 36 +++--- dotnet/samples/Hello/HelloAgent/Program.cs | 24 +--- .../samples/Hello/HelloAgentState/Program.cs | 13 +- .../RegistryGrain.cs | 2 +- 12 files changed, 438 insertions(+), 45 deletions(-) create mode 100644 dotnet/samples/Hello/Hello.ServiceDefaults/Extensions.cs create mode 100644 dotnet/samples/Hello/Hello.ServiceDefaults/Hello.ServiceDefaults.csproj create mode 100644 dotnet/samples/Hello/Hello.Shared/AgentsApp.cs create mode 100644 dotnet/samples/Hello/Hello.Shared/MEAIHostingExtensions.cs create mode 100644 dotnet/samples/Hello/Hello.Shared/ServiceCollectionChatClientExtensions.cs diff --git a/dotnet/AutoGen.sln b/dotnet/AutoGen.sln index bdae578b14f1..e8841ec3f0eb 100644 --- a/dotnet/AutoGen.sln +++ b/dotnet/AutoGen.sln @@ -64,6 +64,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AutoGen.Core.Grpc EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AutoGen.Runtime.Grpc.Tests", "test\Microsoft.AutoGen.Runtime.Grpc.Tests\Microsoft.AutoGen.Runtime.Grpc.Tests.csproj", "{8881C07D-5B57-4D7A-81D2-65A727315A2F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hello.ServiceDefaults", "samples\Hello\Hello.ServiceDefaults\Hello.ServiceDefaults.csproj", "{FACFAB26-0C21-4D9E-A855-875AEFF5948B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -146,6 +148,10 @@ Global {8881C07D-5B57-4D7A-81D2-65A727315A2F}.Debug|Any CPU.Build.0 = Debug|Any CPU {8881C07D-5B57-4D7A-81D2-65A727315A2F}.Release|Any CPU.ActiveCfg = Release|Any CPU {8881C07D-5B57-4D7A-81D2-65A727315A2F}.Release|Any CPU.Build.0 = Release|Any CPU + {FACFAB26-0C21-4D9E-A855-875AEFF5948B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FACFAB26-0C21-4D9E-A855-875AEFF5948B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FACFAB26-0C21-4D9E-A855-875AEFF5948B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FACFAB26-0C21-4D9E-A855-875AEFF5948B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -172,6 +178,7 @@ Global {6EF624FB-4247-138B-67FC-9ECC925FC4FA} = {18BF8DD7-0585-48BF-8F97-AD333080CE06} {FCCE32DE-8162-47F3-835D-2EF78D4381C3} = {F823671B-3ECA-4AE6-86DA-25E920D3FE64} {8881C07D-5B57-4D7A-81D2-65A727315A2F} = {F823671B-3ECA-4AE6-86DA-25E920D3FE64} + {FACFAB26-0C21-4D9E-A855-875AEFF5948B} = {7EB336C2-7C0A-4BC8-80C6-A3173AB8DC45} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {93384647-528D-46C8-922C-8DB36A382F0B} diff --git a/dotnet/samples/Hello/Hello.ServiceDefaults/Extensions.cs b/dotnet/samples/Hello/Hello.ServiceDefaults/Extensions.cs new file mode 100644 index 000000000000..adb2952115ff --- /dev/null +++ b/dotnet/samples/Hello/Hello.ServiceDefaults/Extensions.cs @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Extensions.cs + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Logging; +using OpenTelemetry; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; + +namespace Microsoft.Extensions.Hosting; +// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry. +// This project should be referenced by each service project in your solution. +// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults +public static class Extensions +{ + public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.ConfigureOpenTelemetry(); + + builder.AddDefaultHealthChecks(); + + builder.Services.AddServiceDiscovery(); + + builder.Services.ConfigureHttpClientDefaults(http => + { + // Turn on resilience by default + http.AddStandardResilienceHandler(); + + // Turn on service discovery by default + http.AddServiceDiscovery(); + }); + + // Uncomment the following to restrict the allowed schemes for service discovery. + // builder.Services.Configure(options => + // { + // options.AllowedSchemes = ["https"]; + // }); + + return builder; + } + + public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.Logging.AddOpenTelemetry(logging => + { + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + }); + + builder.Services.AddOpenTelemetry() + .WithMetrics(metrics => + { + metrics.AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddRuntimeInstrumentation(); + }) + .WithTracing(tracing => + { + tracing.AddSource(builder.Environment.ApplicationName) + .AddAspNetCoreInstrumentation() + // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) + //.AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation(); + }); + + builder.AddOpenTelemetryExporters(); + + return builder; + } + + private static TBuilder AddOpenTelemetryExporters(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); + + if (useOtlpExporter) + { + builder.Services.AddOpenTelemetry().UseOtlpExporter(); + } + + // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package) + //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"])) + //{ + // builder.Services.AddOpenTelemetry() + // .UseAzureMonitor(); + //} + + return builder; + } + + public static TBuilder AddDefaultHealthChecks(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.Services.AddHealthChecks() + // Add a default liveness check to ensure app is responsive + .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); + + return builder; + } + + public static WebApplication MapDefaultEndpoints(this WebApplication app) + { + // Adding health checks endpoints to applications in non-development environments has security implications. + // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments. + if (app.Environment.IsDevelopment()) + { + // All health checks must pass for app to be considered ready to accept traffic after starting + app.MapHealthChecks("/health"); + + // Only health checks tagged with the "live" tag must pass for app to be considered alive + app.MapHealthChecks("/alive", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("live") + }); + } + + return app; + } +} diff --git a/dotnet/samples/Hello/Hello.ServiceDefaults/Hello.ServiceDefaults.csproj b/dotnet/samples/Hello/Hello.ServiceDefaults/Hello.ServiceDefaults.csproj new file mode 100644 index 000000000000..2388aea655b8 --- /dev/null +++ b/dotnet/samples/Hello/Hello.ServiceDefaults/Hello.ServiceDefaults.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + + + + + + + diff --git a/dotnet/samples/Hello/Hello.Shared/AgentsApp.cs b/dotnet/samples/Hello/Hello.Shared/AgentsApp.cs new file mode 100644 index 000000000000..8e861a30e4ba --- /dev/null +++ b/dotnet/samples/Hello/Hello.Shared/AgentsApp.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// AgentsApp.cs + +using Google.Protobuf; +using Microsoft.AspNetCore.Builder; +using Microsoft.AutoGen.Core; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System.Diagnostics.CodeAnalysis; + +public static class AgentsApp +{ + // need a variable to store the runtime instance + public static WebApplication? Host { get; private set; } + + [MemberNotNull(nameof(Host))] + public static async ValueTask StartAsync(WebApplicationBuilder? builder = null, AgentTypes? agentTypes = null, bool local = false) + { + builder ??= WebApplication.CreateBuilder(); + if (local) + { + // start the server runtime + builder.AddInMemoryWorker(); + builder.AddAgentHost(); + builder.AddAgents(agentTypes); + } + + //builder.AddServiceDefaults(); + var app = builder.Build(); + if (local) + { + // app.MapAgentService(local: true, useGrpc: false); + } + app.MapDefaultEndpoints(); + Host = app; + await app.StartAsync().ConfigureAwait(false); + return Host; + } + public static async ValueTask PublishMessageAsync( + string topic, + IMessage message, + WebApplicationBuilder? builder = null, + AgentTypes? agents = null, + bool local = false) + { + if (Host == null) + { + await StartAsync(builder, agents, local); + } + var client = Host.Services.GetRequiredService() ?? throw new InvalidOperationException("Host not started"); + await client.PublishEventAsync(message, topic, new CancellationToken()).ConfigureAwait(true); + return Host; + } + public static async ValueTask ShutdownAsync() + { + if (Host == null) + { + throw new InvalidOperationException("Host not started"); + } + await Host.StopAsync(); + } + + private static IHostApplicationBuilder AddAgents(this IHostApplicationBuilder builder, AgentTypes? agentTypes) + { + agentTypes ??= AgentTypes.GetAgentTypesFromAssembly() + ?? throw new InvalidOperationException("No agent types found in the assembly"); + foreach (var type in agentTypes.Types) + { + builder.AddAgent(type.Key, type.Value); + } + return builder; + } +} +public sealed class AgentTypes(Dictionary types) +{ + public Dictionary Types { get; } = types; + public static AgentTypes? GetAgentTypesFromAssembly() + { + var agents = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(assembly => assembly.GetTypes()) + .Where(type => ReflectionHelper.IsSubclassOfGeneric(type, typeof(Agent)) + && !type.IsAbstract + && !type.Name.Equals(nameof(Client))) + .ToDictionary(type => type.Name, type => type); + + return new AgentTypes(agents); + } +} diff --git a/dotnet/samples/Hello/Hello.Shared/Hello.Shared.csproj b/dotnet/samples/Hello/Hello.Shared/Hello.Shared.csproj index 694773751040..6bee91d2f99f 100644 --- a/dotnet/samples/Hello/Hello.Shared/Hello.Shared.csproj +++ b/dotnet/samples/Hello/Hello.Shared/Hello.Shared.csproj @@ -15,6 +15,22 @@ + + + + + + + + + + + + + + + + diff --git a/dotnet/samples/Hello/Hello.Shared/MEAIHostingExtensions.cs b/dotnet/samples/Hello/Hello.Shared/MEAIHostingExtensions.cs new file mode 100644 index 000000000000..720de447b1b0 --- /dev/null +++ b/dotnet/samples/Hello/Hello.Shared/MEAIHostingExtensions.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// MEAIHostingExtensions.cs + +using Microsoft.Extensions.AI; +using Microsoft.Extensions.Hosting; + +public static class MEAIHostingExtensions +{ + public static IHostApplicationBuilder AddChatCompletionService(this IHostApplicationBuilder builder, string serviceName) + { + var pipeline = (ChatClientBuilder pipeline) => pipeline + .UseLogging() + .UseFunctionInvocation() + .UseOpenTelemetry(configure: c => c.EnableSensitiveData = true); + + if (builder.Configuration[$"{serviceName}:ModelType"] == "ollama") + { + builder.AddOllamaChatClient(serviceName, pipeline); + } + else if (builder.Configuration[$"{serviceName}:ModelType"] == "openai" || builder.Configuration[$"{serviceName}:ModelType"] == "azureopenai") + { + builder.AddOpenAIChatClient(serviceName, pipeline); + } + else if (builder.Configuration[$"{serviceName}:ModelType"] == "azureaiinference") + { + builder.AddAzureChatClient(serviceName, pipeline); + } + else + { + throw new InvalidOperationException("Did not find a valid model implementation for the given service name ${serviceName}, valid supported implemenation types are ollama, openai, azureopenai, azureaiinference"); + } + return builder; + } +} diff --git a/dotnet/samples/Hello/Hello.Shared/ServiceCollectionChatClientExtensions.cs b/dotnet/samples/Hello/Hello.Shared/ServiceCollectionChatClientExtensions.cs new file mode 100644 index 000000000000..0b5e14c250d5 --- /dev/null +++ b/dotnet/samples/Hello/Hello.Shared/ServiceCollectionChatClientExtensions.cs @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ServiceCollectionChatClientExtensions.cs + +using Microsoft.Extensions.AI; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using System.Data.Common; +using Microsoft.Extensions.Hosting; +using OpenAI; +using Azure.AI.OpenAI; +using System.ClientModel; +using Azure.AI.Inference; +using Azure; + +public static class ServiceCollectionChatClientExtensions +{ + public static IServiceCollection AddOllamaChatClient( + this IHostApplicationBuilder hostBuilder, + string serviceName, + Func? builder = null, + string? modelName = null) + { + if (modelName is null) + { + var configKey = $"{serviceName}:LlmModelName"; + modelName = hostBuilder.Configuration[configKey]; + if (string.IsNullOrEmpty(modelName)) + { + throw new InvalidOperationException($"No {nameof(modelName)} was specified, and none could be found from configuration at '{configKey}'"); + } + } + return hostBuilder.Services.AddOllamaChatClient( + modelName, + new Uri($"http://{serviceName}"), + builder); + } + public static IServiceCollection AddOllamaChatClient( + this IServiceCollection services, + string modelName, + Uri? uri = null, + Func? builder = null) + { + uri ??= new Uri("http://localhost:11434"); + return services.AddChatClient(pipeline => + { + builder?.Invoke(pipeline); + var httpClient = pipeline.Services.GetService() ?? new(); + return pipeline.Use(new OllamaChatClient(uri, modelName, httpClient)); + }); + } + public static IServiceCollection AddOpenAIChatClient( + this IHostApplicationBuilder hostBuilder, + string serviceName, + Func? builder = null, + string? modelOrDeploymentName = null) + { + // TODO: We would prefer to use Aspire.AI.OpenAI here, + var connectionString = hostBuilder.Configuration.GetConnectionString(serviceName); + if (string.IsNullOrWhiteSpace(connectionString)) + { + throw new InvalidOperationException($"No connection string named '{serviceName}' was found. Ensure a corresponding Aspire service was registered."); + } + var connectionStringBuilder = new DbConnectionStringBuilder(); + connectionStringBuilder.ConnectionString = connectionString; + var endpoint = (string?)connectionStringBuilder["endpoint"]; + var apiKey = (string)connectionStringBuilder["key"] ?? throw new InvalidOperationException($"The connection string named '{serviceName}' does not specify a value for 'Key', but this is required."); + + modelOrDeploymentName ??= (connectionStringBuilder["Deployment"] ?? connectionStringBuilder["Model"]) as string; + if (string.IsNullOrWhiteSpace(modelOrDeploymentName)) + { + throw new InvalidOperationException($"The connection string named '{serviceName}' does not specify a value for 'Deployment' or 'Model', and no value was passed for {nameof(modelOrDeploymentName)}."); + } + + var endpointUri = string.IsNullOrEmpty(endpoint) ? null : new Uri(endpoint); + return hostBuilder.Services.AddOpenAIChatClient(apiKey, modelOrDeploymentName, endpointUri, builder); + } + public static IServiceCollection AddOpenAIChatClient( + this IServiceCollection services, + string apiKey, + string modelOrDeploymentName, + Uri? endpoint = null, + Func? builder = null) + { + return services + .AddSingleton(_ => endpoint is null + ? new OpenAIClient(apiKey) + : new AzureOpenAIClient(endpoint, new ApiKeyCredential(apiKey))) + .AddChatClient(pipeline => + { + builder?.Invoke(pipeline); + var openAiClient = pipeline.Services.GetRequiredService(); + return pipeline.Use(openAiClient.AsChatClient(modelOrDeploymentName)); + }); + } + public static IServiceCollection AddAzureChatClient( + this IHostApplicationBuilder hostBuilder, + string serviceName, + Func? builder = null, + string? modelOrDeploymentName = null) + { + if (modelOrDeploymentName is null) + { + var configKey = $"{serviceName}:LlmModelName"; + modelOrDeploymentName = hostBuilder.Configuration[configKey]; + if (string.IsNullOrEmpty(modelOrDeploymentName)) + { + throw new InvalidOperationException($"No {nameof(modelOrDeploymentName)} was specified, and none could be found from configuration at '{configKey}'"); + } + } + var endpoint = $"{serviceName}:Endpoint" ?? throw new InvalidOperationException($"No endpoint was specified for the Azure Inference Chat Client"); + var endpointUri = string.IsNullOrEmpty(endpoint) ? null : new Uri(endpoint); + return hostBuilder.Services.AddChatClient(pipeline => + { + builder?.Invoke(pipeline); + var token = Environment.GetEnvironmentVariable("GH_TOKEN") ?? throw new InvalidOperationException("No model access token was found in the environment variable GH_TOKEN"); + return pipeline.Use(new ChatCompletionsClient( + endpointUri, new AzureKeyCredential(token)).AsChatClient(modelOrDeploymentName)); + }); + } +} diff --git a/dotnet/samples/Hello/HelloAIAgents/HelloAIAgent.cs b/dotnet/samples/Hello/HelloAIAgents/HelloAIAgent.cs index 2290d018f45a..3d70d1454e9f 100644 --- a/dotnet/samples/Hello/HelloAIAgents/HelloAIAgent.cs +++ b/dotnet/samples/Hello/HelloAIAgents/HelloAIAgent.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // HelloAIAgent.cs +using Hello; using Hello.Events; using Microsoft.AutoGen.Abstractions; using Microsoft.AutoGen.Core; diff --git a/dotnet/samples/Hello/HelloAIAgents/Program.cs b/dotnet/samples/Hello/HelloAIAgents/Program.cs index 3cbab1b4fa9f..ac0ba9452a6c 100644 --- a/dotnet/samples/Hello/HelloAIAgents/Program.cs +++ b/dotnet/samples/Hello/HelloAIAgents/Program.cs @@ -2,7 +2,7 @@ // Program.cs using Hello.Events; -using Microsoft.AutoGen.Abstractions; +using HelloAIAgents; using Microsoft.AutoGen.Core; // send a message to the agent @@ -16,29 +16,27 @@ throw new InvalidOperationException("AZURE_OPENAI_CONNECTION_STRING not set, try something like AZURE_OPENAI_CONNECTION_STRING = \"Endpoint=https://TODO.openai.azure.com/;Key=TODO;Deployment=TODO\""); } builder.Configuration["ConectionStrings:HelloAIAgents"] = Environment.GetEnvironmentVariable("AZURE_OPENAI_CONNECTION_STRING"); -//builder.AddChatCompletionService("HelloAIAgents"); -//var agentTypes = new AgentTypes(new Dictionary -//{ -// { "HelloAIAgents", typeof(HelloAIAgent) } -//}); -// TODO: replace with Client -//var app = await AgentsApp.PublishMessageAsync("HelloAgents", new NewMessageReceived -//{ -// Message = "World" -//}, builder, agentTypes, local: true); -var app = builder.Build(); +builder.AddChatCompletionService("HelloAIAgents"); +var agentTypes = new AgentTypes(new Dictionary +{ + { "HelloAIAgents", typeof(HelloAIAgent) } +}); +var app = await AgentsApp.PublishMessageAsync("HelloAgents", new NewMessageReceived +{ + Message = "World" +}, builder, agentTypes, local: true); + await app.WaitForShutdownAsync(); -namespace HelloAIAgents +namespace Hello { - [TopicSubscription("HelloAgents")] + [TopicSubscription("agents")] public class HelloAgent( [FromKeyedServices("EventTypes")] EventTypes typeRegistry, IHostApplicationLifetime hostApplicationLifetime) : Agent( - typeRegistry), - ISayHello, - IHandle, - IHandle + typeRegistry), + IHandle, + IHandle { public async Task Handle(NewMessageReceived item, CancellationToken cancellationToken = default) { @@ -50,7 +48,7 @@ public async Task Handle(NewMessageReceived item, CancellationToken cancellation await PublishEventAsync(evt).ConfigureAwait(false); var goodbye = new ConversationClosed { - UserId = AgentId.Key, + UserId = this.AgentId.Key, UserMessage = "Goodbye" }; await PublishEventAsync(goodbye).ConfigureAwait(false); diff --git a/dotnet/samples/Hello/HelloAgent/Program.cs b/dotnet/samples/Hello/HelloAgent/Program.cs index 2185c5184e2f..e07424e19440 100644 --- a/dotnet/samples/Hello/HelloAgent/Program.cs +++ b/dotnet/samples/Hello/HelloAgent/Program.cs @@ -2,28 +2,16 @@ // Program.cs using Hello.Events; -using Microsoft.AspNetCore.Builder; using Microsoft.AutoGen.Core; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -// step 1: create in-memory agent runtime - -// step 2: register HelloAgent to that agent runtime - -// step 3: start the agent runtime - -// step 4: send a message to the agent - -// step 5: wait for the agent runtime to shutdown -// TODO: replace with Client -var builder = WebApplication.CreateBuilder(); -//var app = await AgentsApp.PublishMessageAsync("HelloAgents", new NewMessageReceived -//{ -// Message = "World" -//}, local: true); -////var app = await AgentsApp.StartAsync(); -var app = builder.Build(); +var local = true; +if (Environment.GetEnvironmentVariable("AGENT_HOST") != null) { local = false; } +var app = await AgentsApp.PublishMessageAsync("HelloAgents", new NewMessageReceived +{ + Message = "World" +}, local: local).ConfigureAwait(false); await app.WaitForShutdownAsync(); namespace HelloAgent diff --git a/dotnet/samples/Hello/HelloAgentState/Program.cs b/dotnet/samples/Hello/HelloAgentState/Program.cs index d18e4ca7d2a5..826ba0b38d62 100644 --- a/dotnet/samples/Hello/HelloAgentState/Program.cs +++ b/dotnet/samples/Hello/HelloAgentState/Program.cs @@ -7,13 +7,12 @@ using Microsoft.AutoGen.Core; // send a message to the agent -// TODO: replace with Client -var builder = WebApplication.CreateBuilder(); -//var app = await AgentsApp.PublishMessageAsync("HelloAgents", new NewMessageReceived -//{ -// Message = "World" -//}, local: false); -var app = builder.Build(); +var local = true; +if (Environment.GetEnvironmentVariable("AGENT_HOST") != null) { local = false; } +var app = await AgentsApp.PublishMessageAsync("HelloAgents", new NewMessageReceived +{ + Message = "World" +}, local: local).ConfigureAwait(false); await app.WaitForShutdownAsync(); namespace HelloAgentState diff --git a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/RegistryGrain.cs b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/RegistryGrain.cs index 159e4062fade..2c077dba56a0 100644 --- a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/RegistryGrain.cs +++ b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/RegistryGrain.cs @@ -20,7 +20,7 @@ public override Task OnActivateAsync(CancellationToken cancellationToken) } public ValueTask<(IGateway? Worker, bool NewPlacement)> GetOrPlaceAgent(AgentId agentId) { - // TODO: + // TODO: Clarify the logic bool isNewPlacement; if (!_agentDirectory.TryGetValue((agentId.Type, agentId.Key), out var worker) || !_workerStates.ContainsKey(worker)) {