From c197f946318ee3c7194c0ddb78d3cec5779f30f4 Mon Sep 17 00:00:00 2001 From: Erik Simon Date: Sat, 4 Apr 2026 05:01:51 +0200 Subject: [PATCH] Fixed some warnings --- Luna.Agents/Librarian/LibrarianAgent.cs | 5 +- .../ChannelManagerInterfaceTests.cs | 13 ++- Luna.Channels.Tests/CliChannelTests.cs | 1 - .../DependencyInjectionTests.cs | 40 +++---- Luna.Channels.Tests/IntegrationTests.cs | 82 +++++++------- .../Stubs/ChannelManagerStub.cs | 2 +- Luna.Channels.Tests/TelegramChannelTests.cs | 100 +++++++++--------- Luna.Channels/Telegram/TelegramChannel.cs | 3 +- Luna.Clients.Cli/ChatClientService.cs | 2 - .../ConfigurationBuilderExtensions.cs | 4 +- Luna.Core/Session/SessionManager.cs | 3 +- .../Extensions/ServiceCollectionExtensions.cs | 5 +- 12 files changed, 129 insertions(+), 131 deletions(-) diff --git a/Luna.Agents/Librarian/LibrarianAgent.cs b/Luna.Agents/Librarian/LibrarianAgent.cs index 902ba66..df162a7 100644 --- a/Luna.Agents/Librarian/LibrarianAgent.cs +++ b/Luna.Agents/Librarian/LibrarianAgent.cs @@ -1,3 +1,4 @@ +using System.Runtime.CompilerServices; using Luna.Agents.Abstractions; using Luna.Configuration; using Luna.Providers.Abstractions; @@ -38,7 +39,9 @@ public class LibrarianAgent( .Where(m => m.Role != ChatRole.System); } - public async IAsyncEnumerable ProcessStreamingAsync(IReadOnlyList messages, CancellationToken ct = default) + public async IAsyncEnumerable ProcessStreamingAsync( + IReadOnlyList messages, + [EnumeratorCancellation] CancellationToken ct = default) { var chatOptions = new ChatOptions { diff --git a/Luna.Channels.Tests/ChannelManagerInterfaceTests.cs b/Luna.Channels.Tests/ChannelManagerInterfaceTests.cs index 2a1adc6..0fbefb0 100644 --- a/Luna.Channels.Tests/ChannelManagerInterfaceTests.cs +++ b/Luna.Channels.Tests/ChannelManagerInterfaceTests.cs @@ -1,5 +1,4 @@ using Luna.Channels.Abstractions; -using Luna.Channels.Tests.Stubs; using Luna.Core.Abstractions; using Luna.Shared; using Microsoft.Extensions.Logging; @@ -95,7 +94,7 @@ public class ChannelManagerInterfaceTests stub.RegisterChannel(mockChannel.Object); - var message = new ChannelMessage( + var _ = new ChannelMessage( Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "sender-1", @@ -103,11 +102,11 @@ public class ChannelManagerInterfaceTests "Hello", DateTimeOffset.UtcNow); - var eventArgs = new ChannelMessageReceivedEventArgs - { - Message = message, - Channel = mockChannel.Object - }; + // var eventArgs = new ChannelMessageReceivedEventArgs + // { + // Message = message, + // Channel = mockChannel.Object + // }; Assert.That(capturedArgs, Is.Not.Null); } diff --git a/Luna.Channels.Tests/CliChannelTests.cs b/Luna.Channels.Tests/CliChannelTests.cs index 6b741ff..7afaed2 100644 --- a/Luna.Channels.Tests/CliChannelTests.cs +++ b/Luna.Channels.Tests/CliChannelTests.cs @@ -1,6 +1,5 @@ using Luna.Channels.Abstractions; using Luna.Channels.Cli; -using Luna.Channels.Tests.Stubs; using Luna.Core.Abstractions; using Luna.Shared; using Moq; diff --git a/Luna.Channels.Tests/DependencyInjectionTests.cs b/Luna.Channels.Tests/DependencyInjectionTests.cs index cc98f76..210cfb0 100644 --- a/Luna.Channels.Tests/DependencyInjectionTests.cs +++ b/Luna.Channels.Tests/DependencyInjectionTests.cs @@ -10,21 +10,21 @@ namespace Luna.Channels.Tests; [Category("Unit")] public class DependencyInjectionTests { - private ServiceCollection _services = null!; + private ServiceCollection services = null!; [SetUp] public void SetUp() { - _services = new ServiceCollection(); + services = []; } [Test] public void AddChannels_RegistersIChannelManager_AsSingleton() { - _services.AddChannels(); - var provider = _services.BuildServiceProvider(); + services.AddChannels(); + // var provider = services.BuildServiceProvider(); - var descriptor = _services.FirstOrDefault(d => d.ServiceType == typeof(IChannelManager)); + var descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(IChannelManager)); Assert.That(descriptor, Is.Not.Null); Assert.That(descriptor!.Lifetime, Is.EqualTo(ServiceLifetime.Singleton)); @@ -33,8 +33,8 @@ public class DependencyInjectionTests [Test] public void AddChannels_IChannelManager_IsResolvableFromContainer() { - _services.AddChannels(); - var provider = _services.BuildServiceProvider(); + services.AddChannels(); + var provider = services.BuildServiceProvider(); var manager = provider.GetService(); @@ -44,10 +44,10 @@ public class DependencyInjectionTests [Test] public void AddChannels_TelegramOptions_IsRegistered() { - _services.AddChannels(); - var provider = _services.BuildServiceProvider(); + services.AddChannels(); + // var provider = services.BuildServiceProvider(); - var descriptor = _services.FirstOrDefault(d => + var descriptor = services.FirstOrDefault(d => d.ServiceType.IsGenericType && d.ServiceType.GetGenericTypeDefinition() == typeof(IOptions<>) && d.ServiceType.GetGenericArguments()[0] == typeof(TelegramOptions)); @@ -59,8 +59,8 @@ public class DependencyInjectionTests [Test] public void AddChannels_CliChannel_IsRegistered() { - _services.AddChannels(); - var provider = _services.BuildServiceProvider(); + services.AddChannels(); + var provider = services.BuildServiceProvider(); var channels = provider.GetServices().ToList(); var channelTypes = channels.Select(c => c.ChannelType).ToList(); @@ -72,8 +72,8 @@ public class DependencyInjectionTests [Test] public void AddChannels_TelegramChannel_IsRegistered() { - _services.AddChannels(); - var provider = _services.BuildServiceProvider(); + services.AddChannels(); + var provider = services.BuildServiceProvider(); var channels = provider.GetServices().ToList(); var channelTypes = channels.Select(c => c.ChannelType).ToList(); @@ -85,11 +85,11 @@ public class DependencyInjectionTests [Test] public void AddChannels_CalledTwice_DoesNotDuplicateSingletonRegistration() { - _services.AddChannels(); - _services.AddChannels(); - var provider = _services.BuildServiceProvider(); + services.AddChannels(); + services.AddChannels(); + //var provider = services.BuildServiceProvider(); - var descriptors = _services.Where(d => d.ServiceType == typeof(IChannelManager)).ToList(); + var descriptors = services.Where(d => d.ServiceType == typeof(IChannelManager)).ToList(); Assert.That(descriptors, Has.Count.EqualTo(1), "Calling AddChannels() twice must not register IChannelManager twice"); @@ -98,8 +98,8 @@ public class DependencyInjectionTests [Test] public void AddChannels_SameProviderInstance_ReturnsSameIChannelManager() { - _services.AddChannels(); - var provider = _services.BuildServiceProvider(); + services.AddChannels(); + var provider = services.BuildServiceProvider(); var first = provider.GetRequiredService(); var second = provider.GetRequiredService(); diff --git a/Luna.Channels.Tests/IntegrationTests.cs b/Luna.Channels.Tests/IntegrationTests.cs index 2dd7173..3e2fce2 100644 --- a/Luna.Channels.Tests/IntegrationTests.cs +++ b/Luna.Channels.Tests/IntegrationTests.cs @@ -10,21 +10,21 @@ namespace Luna.Channels.Tests; [Category("Unit")] public class IntegrationTests { - private Mock _sessionManagerMock = null!; - private Mock _channelMock = null!; - private ChannelManagerStub _manager = null!; + private Mock sessionManagerMock = null!; + private Mock channelMock = null!; + private ChannelManagerStub manager = null!; [SetUp] public void SetUp() { - _sessionManagerMock = new Mock(); - _channelMock = new Mock(); - _channelMock.Setup(c => c.ChannelId).Returns("test-ch-1"); - _channelMock.Setup(c => c.ChannelType).Returns("test"); - _channelMock.Setup(c => c.SendStreamingMessageAsync( + sessionManagerMock = new Mock(); + channelMock = new Mock(); + channelMock.Setup(c => c.ChannelId).Returns("test-ch-1"); + channelMock.Setup(c => c.ChannelType).Returns("test"); + channelMock.Setup(c => c.SendStreamingMessageAsync( It.IsAny>(), It.IsAny())).Returns(Task.CompletedTask); - _manager = new ChannelManagerStub(_sessionManagerMock.Object); + manager = new ChannelManagerStub(sessionManagerMock.Object); } private static async IAsyncEnumerable BuildStream(params ChatStreamUpdate[] updates) @@ -42,24 +42,24 @@ public class IntegrationTests var message = new ChannelMessage( Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "user-1", "User One", "Hello Luna!", DateTimeOffset.UtcNow); - _sessionManagerMock + sessionManagerMock .Setup(s => s.RouteMessagesAsync( message.Content, - message.ConversationId.ToString(), + message.ConversationId, It.IsAny(), It.IsAny())) .Returns(BuildStream(new ChatStreamUpdate(ChatStreamUpdateType.Text, "Hi!", null, false))); - _manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); + manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); - var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = _channelMock.Object }; - _channelMock.Raise(c => c.MessageReceived += null, _channelMock.Object, args); + var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = channelMock.Object }; + channelMock.Raise(c => c.MessageReceived += null, channelMock.Object, args); await Task.Delay(50); - _sessionManagerMock.Verify(s => s.RouteMessagesAsync( + sessionManagerMock.Verify(s => s.RouteMessagesAsync( message.Content, - message.ConversationId.ToString(), + message.ConversationId, It.IsAny(), It.IsAny()), Times.Once); } @@ -75,19 +75,19 @@ public class IntegrationTests new ChatStreamUpdate(ChatStreamUpdateType.Text, "noon.", null, false), new ChatStreamUpdate(ChatStreamUpdateType.Complete, null, null, true)); - _sessionManagerMock + sessionManagerMock .Setup(s => s.RouteMessagesAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(responseStream); - _manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); + manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); - var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = _channelMock.Object }; - _channelMock.Raise(c => c.MessageReceived += null, _channelMock.Object, args); + var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = channelMock.Object }; + channelMock.Raise(c => c.MessageReceived += null, channelMock.Object, args); await Task.Delay(50); - _channelMock.Verify(c => c.SendStreamingMessageAsync( + channelMock.Verify(c => c.SendStreamingMessageAsync( It.IsAny>(), It.IsAny()), Times.Once); } @@ -98,14 +98,14 @@ public class IntegrationTests var message = new ChannelMessage( Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "user-3", "User Three", "/start", DateTimeOffset.UtcNow); - _manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); + manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); - var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = _channelMock.Object, IsHandled = true }; - _channelMock.Raise(c => c.MessageReceived += null, _channelMock.Object, args); + var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = channelMock.Object, IsHandled = true }; + channelMock.Raise(c => c.MessageReceived += null, channelMock.Object, args); await Task.Delay(50); - _sessionManagerMock.Verify(s => s.RouteMessagesAsync( + sessionManagerMock.Verify(s => s.RouteMessagesAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } @@ -120,25 +120,25 @@ public class IntegrationTests It.IsAny>(), It.IsAny())) .Returns(Task.CompletedTask); - _sessionManagerMock + sessionManagerMock .Setup(s => s.RouteMessagesAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(BuildStream(new ChatStreamUpdate(ChatStreamUpdateType.Text, "ok", null, true))); - _manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); - _manager.RegisterChannel(channel2Mock.Object); + manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); + manager.RegisterChannel(channel2Mock.Object); var msg1 = new ChannelMessage(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "u1", "U1", "Msg1", DateTimeOffset.UtcNow); var msg2 = new ChannelMessage(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "u2", "U2", "Msg2", DateTimeOffset.UtcNow); - _channelMock.Raise(c => c.MessageReceived += null, _channelMock.Object, - new ChannelMessageReceivedEventArgs { Message = msg1, Channel = _channelMock.Object }); + channelMock.Raise(c => c.MessageReceived += null, channelMock.Object, + new ChannelMessageReceivedEventArgs { Message = msg1, Channel = channelMock.Object }); channel2Mock.Raise(c => c.MessageReceived += null, channel2Mock.Object, new ChannelMessageReceivedEventArgs { Message = msg2, Channel = channel2Mock.Object }); await Task.Delay(100); - _sessionManagerMock.Verify(s => s.RouteMessagesAsync( + sessionManagerMock.Verify(s => s.RouteMessagesAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); } @@ -150,21 +150,21 @@ public class IntegrationTests var message = new ChannelMessage( Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "user-4", "User Four", "Cancel me", DateTimeOffset.UtcNow); - _sessionManagerMock + sessionManagerMock .Setup(s => s.RouteMessagesAsync( It.IsAny(), It.IsAny(), It.IsAny(), cts.Token)) .Returns(BuildStream(new ChatStreamUpdate(ChatStreamUpdateType.Text, "x", null, true))); - _manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); + manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); - var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = _channelMock.Object }; - await _channelMock.RaiseAsync(c => c.MessageReceived += null, _channelMock.Object, args); + var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = channelMock.Object }; + await channelMock.RaiseAsync(c => c.MessageReceived += null, channelMock.Object, args); await Task.Delay(50, cts.Token); - _sessionManagerMock.Verify(s => s.RouteMessagesAsync( + sessionManagerMock.Verify(s => s.RouteMessagesAsync( message.Content, - message.ConversationId.ToString(), + message.ConversationId, It.IsAny(), It.IsAny()), Times.Once); } @@ -175,17 +175,17 @@ public class IntegrationTests var message = new ChannelMessage( Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "user-5", "User Five", "Boom", DateTimeOffset.UtcNow); - _sessionManagerMock + sessionManagerMock .Setup(s => s.RouteMessagesAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Throws(new InvalidOperationException("Simulated routing failure")); - _manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); + manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" }); Assert.DoesNotThrowAsync(async () => { - var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = _channelMock.Object }; - await _channelMock.RaiseAsync(c => c.MessageReceived += null, _channelMock.Object, args); + var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = channelMock.Object }; + await channelMock.RaiseAsync(c => c.MessageReceived += null, channelMock.Object, args); await Task.Delay(50); }); } diff --git a/Luna.Channels.Tests/Stubs/ChannelManagerStub.cs b/Luna.Channels.Tests/Stubs/ChannelManagerStub.cs index cf495e3..4066f00 100644 --- a/Luna.Channels.Tests/Stubs/ChannelManagerStub.cs +++ b/Luna.Channels.Tests/Stubs/ChannelManagerStub.cs @@ -14,7 +14,7 @@ public class ChannelManagerStub : IChannelManager public void UnregisterChannel(string channelId) => throw new NotImplementedException(); - public IChannel? GetChannel(string channelId) => throw new NotImplementedException(); + public IChannel GetChannel(string channelId) => throw new NotImplementedException(); public IReadOnlyList GetAllChannels() => throw new NotImplementedException(); } diff --git a/Luna.Channels.Tests/TelegramChannelTests.cs b/Luna.Channels.Tests/TelegramChannelTests.cs index cf2ebc9..44b4884 100644 --- a/Luna.Channels.Tests/TelegramChannelTests.cs +++ b/Luna.Channels.Tests/TelegramChannelTests.cs @@ -14,43 +14,43 @@ namespace Luna.Channels.Tests; [Category("Unit")] public class TelegramChannelTests { - private Mock _mockBotClient = null!; - private Mock> _mockLogger = null!; - private TelegramOptions _options = null!; - private TelegramChannel _channel = null!; + private Mock mockBotClient = null!; + private Mock> mockLogger = null!; + private TelegramOptions options = null!; + private TelegramChannel channel = null!; [SetUp] public void SetUp() { - _mockBotClient = new Mock(); - _mockLogger = new Mock>(); - _options = new TelegramOptions { BotToken = "test-bot-token:ABCDEF" }; - _channel = new TelegramChannel("100", _mockBotClient.Object, _mockLogger.Object, _options); + mockBotClient = new Mock(); + mockLogger = new Mock>(); + options = new TelegramOptions { BotToken = "test-bot-token:ABCDEF" }; + channel = new TelegramChannel("100", mockBotClient.Object, mockLogger.Object, options); } [TearDown] public void TearDown() { - _channel.Dispose(); + channel.Dispose(); } [Test] public void ChannelType_Returns_Telegram() { - Assert.That(_channel.ChannelType, Is.EqualTo("telegram")); + Assert.That(channel.ChannelType, Is.EqualTo("telegram")); } [Test] public void ChannelId_IsSet_From_Constructor() { - Assert.That(_channel.ChannelId, Is.EqualTo("100")); + Assert.That(channel.ChannelId, Is.EqualTo("100")); } [Test] public void ChannelId_IsUnique_Per_Instance() { - var channel1 = new TelegramChannel("111", _mockBotClient.Object, _mockLogger.Object, _options); - var channel2 = new TelegramChannel("222", _mockBotClient.Object, _mockLogger.Object, _options); + var channel1 = new TelegramChannel("111", mockBotClient.Object, mockLogger.Object, options); + var channel2 = new TelegramChannel("222", mockBotClient.Object, mockLogger.Object, options); Assert.That(channel1.ChannelId, Is.Not.EqualTo(channel2.ChannelId)); @@ -61,36 +61,36 @@ public class TelegramChannelTests [Test] public void DisplayName_Contains_Telegram() { - Assert.That(_channel.DisplayName, Does.Contain("Telegram")); + Assert.That(channel.DisplayName, Does.Contain("Telegram")); } [Test] public void IsConnected_Is_True_Initially() { - Assert.That(_channel.IsConnected, Is.True); + Assert.That(channel.IsConnected, Is.True); } [Test] public void IsConnected_Is_False_After_Dispose() { - _channel.Dispose(); + channel.Dispose(); - Assert.That(_channel.IsConnected, Is.False); + Assert.That(channel.IsConnected, Is.False); } [Test] public async Task SendMessageAsync_Calls_BotClient_SendMessage() { - _mockBotClient + mockBotClient .Setup(c => c.SendRequest(It.IsAny(), It.IsAny())) .ReturnsAsync(new Message { Id = 1, Chat = new Chat { Id = 100 } }); var message = new ChannelMessage( Guid.NewGuid().ToString(), "100", "42", "Alice", "Hello!", DateTimeOffset.UtcNow); - await _channel.SendMessageAsync(message); + await channel.SendMessageAsync(message); - _mockBotClient.Verify( + mockBotClient.Verify( c => c.SendRequest(It.IsAny(), It.IsAny()), Times.Once); } @@ -98,33 +98,33 @@ public class TelegramChannelTests [Test] public async Task SendMessageAsync_Handles_Network_Error_Without_Crash() { - _mockBotClient + mockBotClient .Setup(c => c.SendRequest(It.IsAny(), It.IsAny())) .ThrowsAsync(new HttpRequestException("Network error")); var message = new ChannelMessage( Guid.NewGuid().ToString(), "100", "42", "Alice", "Hello!", DateTimeOffset.UtcNow); - Assert.DoesNotThrowAsync(async () => await _channel.SendMessageAsync(message)); + Assert.DoesNotThrowAsync(async () => await channel.SendMessageAsync(message)); } [Test] public void RaiseMessageReceived_Fires_Event_With_Correct_Mapping() { ChannelMessageReceivedEventArgs? captured = null; - _channel.MessageReceived += (_, args) => { captured = args; return Task.CompletedTask; }; + channel.MessageReceived += (_, args) => { captured = args; return Task.CompletedTask; }; var message = new ChannelMessage( Guid.NewGuid().ToString(), "999", "77", "Bob", "Hello Luna", DateTimeOffset.UtcNow); - _channel.RaiseMessageReceived(message); + channel.RaiseMessageReceived(message); Assert.That(captured, Is.Not.Null); Assert.That(captured!.Message.ConversationId, Is.EqualTo("999")); Assert.That(captured.Message.SenderId, Is.EqualTo("77")); Assert.That(captured.Message.SenderName, Is.EqualTo("Bob")); Assert.That(captured.Message.Content, Is.EqualTo("Hello Luna")); - Assert.That(captured.Channel, Is.SameAs(_channel)); + Assert.That(captured.Channel, Is.SameAs(channel)); } [Test] @@ -133,12 +133,12 @@ public class TelegramChannelTests var sentAt = new DateTimeOffset(2025, 6, 1, 12, 0, 0, TimeSpan.Zero); ChannelMessageReceivedEventArgs? captured = null; - _channel.MessageReceived += (_, args) => { captured = args; return Task.CompletedTask; }; + channel.MessageReceived += (_, args) => { captured = args; return Task.CompletedTask; }; var message = new ChannelMessage( Guid.NewGuid().ToString(), "123", "55", "Carol", "Hi", sentAt); - _channel.RaiseMessageReceived(message); + channel.RaiseMessageReceived(message); Assert.That(captured, Is.Not.Null); Assert.That(captured!.Message.SenderName, Is.EqualTo("Carol")); @@ -148,11 +148,11 @@ public class TelegramChannelTests [Test] public async Task SendStreamingMessageAsync_Sends_Initial_Then_Edits_In_Place() { - _mockBotClient + mockBotClient .Setup(c => c.SendRequest(It.IsAny(), It.IsAny())) .ReturnsAsync(new Message { Id = 10, Chat = new Chat { Id = 100 } }); - _mockBotClient + mockBotClient .Setup(c => c.SendRequest(It.IsAny(), It.IsAny())) .ReturnsAsync(new Message { Id = 10, Chat = new Chat { Id = 100 } }); @@ -163,14 +163,14 @@ public class TelegramChannelTests new(ChatStreamUpdateType.Complete, null, null, true), }; - await _channel.SendStreamingMessageAsync(updates.ToAsyncEnumerable()); + await channel.SendStreamingMessageAsync(updates.ToAsyncEnumerable()); // First chunk sends a message, second chunk edits it - _mockBotClient.Verify( + mockBotClient.Verify( c => c.SendRequest(It.IsAny(), It.IsAny()), Times.Once); - _mockBotClient.Verify( + mockBotClient.Verify( c => c.SendRequest(It.IsAny(), It.IsAny()), Times.AtLeastOnce); } @@ -185,18 +185,18 @@ public class TelegramChannelTests new(ChatStreamUpdateType.Complete, null, null, true), }; - _mockBotClient + mockBotClient .Setup(c => c.SendRequest(It.IsAny(), It.IsAny())) .ReturnsAsync(new Message { Id = 20, Chat = new Chat { Id = 100 } }); - _mockBotClient + mockBotClient .Setup(c => c.SendRequest(It.IsAny(), It.IsAny())) .ReturnsAsync(new Message { Id = 20, Chat = new Chat { Id = 100 } }); - await _channel.SendStreamingMessageAsync(updates.ToAsyncEnumerable()); + await channel.SendStreamingMessageAsync(updates.ToAsyncEnumerable()); // Content exceeds 4096 — needs at least 2 SendMessage calls (initial + overflow) - _mockBotClient.Verify( + mockBotClient.Verify( c => c.SendRequest(It.IsAny(), It.IsAny()), Times.AtLeast(2)); } @@ -204,11 +204,11 @@ public class TelegramChannelTests [Test] public async Task SendStreamingMessageAsync_Handles_IsComplete_True_With_Final_Edit() { - _mockBotClient + mockBotClient .Setup(c => c.SendRequest(It.IsAny(), It.IsAny())) .ReturnsAsync(new Message { Id = 30, Chat = new Chat { Id = 100 } }); - _mockBotClient + mockBotClient .Setup(c => c.SendRequest(It.IsAny(), It.IsAny())) .ReturnsAsync(new Message { Id = 30, Chat = new Chat { Id = 100 } }); @@ -218,10 +218,10 @@ public class TelegramChannelTests new(ChatStreamUpdateType.Complete, null, null, true), }; - await _channel.SendStreamingMessageAsync(updates.ToAsyncEnumerable()); + await channel.SendStreamingMessageAsync(updates.ToAsyncEnumerable()); // Initial message sent - _mockBotClient.Verify( + mockBotClient.Verify( c => c.SendRequest(It.IsAny(), It.IsAny()), Times.Once); } @@ -235,7 +235,7 @@ public class TelegramChannelTests AllowedUserIds = ["111", "222"] }; var restrictedChannel = new TelegramChannel( - "500", _mockBotClient.Object, _mockLogger.Object, restrictedOptions); + "500", mockBotClient.Object, mockLogger.Object, restrictedOptions); ChannelMessageReceivedEventArgs? captured = null; restrictedChannel.MessageReceived += (_, args) => { captured = args; return Task.CompletedTask; }; @@ -259,7 +259,7 @@ public class TelegramChannelTests AllowedUserIds = ["111", "222"] }; var restrictedChannel = new TelegramChannel( - "500", _mockBotClient.Object, _mockLogger.Object, restrictedOptions); + "500", mockBotClient.Object, mockLogger.Object, restrictedOptions); ChannelMessageReceivedEventArgs? captured = null; restrictedChannel.MessageReceived += (_, args) => { captured = args; return Task.CompletedTask; }; @@ -283,7 +283,7 @@ public class TelegramChannelTests AllowedUserIds = [] }; var openChannel = new TelegramChannel( - "600", _mockBotClient.Object, _mockLogger.Object, openOptions); + "600", mockBotClient.Object, mockLogger.Object, openOptions); ChannelMessageReceivedEventArgs? captured = null; openChannel.MessageReceived += (_, args) => { captured = args; return Task.CompletedTask; }; @@ -302,12 +302,12 @@ public class TelegramChannelTests public void Malformed_Message_With_Null_Text_Is_Skipped() { ChannelMessageReceivedEventArgs? captured = null; - _channel.MessageReceived += (_, args) => { captured = args; return Task.CompletedTask; }; + channel.MessageReceived += (_, args) => { captured = args; return Task.CompletedTask; }; var message = new ChannelMessage( Guid.NewGuid().ToString(), "700", "88", "Ghost", null!, DateTimeOffset.UtcNow); - _channel.RaiseMessageReceived(message); + channel.RaiseMessageReceived(message); Assert.That(captured, Is.Null, "Message with null text should be silently skipped"); } @@ -316,12 +316,12 @@ public class TelegramChannelTests public void Malformed_Message_With_Empty_Text_Is_Skipped() { ChannelMessageReceivedEventArgs? captured = null; - _channel.MessageReceived += (_, args) => { captured = args; return Task.CompletedTask; }; + channel.MessageReceived += (_, args) => { captured = args; return Task.CompletedTask; }; var message = new ChannelMessage( Guid.NewGuid().ToString(), "700", "88", "Ghost", "", DateTimeOffset.UtcNow); - _channel.RaiseMessageReceived(message); + channel.RaiseMessageReceived(message); Assert.That(captured, Is.Null, "Message with empty text should be silently skipped"); } @@ -330,16 +330,16 @@ public class TelegramChannelTests public void Dispose_Fires_ConnectionStateChanged() { ChannelConnectionEventArgs? captured = null; - _channel.ConnectionStateChanged += (_, args) => + channel.ConnectionStateChanged += (_, args) => { captured = args; return Task.CompletedTask; }; - _channel.Dispose(); + channel.Dispose(); Assert.That(captured, Is.Not.Null); Assert.That(captured!.IsConnected, Is.False); - Assert.That(captured.Channel, Is.SameAs(_channel)); + Assert.That(captured.Channel, Is.SameAs(channel)); } } diff --git a/Luna.Channels/Telegram/TelegramChannel.cs b/Luna.Channels/Telegram/TelegramChannel.cs index 40b18d1..346182d 100644 --- a/Luna.Channels/Telegram/TelegramChannel.cs +++ b/Luna.Channels/Telegram/TelegramChannel.cs @@ -42,10 +42,9 @@ public class TelegramChannel( CancellationToken cancellationToken = default) { var targetChatId = long.Parse(ChannelId); - int? currentMessageId = null; var typingCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - var typingTask = KeepTypingAsync(targetChatId, typingCts.Token); + var _ = KeepTypingAsync(targetChatId, typingCts.Token); var messageBuilder = new StringBuilder(); await foreach (var update in messageStream.WithCancellation(cancellationToken)) diff --git a/Luna.Clients.Cli/ChatClientService.cs b/Luna.Clients.Cli/ChatClientService.cs index 6bb9ebe..cdbb8e7 100644 --- a/Luna.Clients.Cli/ChatClientService.cs +++ b/Luna.Clients.Cli/ChatClientService.cs @@ -1,5 +1,3 @@ -using System.Text.Json; -using System.Text.Json.Serialization; using System.Threading.Channels; using Luna.Shared; using Microsoft.AspNetCore.SignalR.Client; diff --git a/Luna.Configuration/Extensions/ConfigurationBuilderExtensions.cs b/Luna.Configuration/Extensions/ConfigurationBuilderExtensions.cs index a346af3..65c6261 100644 --- a/Luna.Configuration/Extensions/ConfigurationBuilderExtensions.cs +++ b/Luna.Configuration/Extensions/ConfigurationBuilderExtensions.cs @@ -6,12 +6,12 @@ namespace Luna.Configuration.Extensions; public static class ConfigurationBuilderExtensions { - private static string[] AgentConfigSearchPaths = + private static readonly string[] AgentConfigSearchPaths = [ Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".luna", "agents") ]; - private static string[] ProviderConfigSearchPaths = + private static readonly string[] ProviderConfigSearchPaths = [ Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".luna", "providers") ]; diff --git a/Luna.Core/Session/SessionManager.cs b/Luna.Core/Session/SessionManager.cs index bd86ae6..b6b1225 100644 --- a/Luna.Core/Session/SessionManager.cs +++ b/Luna.Core/Session/SessionManager.cs @@ -1,5 +1,6 @@ using System.Collections.Concurrent; using System.Globalization; +using System.Runtime.CompilerServices; using System.Text; using Luna.Agents.Abstractions; using Luna.Core.Abstractions; @@ -31,7 +32,7 @@ public class SessionManager( string content, string conversationId, string connectionId, - CancellationToken ct = default) + [EnumeratorCancellation] CancellationToken ct = default) { if (!connectedClients.ContainsKey(connectionId)) connectedClients[connectionId] = conversationId; diff --git a/Luna.Providers/Extensions/ServiceCollectionExtensions.cs b/Luna.Providers/Extensions/ServiceCollectionExtensions.cs index f768310..ec28d50 100644 --- a/Luna.Providers/Extensions/ServiceCollectionExtensions.cs +++ b/Luna.Providers/Extensions/ServiceCollectionExtensions.cs @@ -19,9 +19,8 @@ public static class ServiceCollectionExtensions } /// - /// Registers the and maps to it as a singleton. + /// Registers the and maps to it as a singleton. /// - /// The service collection. /// The updated service collection. private IServiceCollection AddMistralProvider() { @@ -42,7 +41,7 @@ public static class ServiceCollectionExtensions } /// - /// Registers the and maps to it as a singleton. + /// Registers the and maps to it as a singleton. /// /// private IServiceCollection AddOllamaProvider()