diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props
index e6ada46abd48..5c41c338159c 100644
--- a/dotnet/Directory.Packages.props
+++ b/dotnet/Directory.Packages.props
@@ -78,6 +78,7 @@
+
diff --git a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Core.Grpc/GrpcAgentWorker.cs b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Core.Grpc/GrpcAgentWorker.cs
index 177310c470e2..5f58e1a92a2d 100644
--- a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Core.Grpc/GrpcAgentWorker.cs
+++ b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Core.Grpc/GrpcAgentWorker.cs
@@ -203,17 +203,14 @@ private async ValueTask RegisterAgentTypeAsync(string type, Type agentType, Canc
// TODO: Reimplement registration as RPC call
_logger.LogInformation($"{cancellationToken.ToString}"); // TODO: remove this
- //await WriteChannelAsync(new Message
- //{
- // RegisterAgentTypeRequest = new RegisterAgentTypeRequest
- // {
- // Type = type,
- // RequestId = Guid.NewGuid().ToString(),
- // //TopicTypes = { topicTypes },
- // //StateType = state?.Name,
- // Events = { events }
- // }
- //}, cancellationToken).ConfigureAwait(false);
+ var response = await _client.RegisterAgentAsync(new RegisterAgentTypeRequest
+ {
+ Type = type,
+ RequestId = Guid.NewGuid().ToString(),
+ //TopicTypes = { topicTypes },
+ //StateType = state?.Name,
+ Events = { events }
+ }, null, null, cancellationToken);
}
}
diff --git a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/GrpcGateway.cs b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/GrpcGateway.cs
index d8ddca87421a..ed2b2ed3b3bd 100644
--- a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/GrpcGateway.cs
+++ b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/GrpcGateway.cs
@@ -17,6 +17,7 @@ public sealed class GrpcGateway : BackgroundService, IGateway
private readonly ConcurrentDictionary _agentState = new();
private readonly IRegistryGrain _gatewayRegistry;
private readonly IGateway _reference;
+
// The agents supported by each worker process.
private readonly ConcurrentDictionary> _supportedAgentTypes = [];
internal readonly ConcurrentDictionary _workers = new();
@@ -35,33 +36,6 @@ public GrpcGateway(IClusterClient clusterClient, ILogger logger)
_reference = clusterClient.CreateObjectReference(this);
_gatewayRegistry = clusterClient.GetGrain(0);
}
- public async ValueTask BroadcastEvent(CloudEvent evt)
- {
- var tasks = new List();
- foreach (var (key, connection) in _supportedAgentTypes)
- {
- if (_agentsToEventsMap.TryGetValue(key, out var events) && events.Contains(evt.Type))
- {
- tasks.Add(SendMessageAsync(connection[0], evt, default));
- }
- }
- await Task.WhenAll(tasks).ConfigureAwait(false);
- }
- //intetionally not static so can be called by some methods implemented in base class
- internal async Task SendMessageAsync(GrpcWorkerConnection connection, CloudEvent cloudEvent, CancellationToken cancellationToken = default)
- {
- await connection.ResponseStream.WriteAsync(new Message { CloudEvent = cloudEvent }, cancellationToken).ConfigureAwait(false);
- }
- private void DispatchResponse(GrpcWorkerConnection connection, RpcResponse response)
- {
- if (!_pendingRequests.TryRemove((connection, response.RequestId), out var completion))
- {
- _logger.LogWarning("Received response for unknown request.");
- return;
- }
- // Complete the request.
- completion.SetResult(response);
- }
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
@@ -85,7 +59,32 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
_logger.LogWarning(exception, "Error removing worker from registry.");
}
}
- //new is intentional...
+
+ internal Task ConnectToWorkerProcess(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context)
+ {
+ _logger.LogInformation("Received new connection from {Peer}.", context.Peer);
+ var workerProcess = new GrpcWorkerConnection(this, requestStream, responseStream, context);
+ _workers[workerProcess] = workerProcess;
+ return workerProcess.Completion;
+ }
+
+ public async ValueTask BroadcastEvent(CloudEvent evt)
+ {
+ var tasks = new List();
+ foreach (var (key, connection) in _supportedAgentTypes)
+ {
+ if (_agentsToEventsMap.TryGetValue(key, out var events) && events.Contains(evt.Type))
+ {
+ tasks.Add(SendMessageAsync(connection[0], evt, default));
+ }
+ }
+ await Task.WhenAll(tasks).ConfigureAwait(false);
+ }
+ //intetionally not static so can be called by some methods implemented in base class
+ internal async Task SendMessageAsync(GrpcWorkerConnection connection, CloudEvent cloudEvent, CancellationToken cancellationToken = default)
+ {
+ await connection.ResponseStream.WriteAsync(new Message { CloudEvent = cloudEvent }, cancellationToken).ConfigureAwait(false);
+ }
internal async Task OnReceivedMessageAsync(GrpcWorkerConnection connection, Message message)
{
_logger.LogInformation("Received message {Message} from connection {Connection}.", message, connection);
@@ -101,32 +100,20 @@ internal async Task OnReceivedMessageAsync(GrpcWorkerConnection connection, Mess
await DispatchEventAsync(message.CloudEvent);
break;
default:
- // if it wasn't recognized return bad request
- await RespondBadRequestAsync(connection, $"Unknown message type for message '{message}'.");
- break;
+ throw new RpcException(new Status(StatusCode.InvalidArgument, $"Unknown message type for message '{message}'."));
};
}
- private async ValueTask RespondBadRequestAsync(GrpcWorkerConnection connection, string error)
+ private void DispatchResponse(GrpcWorkerConnection connection, RpcResponse response)
{
- throw new RpcException(new Status(StatusCode.InvalidArgument, error));
+ if (!_pendingRequests.TryRemove((connection, response.RequestId), out var completion))
+ {
+ _logger.LogWarning("Received response for unknown request.");
+ return;
+ }
+ // Complete the request.
+ completion.SetResult(response);
}
- private async ValueTask RegisterAgentTypeAsync(GrpcWorkerConnection connection, RegisterAgentTypeRequest msg)
- {
- connection.AddSupportedType(msg.Type);
- _supportedAgentTypes.GetOrAdd(msg.Type, _ => []).Add(connection);
- _agentsToEventsMap.TryAdd(msg.Type, new HashSet(msg.Events));
-
- await _gatewayRegistry.RegisterAgentType(msg.Type, _reference).ConfigureAwait(true);
- }
- private async ValueTask DispatchEventAsync(CloudEvent evt)
- {
- await BroadcastEvent(evt).ConfigureAwait(false);
- /*
- var topic = _clusterClient.GetStreamProvider("agents").GetStream(StreamId.Create(evt.Namespace, evt.Type));
- await topic.OnNextAsync(evt.ToEvent());
- */
- }
private async ValueTask DispatchRequestAsync(GrpcWorkerConnection connection, RpcRequest request)
{
var requestId = request.RequestId;
@@ -151,6 +138,24 @@ await InvokeRequestDelegate(connection, request, async request =>
//}
}
+ private async ValueTask DispatchEventAsync(CloudEvent evt)
+ {
+ await BroadcastEvent(evt).ConfigureAwait(false);
+ /*
+ var topic = _clusterClient.GetStreamProvider("agents").GetStream(StreamId.Create(evt.Namespace, evt.Type));
+ await topic.OnNextAsync(evt.ToEvent());
+ */
+ }
+
+ private async ValueTask RegisterAgentTypeAsync(GrpcWorkerConnection connection, RegisterAgentTypeRequest msg)
+ {
+ connection.AddSupportedType(msg.Type);
+ _supportedAgentTypes.GetOrAdd(msg.Type, _ => []).Add(connection);
+ _agentsToEventsMap.TryAdd(msg.Type, new HashSet(msg.Events));
+
+ await _gatewayRegistry.RegisterAgentType(msg.Type, _reference).ConfigureAwait(true);
+ }
+
private static async Task InvokeRequestDelegate(GrpcWorkerConnection connection, RpcRequest request, Func> func)
{
try
@@ -164,13 +169,7 @@ private static async Task InvokeRequestDelegate(GrpcWorkerConnection connection,
await connection.ResponseStream.WriteAsync(new Message { Response = new RpcResponse { RequestId = request.RequestId, Error = ex.Message } }).ConfigureAwait(false);
}
}
- internal Task ConnectToWorkerProcess(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context)
- {
- _logger.LogInformation("Received new connection from {Peer}.", context.Peer);
- var workerProcess = new GrpcWorkerConnection(this, requestStream, responseStream, context);
- _workers[workerProcess] = workerProcess;
- return workerProcess.Completion;
- }
+
public async ValueTask StoreAsync(AgentState value)
{
var agentId = value.AgentId ?? throw new ArgumentNullException(nameof(value.AgentId));
@@ -205,6 +204,7 @@ internal void OnRemoveWorkerProcess(GrpcWorkerConnection workerProcess)
}
}
}
+
public async ValueTask InvokeRequest(RpcRequest request, CancellationToken cancellationToken = default)
{
var agentId = (request.Target.Type, request.Target.Key);
@@ -233,8 +233,13 @@ public async ValueTask InvokeRequest(RpcRequest request, Cancellati
return response;
}
- async ValueTask IGateway.InvokeRequest(RpcRequest request)
+ public ValueTask RegisterAgentTypeAsync(RegisterAgentTypeRequest request)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ValueTask InvokeRequest(RpcRequest request)
{
- return await InvokeRequest(request).ConfigureAwait(false);
+ throw new NotImplementedException();
}
}
diff --git a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/GrpcGatewayService.cs b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/GrpcGatewayService.cs
index a2985c95f7bb..16e63e16bb93 100644
--- a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/GrpcGatewayService.cs
+++ b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/GrpcGatewayService.cs
@@ -43,4 +43,16 @@ public override async Task SaveState(AgentState request, Serv
Success = true // TODO: Implement error handling
};
}
+
+ public override Task AddSubscription(AddSubscriptionRequest request, ServerCallContext context)
+ {
+ // TODO: This should map to Orleans Streaming explicit api
+ return base.AddSubscription(request, context);
+ }
+
+ public override async Task RegisterAgent(RegisterAgentTypeRequest request, ServerCallContext context)
+ {
+ // TODO: This should add the agent to registry
+ return await Gateway.RegisterAgentTypeAsync(request);
+ }
}
diff --git a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/AgentWorkerHostingExtensions.cs b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/GrpcRuntimeHostingExtensions.cs
similarity index 51%
rename from dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/AgentWorkerHostingExtensions.cs
rename to dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/GrpcRuntimeHostingExtensions.cs
index 4c3c889ca9d6..bfb67f39281d 100644
--- a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/AgentWorkerHostingExtensions.cs
+++ b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/GrpcRuntimeHostingExtensions.cs
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
-// AgentWorkerHostingExtensions.cs
+// GrpcRuntimeHostingExtensions.cs
using System.Diagnostics;
using Microsoft.AspNetCore.Builder;
@@ -11,30 +11,28 @@
namespace Microsoft.AutoGen.Runtime.Grpc;
-public static class AgentWorkerHostingExtensions
+public static class GrpcRuntimeHostingExtensions
{
- public static WebApplicationBuilder AddAgentService(this WebApplicationBuilder builder, bool inMemoryOrleans = false, bool useGrpc = true)
+ public static WebApplicationBuilder AddGrpcRuntime(this WebApplicationBuilder builder, bool inMemoryOrleans = false)
{
+ // TODO: allow for configuration of Orleans, for state and streams
builder.AddOrleans(inMemoryOrleans);
builder.Services.TryAddSingleton(DistributedContextPropagator.Current);
- if (useGrpc)
+ builder.WebHost.ConfigureKestrel(serverOptions =>
{
- builder.WebHost.ConfigureKestrel(serverOptions =>
+ // TODO: make port configurable
+ serverOptions.ListenAnyIP(5001, listenOptions =>
{
- // TODO: make port configurable
- serverOptions.ListenAnyIP(5001, listenOptions =>
- {
- listenOptions.Protocols = HttpProtocols.Http2;
- listenOptions.UseHttps();
- });
+ listenOptions.Protocols = HttpProtocols.Http2;
+ listenOptions.UseHttps();
});
+ });
- builder.Services.AddGrpc();
- builder.Services.AddSingleton();
- builder.Services.AddSingleton(sp => (IHostedService)sp.GetRequiredService());
- }
+ builder.Services.AddGrpc();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton(sp => (IHostedService)sp.GetRequiredService());
return builder;
}
diff --git a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/IGateway.cs b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/IGateway.cs
index 16784b64fcc9..9ea0fdb076fd 100644
--- a/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/IGateway.cs
+++ b/dotnet/src/Microsoft.AutoGen/Microsoft.AutoGen.Runtime.Grpc/IGateway.cs
@@ -11,4 +11,5 @@ public interface IGateway : IGrainObserver
ValueTask BroadcastEvent(CloudEvent evt);
ValueTask StoreAsync(AgentState value);
ValueTask ReadAsync(AgentId agentId);
+ ValueTask RegisterAgentTypeAsync(RegisterAgentTypeRequest request);
}
diff --git a/dotnet/src/Microsoft.AutoGen/Microsoft.Autogen.AgentHost/Program.cs b/dotnet/src/Microsoft.AutoGen/Microsoft.Autogen.AgentHost/Program.cs
index 4c406429a9a2..01e08410cff1 100644
--- a/dotnet/src/Microsoft.AutoGen/Microsoft.Autogen.AgentHost/Program.cs
+++ b/dotnet/src/Microsoft.AutoGen/Microsoft.Autogen.AgentHost/Program.cs
@@ -6,7 +6,7 @@
var builder = WebApplication.CreateBuilder(args);
-builder.AddAgentService(inMemoryOrleans: true, useGrpc: true);
+builder.AddGrpcRuntime(inMemoryOrleans: true);
var app = builder.Build();
diff --git a/dotnet/test/Microsoft.AutoGen.Core.Tests/HandleInterfaceTest.cs b/dotnet/test/Microsoft.AutoGen.Core.Tests/HandleInterfaceTests.cs
similarity index 93%
rename from dotnet/test/Microsoft.AutoGen.Core.Tests/HandleInterfaceTest.cs
rename to dotnet/test/Microsoft.AutoGen.Core.Tests/HandleInterfaceTests.cs
index 14694543f196..8cf74a74bf3b 100644
--- a/dotnet/test/Microsoft.AutoGen.Core.Tests/HandleInterfaceTest.cs
+++ b/dotnet/test/Microsoft.AutoGen.Core.Tests/HandleInterfaceTests.cs
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
-// HandleInterfaceTest.cs
+// HandleInterfaceTests.cs
using FluentAssertions;
using Tests.Events;
@@ -7,7 +7,7 @@
namespace Microsoft.AutoGen.Core.Tests;
-public class HandleInterfaceTest
+public class HandleInterfaceTests
{
[Fact]
public void Can_Get_Handler_Methods_From_Class()
diff --git a/dotnet/test/Microsoft.AutoGen.Core.Tests/ClusterFixtureCollection.cs b/dotnet/test/Microsoft.AutoGen.Core.Tests/Helpers/ClusterFixtureCollection.cs
similarity index 86%
rename from dotnet/test/Microsoft.AutoGen.Core.Tests/ClusterFixtureCollection.cs
rename to dotnet/test/Microsoft.AutoGen.Core.Tests/Helpers/ClusterFixtureCollection.cs
index 4981d779904f..5f643410d8be 100644
--- a/dotnet/test/Microsoft.AutoGen.Core.Tests/ClusterFixtureCollection.cs
+++ b/dotnet/test/Microsoft.AutoGen.Core.Tests/Helpers/ClusterFixtureCollection.cs
@@ -3,7 +3,7 @@
using Xunit;
-namespace Microsoft.AutoGen.Core.Tests;
+namespace Microsoft.AutoGen.Core.Tests.Helpers;
[CollectionDefinition(Name)]
public sealed class ClusterFixtureCollection : ICollectionFixture
diff --git a/dotnet/test/Microsoft.AutoGen.Core.Tests/InMemoryAgentRuntimeFixture.cs b/dotnet/test/Microsoft.AutoGen.Core.Tests/Helpers/InMemoryAgentRuntimeFixture.cs
similarity index 96%
rename from dotnet/test/Microsoft.AutoGen.Core.Tests/InMemoryAgentRuntimeFixture.cs
rename to dotnet/test/Microsoft.AutoGen.Core.Tests/Helpers/InMemoryAgentRuntimeFixture.cs
index abf5dcadfc52..66d54c938840 100644
--- a/dotnet/test/Microsoft.AutoGen.Core.Tests/InMemoryAgentRuntimeFixture.cs
+++ b/dotnet/test/Microsoft.AutoGen.Core.Tests/Helpers/InMemoryAgentRuntimeFixture.cs
@@ -8,7 +8,7 @@
using Microsoft.Extensions.Logging;
using Moq;
-namespace Microsoft.AutoGen.Core.Tests;
+namespace Microsoft.AutoGen.Core.Tests.Helpers;
public sealed class InMemoryAgentRuntimeFixture : IDisposable
{
diff --git a/dotnet/test/Microsoft.AutoGen.Core.Tests/InMemoryAgentTests.cs b/dotnet/test/Microsoft.AutoGen.Core.Tests/InMemoryAgentTests.cs
index 12ea850566cb..7e71342fc71d 100644
--- a/dotnet/test/Microsoft.AutoGen.Core.Tests/InMemoryAgentTests.cs
+++ b/dotnet/test/Microsoft.AutoGen.Core.Tests/InMemoryAgentTests.cs
@@ -4,6 +4,7 @@
using FluentAssertions;
using Google.Protobuf.Reflection;
using Microsoft.AutoGen.Abstractions;
+using Microsoft.AutoGen.Core.Tests.Helpers;
using Microsoft.Extensions.DependencyInjection;
using Tests.Events;
using Xunit;
diff --git a/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Class1.cs b/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Class1.cs
deleted file mode 100644
index 59d7f60b7172..000000000000
--- a/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Class1.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Class1.cs
-
-namespace Microsoft.AutoGen.Runtime.Grpc.Tests;
-
-public class Class1
-{
-
-}
diff --git a/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/GrpcGatewayTests.cs b/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/GrpcGatewayTests.cs
new file mode 100644
index 000000000000..5ef8ce9b04de
--- /dev/null
+++ b/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/GrpcGatewayTests.cs
@@ -0,0 +1,119 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// GrpcGatewayTests.cs
+
+using Microsoft.AutoGen.Abstractions;
+using Microsoft.AutoGen.Runtime.Grpc.Tests.Helpers;
+using Microsoft.Extensions.Logging;
+using Moq;
+
+namespace Microsoft.AutoGen.Runtime.Grpc.Tests;
+
+[Collection(ClusterCollection.Name)]
+public class GrpcGatewayTests
+{
+ private readonly ClusterFixture _fixture;
+
+ public GrpcGatewayTests(ClusterFixture fixture)
+ {
+ _fixture = fixture;
+ }
+ // Test broadcast Event
+ [Fact]
+ public async Task TestBroadcastEvent()
+ {
+ var logger = Mock.Of>();
+ var gateway = new GrpcGateway(_fixture.Cluster.Client, logger);
+ var evt = new CloudEvent {
+ Type = "TestType",
+ };
+
+ // 1. Register Agent
+ // 2. Broadcast Event
+ // 3.
+ await gateway.BroadcastEvent(evt);
+ //var registry = fixture.Registry;
+ //var subscriptions = fixture.Subscriptions;
+ //var gateway = new Gateway(registry, subscriptions);
+ //var agentId = new AgentId(1, "TestAgent");
+ //var worker = new GatewayWorker(agentId, gateway);
+ //await registry.AddWorker(worker);
+ //var agentType = "TestAgent";
+ //var topic = "TestTopic";
+ //await subscriptions.Subscribe(agentType, topic);
+ //var message = new Message(agentId, topic, new byte[] { 1, 2, 3 });
+ //await gateway.BroadcastEvent(message);
+ //var receivedMessage = await worker.ReceiveMessage();
+ //Assert.Equal(message, receivedMessage);
+ //await registry.RemoveWorker(worker);
+ }
+
+ // Test StoreAsync
+ [Fact]
+ public async Task TestStoreAsync()
+ {
+ var logger = Mock.Of>();
+ var gateway = new GrpcGateway(_fixture.Cluster.Client, logger);
+ var agentState = new AgentState
+ {
+ AgentId = new AgentId
+ {
+ Type = "TestType",
+ Key = "TestKey",
+ },
+ };
+ await gateway.StoreAsync(agentState);
+ //var registry = fixture.Registry;
+ //var gateway = new Gateway(registry, subscriptions);
+ //var agentId = new AgentId(1, "TestAgent");
+ //var worker = new GatewayWorker(agentId, gateway);
+ //await registry.AddWorker(worker);
+ //var agentState = new AgentState(agentId, new byte[] { 1, 2, 3 });
+ //await gateway.StoreAsync(agentState);
+ //var receivedAgentState = await worker.ReceiveState();
+ //Assert.Equal(agentState, receivedAgentState);
+ //await registry.RemoveWorker(worker);
+ }
+
+ // Test ReadAsync
+ [Fact]
+ public async Task TestReadAsync()
+ {
+ var logger = Mock.Of>();
+ var gateway = new GrpcGateway(_fixture.Cluster.Client, logger);
+ var agentId = new AgentId
+ {
+ Type = "TestType",
+ Key = "TestKey",
+ };
+ var _ = await gateway.ReadAsync(agentId);
+ //var registry = fixture.Registry;
+ //var gateway = new Gateway(registry, subscriptions);
+ //var agentId = new AgentId(1, "TestAgent");
+ //var worker = new GatewayWorker(agentId, gateway);
+ //await registry.AddWorker(worker);
+ //var agentState = new AgentState(agentId, new byte[] { 1, 2, 3 });
+ //await worker.SendState(agentState);
+ //var receivedAgentState = await gateway.ReadAsync(agentId);
+ //Assert.Equal(agentState, receivedAgentState);
+ //await registry.RemoveWorker(worker);
+ }
+
+ // Test RegisterAgentTypeAsync
+ [Fact]
+ public async Task TestRegisterAgentTypeAsync()
+ {
+ var logger = Mock.Of>();
+ var gateway = new GrpcGateway(_fixture.Cluster.Client, logger);
+ var request = new RegisterAgentTypeRequest
+ {
+ Type = "TestType",
+ };
+ var _ = await gateway.RegisterAgentTypeAsync(request);
+ //var registry = fixture.Registry;
+ //var gateway = new Gateway(registry, subscriptions);
+ //var agentType = "TestAgent";
+ //var request = new RegisterAgentTypeRequest(agentType);
+ //var response = await gateway.RegisterAgentTypeAsync(request);
+ //Assert.Equal(agentType, response.AgentType);
+ }
+}
diff --git a/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Helpers/ClusterCollection.cs b/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Helpers/ClusterCollection.cs
new file mode 100644
index 000000000000..3493ba1d58fa
--- /dev/null
+++ b/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Helpers/ClusterCollection.cs
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ClusterCollection.cs
+
+namespace Microsoft.AutoGen.Runtime.Grpc.Tests.Helpers;
+
+[CollectionDefinition(Name)]
+public sealed class ClusterCollection : ICollectionFixture
+{
+ public const string Name = nameof(ClusterCollection);
+}
diff --git a/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Helpers/ClusterFixture.cs b/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Helpers/ClusterFixture.cs
new file mode 100644
index 000000000000..f3a3cf2ccf40
--- /dev/null
+++ b/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Helpers/ClusterFixture.cs
@@ -0,0 +1,15 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ClusterFixture.cs
+
+using Orleans.TestingHost;
+
+namespace Microsoft.AutoGen.Runtime.Grpc.Tests.Helpers;
+
+public sealed class ClusterFixture : IDisposable
+{
+ public TestCluster Cluster { get; } = new TestClusterBuilder().Build();
+
+ public ClusterFixture() => Cluster.Deploy();
+
+ void IDisposable.Dispose() => Cluster.StopAllSilos();
+}
diff --git a/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Microsoft.AutoGen.Runtime.Grpc.Tests.csproj b/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Microsoft.AutoGen.Runtime.Grpc.Tests.csproj
index 80fccfe5e9a2..0a0df26b158a 100644
--- a/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Microsoft.AutoGen.Runtime.Grpc.Tests.csproj
+++ b/dotnet/test/Microsoft.AutoGen.Runtime.Grpc.Tests/Microsoft.AutoGen.Runtime.Grpc.Tests.csproj
@@ -7,6 +7,11 @@
True
+
+
+
+
+