diff --git a/Frontend/MainFE/Components/Models/AgentContextDto.cs b/Frontend/MainFE/Components/Models/AgentConfigDto.cs similarity index 92% rename from Frontend/MainFE/Components/Models/AgentContextDto.cs rename to Frontend/MainFE/Components/Models/AgentConfigDto.cs index 57760d89..dac5bf76 100644 --- a/Frontend/MainFE/Components/Models/AgentContextDto.cs +++ b/Frontend/MainFE/Components/Models/AgentConfigDto.cs @@ -2,7 +2,7 @@ namespace MaIN.Models.Rag; -public class AgentContextDto +public class AgentConfigDto { [JsonPropertyName("instruction")] public string Instruction { get; set; } @@ -13,4 +13,4 @@ public class AgentContextDto [JsonPropertyName("relations")] public List? Relations { get; set; } -} \ No newline at end of file +} diff --git a/Frontend/MainFE/Components/Models/AgentDto.cs b/Frontend/MainFE/Components/Models/AgentDto.cs index b4d79e1d..acc78057 100644 --- a/Frontend/MainFE/Components/Models/AgentDto.cs +++ b/Frontend/MainFE/Components/Models/AgentDto.cs @@ -21,8 +21,8 @@ public class AgentDto public bool Started { get; set; } [JsonPropertyName("flow")] public bool Flow { get; set; } - [JsonPropertyName("context")] - public AgentContextDto Context { get; set; } + [JsonPropertyName("config")] + public AgentConfigDto Config { get; set; } public AgentProcessingState State { get; set; } public bool IsProcessing { get; set; } public List? AgentDependencies { get; set; } = []; @@ -36,4 +36,4 @@ public string ProgressMessage set => _progressMessage = value; } private string? _progressMessage; -} \ No newline at end of file +} diff --git a/src/MaIN.Core.UnitTests/AgentContextTests.cs b/src/MaIN.Core.UnitTests/AgentContextTests.cs index 27b8a7af..a5187b4c 100644 --- a/src/MaIN.Core.UnitTests/AgentContextTests.cs +++ b/src/MaIN.Core.UnitTests/AgentContextTests.cs @@ -34,7 +34,7 @@ public void Constructor_ShouldInitializeNewAgent() Assert.NotNull(agentId); Assert.NotEmpty(agentId); Assert.NotNull(agent); - Assert.NotNull(agent.Context); + Assert.NotNull(agent.Config); Assert.NotNull(agent.Behaviours); Assert.Equal("Agent created by MaIN", agent.Description); } @@ -88,7 +88,7 @@ public void WithInitialPrompt_ShouldSetInstruction() var result = _agentContext.WithInitialPrompt(expectedPrompt); // Assert - Assert.Equal(expectedPrompt, _agentContext.GetAgent().Context.Instruction); + Assert.Equal(expectedPrompt, _agentContext.GetAgent().Config.Instruction); Assert.Equal(result, _agentContext); } @@ -102,7 +102,7 @@ public void WithSteps_ShouldSetAgentSteps() var result = _agentContext.WithSteps(expectedSteps); // Assert - Assert.Equal(expectedSteps, _agentContext.GetAgent().Context.Steps); + Assert.Equal(expectedSteps, _agentContext.GetAgent().Config.Steps); Assert.Equal(result, _agentContext); } @@ -132,7 +132,7 @@ public async Task CreateAsync_ShouldCallAgentServiceCreateAgent() { Id = Guid.NewGuid().ToString(), CurrentBehaviour = "Default", - Context = new AgentData() + Config = new AgentConfig() }; _mockAgentService .Setup(s => s.CreateAgent( @@ -224,7 +224,7 @@ public async Task FromExisting_ShouldCreateContextFromExistingAgent() Id = existingAgentId, Name = "Existing Agent", CurrentBehaviour = "Default", - Context = new AgentData() + Config = new AgentConfig() }; _mockAgentService diff --git a/src/MaIN.Core.UnitTests/FlowContextTests.cs b/src/MaIN.Core.UnitTests/FlowContextTests.cs index baf090a8..96170db4 100644 --- a/src/MaIN.Core.UnitTests/FlowContextTests.cs +++ b/src/MaIN.Core.UnitTests/FlowContextTests.cs @@ -25,7 +25,7 @@ public FlowContextTests() var testModel = new GenericLocalModel(_testModelId); ModelRegistry.RegisterOrReplace(testModel); } - + [Fact] public async Task WithId_ShouldSetFlowId() { @@ -34,7 +34,7 @@ public async Task WithId_ShouldSetFlowId() // Act var result = _flowContext.WithId(expectedId); - + // Setup mock to return flow with the set ID _mockFlowService .Setup(s => s.GetFlowById(expectedId)) @@ -55,13 +55,14 @@ public async Task WithName_ShouldSetFlowName() // Act var result = _flowContext.WithName(expectedName); - + // Setup mock to return flow with the set name _mockFlowService .Setup(s => s.GetFlowById(It.IsAny())) - .ReturnsAsync(new AgentFlow { - Id = It.IsAny(), - Name = expectedName + .ReturnsAsync(new AgentFlow + { + Id = It.IsAny(), + Name = expectedName }); var flow = await _flowContext.GetCurrentFlow(); @@ -92,11 +93,17 @@ public async Task CreateAsync_ShouldCallFlowService() public async Task ProcessAsync_WithStringMessage_ShouldReturnChatResult() { // Arrange - var firstAgent = new Agent { Id = "first-agent", Order = 0, CurrentBehaviour = It.IsAny(), Context = new AgentData()}; + var firstAgent = new Agent + { + Id = "first-agent", + Order = 0, + CurrentBehaviour = It.IsAny(), + Config = new AgentConfig() + }; _flowContext.AddAgent(firstAgent); var message = "Hello, flow!"; - var chat = new Chat { Id = firstAgent.Id, Messages = new List(), ModelId = _testModelId, Name = "test"}; + var chat = new Chat { Id = firstAgent.Id, Messages = [], ModelId = _testModelId, Name = "test" }; _mockAgentService .Setup(s => s.GetChatByAgent(firstAgent.Id)) @@ -104,12 +111,14 @@ public async Task ProcessAsync_WithStringMessage_ShouldReturnChatResult() _mockAgentService .Setup(s => s.Process(It.IsAny(), firstAgent.Id, It.IsAny(), It.IsAny(), null, null)) - .ReturnsAsync(new Chat { - ModelId = _testModelId, + .ReturnsAsync(new Chat + { + ModelId = _testModelId, Name = "test", - Messages = new List { - new() { Content = "Response", Role = "Assistant", Type = MessageType.LocalLLM} - } + Messages = + [ + new() { Content = "Response", Role = "Assistant", Type = MessageType.LocalLLM} + ] }); // Act @@ -165,9 +174,9 @@ public async Task FromExisting_ShouldCreateFlowContextFromExistingFlow() { // Arrange var existingFlowId = "existing-flow-id"; - var existingFlow = new AgentFlow - { - Id = existingFlowId, + var existingFlow = new AgentFlow + { + Id = existingFlowId, Name = "Existing Flow", Agents = [ @@ -175,7 +184,7 @@ public async Task FromExisting_ShouldCreateFlowContextFromExistingFlow() { Id = "agent1", CurrentBehaviour = It.IsAny(), - Context = new AgentData() + Config = new AgentConfig() } ] }; @@ -203,4 +212,4 @@ public async Task FromExisting_ShouldThrowArgumentExceptionWhenFlowNotFound() // Act & Assert await Assert.ThrowsAsync(() => _flowContext.FromExisting(nonExistentFlowId)); } -} \ No newline at end of file +} diff --git a/src/MaIN.Core/Bootstrapper.cs b/src/MaIN.Core/Bootstrapper.cs index 7dea927d..d3ebfa80 100644 --- a/src/MaIN.Core/Bootstrapper.cs +++ b/src/MaIN.Core/Bootstrapper.cs @@ -2,6 +2,7 @@ using MaIN.Core.Interfaces; using MaIN.Core.Services; using MaIN.Domain.Configuration; +using MaIN.Infrastructure; using MaIN.Services; using MaIN.Services.Services; using MaIN.Services.Services.Abstract; @@ -18,6 +19,7 @@ public static IServiceCollection AddMaIN( Action? configureSettings = null) { services.ConfigureMaIN(configuration, configureSettings); + services.ConfigureInfrastructure(configuration); services.AddAIHub(); return services; } diff --git a/src/MaIN.Core/Hub/Contexts/AgentContext.cs b/src/MaIN.Core/Hub/Contexts/AgentContext.cs index c4c259d6..86ce1501 100644 --- a/src/MaIN.Core/Hub/Contexts/AgentContext.cs +++ b/src/MaIN.Core/Hub/Contexts/AgentContext.cs @@ -35,7 +35,7 @@ internal AgentContext(IAgentService agentService) Description = "Agent created by MaIN", CurrentBehaviour = "Default", Flow = false, - Context = new AgentData() + Config = new AgentConfig() { Instruction = "Hello, I'm your personal assistant. How can I assist you today?", Relations = [], @@ -84,7 +84,7 @@ public async Task FromExisting(string agentId) public IAgentConfigurationBuilder WithInitialPrompt(string prompt) { - _agent.Context.Instruction = prompt; + _agent.Config.Instruction = prompt; return this; } @@ -114,7 +114,7 @@ public IAgentConfigurationBuilder EnsureModelDownloaded() public IAgentConfigurationBuilder WithSource(IAgentSource source, AgentSourceType type) { - _agent.Context.Source = new AgentSource() + _agent.Config.Source = new AgentSource() { Details = source, Type = type @@ -134,8 +134,7 @@ public IAgentConfigurationBuilder WithMcpConfig(Mcp mcpConfig) { mcpConfig.Backend = ModelRegistry.GetById(_agent.Model).Backend; } - - _agent.Context.McpConfig = mcpConfig; + _agent.Config.McpConfig = mcpConfig; return this; } @@ -153,7 +152,7 @@ public IAgentConfigurationBuilder WithMemoryParams(MemoryParams memoryParams) public IAgentConfigurationBuilder WithSteps(List? steps) { - _agent.Context.Steps = steps; + _agent.Config.Steps = steps; return this; } diff --git a/src/MaIN.Domain/Entities/Agents/Agent.cs b/src/MaIN.Domain/Entities/Agents/Agent.cs index 0bf6af30..474ebed9 100644 --- a/src/MaIN.Domain/Entities/Agents/Agent.cs +++ b/src/MaIN.Domain/Entities/Agents/Agent.cs @@ -11,7 +11,7 @@ public class Agent public string? Description { get; init; } public bool Started { get; set; } public bool Flow { get; set; } - public required AgentData Context { get; init; } + public required AgentConfig Config { get; init; } public string ChatId { get; set; } = string.Empty; public int Order { get; set; } public BackendType? Backend { get; set; } diff --git a/src/MaIN.Domain/Entities/Agents/AgentData.cs b/src/MaIN.Domain/Entities/Agents/AgentConfig.cs similarity index 91% rename from src/MaIN.Domain/Entities/Agents/AgentData.cs rename to src/MaIN.Domain/Entities/Agents/AgentConfig.cs index 014348e1..22efb033 100644 --- a/src/MaIN.Domain/Entities/Agents/AgentData.cs +++ b/src/MaIN.Domain/Entities/Agents/AgentConfig.cs @@ -1,11 +1,10 @@ namespace MaIN.Domain.Entities.Agents; -public class AgentData +public class AgentConfig { public string? Instruction { get; set; } public AgentSource.AgentSource? Source { get; set; } public Mcp? McpConfig { get; set; } public List? Steps { get; set; } public List? Relations { get; set; } - -} \ No newline at end of file +} diff --git a/src/MaIN.Domain/Exceptions/Agents/AgentContextNotFoundException.cs b/src/MaIN.Domain/Exceptions/Agents/AgentConfigNotFoundException.cs similarity index 56% rename from src/MaIN.Domain/Exceptions/Agents/AgentContextNotFoundException.cs rename to src/MaIN.Domain/Exceptions/Agents/AgentConfigNotFoundException.cs index d852cba2..44376311 100644 --- a/src/MaIN.Domain/Exceptions/Agents/AgentContextNotFoundException.cs +++ b/src/MaIN.Domain/Exceptions/Agents/AgentConfigNotFoundException.cs @@ -1,8 +1,8 @@ -using System.Net; +using System.Net; namespace MaIN.Domain.Exceptions.Agents; -public class AgentContextNotFoundException(string agentId) : MaINCustomException($"Context of agent with id: '{agentId}' not found.") +public class AgentConfigNotFoundException(string agentId) : MaINCustomException($"Context of agent with id: '{agentId}' not found.") { public override string PublicErrorMessage => "Agent context not found."; public override HttpStatusCode HttpStatusCode => HttpStatusCode.NotFound; diff --git a/src/MaIN.Domain/Repositories/IAgentFlowRepository.cs b/src/MaIN.Domain/Repositories/IAgentFlowRepository.cs new file mode 100644 index 00000000..c55eb61f --- /dev/null +++ b/src/MaIN.Domain/Repositories/IAgentFlowRepository.cs @@ -0,0 +1,12 @@ +using MaIN.Domain.Entities.Agents.AgentSource; + +namespace MaIN.Domain.Repositories; + +public interface IAgentFlowRepository +{ + Task> GetAllFlows(); + Task GetFlowById(string id); + Task AddFlow(AgentFlow flow); + Task UpdateFlow(string id, AgentFlow flow); + Task DeleteFlow(string id); +} diff --git a/src/MaIN.Domain/Repositories/IAgentRepository.cs b/src/MaIN.Domain/Repositories/IAgentRepository.cs new file mode 100644 index 00000000..570a8a78 --- /dev/null +++ b/src/MaIN.Domain/Repositories/IAgentRepository.cs @@ -0,0 +1,13 @@ +using MaIN.Domain.Entities.Agents; + +namespace MaIN.Domain.Repositories; + +public interface IAgentRepository +{ + Task> GetAllAgents(); + Task GetAgentById(string id); + Task AddAgent(Agent agent); + Task UpdateAgent(string id, Agent agent); + Task DeleteAgent(string id); + Task Exists(string id); +} diff --git a/src/MaIN.Domain/Repositories/IChatRepository.cs b/src/MaIN.Domain/Repositories/IChatRepository.cs new file mode 100644 index 00000000..06fad858 --- /dev/null +++ b/src/MaIN.Domain/Repositories/IChatRepository.cs @@ -0,0 +1,12 @@ +using MaIN.Domain.Entities; + +namespace MaIN.Domain.Repositories; + +public interface IChatRepository +{ + Task> GetAllChats(); + Task GetChatById(string id); + Task AddChat(Chat chat); + Task UpdateChat(string id, Chat chat); + Task DeleteChat(string id); +} diff --git a/src/MaIN.Infrastructure/Bootstrapper.cs b/src/MaIN.Infrastructure/Bootstrapper.cs index 08a12600..67edcc74 100644 --- a/src/MaIN.Infrastructure/Bootstrapper.cs +++ b/src/MaIN.Infrastructure/Bootstrapper.cs @@ -1,7 +1,7 @@ using MaIN.Domain.Configuration; using MaIN.Infrastructure.Configuration; using MaIN.Infrastructure.Repositories; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; using MaIN.Infrastructure.Repositories.FileSystem; using MaIN.Infrastructure.Repositories.Mongo; using Microsoft.Extensions.Configuration; diff --git a/src/MaIN.Infrastructure/Configuration/SqlExtensions.cs b/src/MaIN.Infrastructure/Configuration/SqlExtensions.cs index 88983ad9..692af6b4 100644 --- a/src/MaIN.Infrastructure/Configuration/SqlExtensions.cs +++ b/src/MaIN.Infrastructure/Configuration/SqlExtensions.cs @@ -1,5 +1,5 @@ using Dapper; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; using MaIN.Infrastructure.Repositories.Sql; using Microsoft.Data.SqlClient; using Microsoft.Extensions.DependencyInjection; diff --git a/src/MaIN.Infrastructure/Configuration/SqliteExtensions.cs b/src/MaIN.Infrastructure/Configuration/SqliteExtensions.cs index 7ab75dad..250f66d0 100644 --- a/src/MaIN.Infrastructure/Configuration/SqliteExtensions.cs +++ b/src/MaIN.Infrastructure/Configuration/SqliteExtensions.cs @@ -1,5 +1,5 @@ using Dapper; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; using MaIN.Infrastructure.Repositories.Sqlite; using Microsoft.Data.Sqlite; using Microsoft.Extensions.DependencyInjection; diff --git a/src/MaIN.Infrastructure/Mappers/AgentDocumentMapper.cs b/src/MaIN.Infrastructure/Mappers/AgentDocumentMapper.cs new file mode 100644 index 00000000..a7bcb1ff --- /dev/null +++ b/src/MaIN.Infrastructure/Mappers/AgentDocumentMapper.cs @@ -0,0 +1,92 @@ +using MaIN.Domain.Entities.Agents; +using MaIN.Domain.Entities.Agents.AgentSource; +using MaIN.Domain.Exceptions.Agents; +using MaIN.Infrastructure.Models; +using System.Text.Json; + +namespace MaIN.Infrastructure.Mappers; + +internal static class AgentDocumentMapper +{ + internal static AgentDocument ToDocument(this Agent agent) => new() + { + Id = agent.Id, + Name = agent.Name, + Model = agent.Model, + Order = agent.Order, + Started = agent.Started, + Flow = agent.Flow, + ToolsConfiguration = agent.ToolsConfiguration, + Backend = agent.Backend, + ChatId = agent.ChatId, + Description = agent.Description, + Behaviours = agent.Behaviours, + CurrentBehaviour = agent.CurrentBehaviour, + Config = agent.Config.ToDocument() + }; + + internal static Agent ToDomain(this AgentDocument agent) => new() + { + Id = agent.Id, + Name = agent.Name, + Model = agent.Model, + Started = agent.Started, + Order = agent.Order, + Flow = agent.Flow, + ToolsConfiguration = agent.ToolsConfiguration, + Backend = agent.Backend, + ChatId = agent.ChatId, + Description = agent.Description, + Behaviours = agent.Behaviours, + CurrentBehaviour = agent.CurrentBehaviour, + Config = agent.Config?.ToDomain() ?? throw new AgentConfigNotFoundException(agent.Id) + }; + + internal static AgentConfigDocument ToDocument(this AgentConfig config) => new() + { + Instruction = config.Instruction, + Relations = config.Relations?.ToList(), + Steps = config.Steps?.ToList(), + McpConfig = config.McpConfig, + Source = config.Source is not null + ? new AgentSourceDocument + { + DetailsSerialized = JsonSerializer.Serialize(config.Source.Details), + AdditionalMessage = config.Source.AdditionalMessage, + Type = Enum.Parse(config.Source.Type.ToString()) + } + : null + }; + + internal static AgentConfig ToDomain(this AgentConfigDocument agentConfigDocument) => new() + { + Instruction = agentConfigDocument.Instruction, + Relations = agentConfigDocument.Relations, + McpConfig = agentConfigDocument.McpConfig, + Source = agentConfigDocument.Source is not null + ? new AgentSource + { + AdditionalMessage = agentConfigDocument.Source.AdditionalMessage, + Details = agentConfigDocument.Source.DetailsSerialized, + Type = Enum.Parse(agentConfigDocument.Source.Type.ToString()) + } + : null, + Steps = agentConfigDocument.Steps + }; + + internal static AgentFlowDocument ToDocument(this AgentFlow agentFlow) => new() + { + Id = agentFlow.Id!, + Name = agentFlow.Name, + Description = agentFlow.Description!, + Agents = [.. agentFlow.Agents.Select(x => x.ToDocument())] + }; + + internal static AgentFlow ToDomain(this AgentFlowDocument agentFlow) => new() + { + Id = agentFlow.Id, + Name = agentFlow.Name, + Description = agentFlow.Description, + Agents = [.. agentFlow.Agents.Select(x => x.ToDomain())] + }; +} diff --git a/src/MaIN.Infrastructure/Mappers/ChatDocumentMapper.cs b/src/MaIN.Infrastructure/Mappers/ChatDocumentMapper.cs new file mode 100644 index 00000000..2d5f70db --- /dev/null +++ b/src/MaIN.Infrastructure/Mappers/ChatDocumentMapper.cs @@ -0,0 +1,140 @@ +using LLama.Batched; +using MaIN.Domain.Entities; +using MaIN.Domain.Models; +using MaIN.Infrastructure.Models; + +namespace MaIN.Infrastructure.Mappers; + +internal static class ChatDocumentMapper +{ + internal static ChatDocument ToDocument(this Chat chat) => new() + { + Id = chat.Id, + Name = chat.Name, + Model = chat.ModelId, + Messages = [.. chat.Messages.Select(m => m.ToDocument())], + ImageGen = chat.ImageGen, + ToolsConfiguration = chat.ToolsConfiguration, + MemoryParams = chat.MemoryParams.ToDocument(), + InferenceParams = chat.InterferenceParams.ToDocument(), + ConvState = chat.ConversationState, + Properties = chat.Properties, + Interactive = chat.Interactive, + Translate = chat.Translate, + Type = Enum.Parse(chat.Type.ToString()) + }; + + internal static Chat ToDomain(this ChatDocument chat) => new() + { + Id = chat.Id, + Name = chat.Name, + ModelId = chat.Model, + Messages = [.. chat.Messages.Select(m => m.ToDomain())], + ImageGen = chat.ImageGen, + Properties = chat.Properties, + ToolsConfiguration = chat.ToolsConfiguration, + ConversationState = chat.ConvState as Conversation.State, + MemoryParams = chat.MemoryParams!.ToDomain(), + InterferenceParams = chat.InferenceParams!.ToDomain(), + Interactive = chat.Interactive, + Translate = chat.Translate, + Type = Enum.Parse(chat.Type.ToString()) + }; + + private static MessageDocument ToDocument(this Message message) => new() + { + Content = message.Content, + Role = message.Role, + Time = message.Time, + MessageType = message.Type.ToString(), + Images = message.Image, + Tokens = [.. message.Tokens.Select(x => x.ToDocument())], + Properties = message.Properties, + Tool = message.Tool, + Files = (message.Files?.Select(x => x.Content).ToArray() ?? [])! + }; + + private static Message ToDomain(this MessageDocument message) => new() + { + Content = message.Content, + Tool = message.Tool, + Time = message.Time, + Type = Enum.Parse(message.MessageType), + Tokens = [.. message.Tokens.Select(x => x.ToDomain())], + Role = message.Role, + Image = message.Images, + Properties = message.Properties, + }; + + private static LLMTokenValueDocument ToDocument(this LLMTokenValue llmTokenValue) => new() + { + Text = llmTokenValue.Text, + Type = llmTokenValue.Type + }; + + private static LLMTokenValue ToDomain(this LLMTokenValueDocument llmTokenValue) => new() + { + Text = llmTokenValue.Text, + Type = llmTokenValue.Type + }; + + private static InferenceParamsDocument ToDocument(this InferenceParams inferenceParams) => new() + { + Temperature = inferenceParams.Temperature, + ContextSize = inferenceParams.ContextSize, + GpuLayerCount = inferenceParams.GpuLayerCount, + SeqMax = inferenceParams.SeqMax, + BatchSize = inferenceParams.BatchSize, + UBatchSize = inferenceParams.UBatchSize, + Embeddings = inferenceParams.Embeddings, + TypeK = inferenceParams.TypeK, + TypeV = inferenceParams.TypeV, + TokensKeep = inferenceParams.TokensKeep, + MaxTokens = inferenceParams.MaxTokens, + TopK = inferenceParams.TopK, + TopP = inferenceParams.TopP, + Grammar = inferenceParams.Grammar + }; + + private static InferenceParams ToDomain(this InferenceParamsDocument inferenceParams) => new() + { + Temperature = inferenceParams.Temperature, + ContextSize = inferenceParams.ContextSize, + GpuLayerCount = inferenceParams.GpuLayerCount, + SeqMax = inferenceParams.SeqMax, + BatchSize = inferenceParams.BatchSize, + UBatchSize = inferenceParams.UBatchSize, + Embeddings = inferenceParams.Embeddings, + TypeK = inferenceParams.TypeK, + TypeV = inferenceParams.TypeV, + TokensKeep = inferenceParams.TokensKeep, + MaxTokens = inferenceParams.MaxTokens, + TopK = inferenceParams.TopK, + TopP = inferenceParams.TopP, + Grammar = inferenceParams.Grammar + }; + + private static MemoryParamsDocument ToDocument(this MemoryParams memoryParams) => new() + { + Temperature = memoryParams.Temperature, + AnswerTokens = memoryParams.AnswerTokens, + MultiModalMode = memoryParams.MultiModalMode, + ContextSize = memoryParams.ContextSize, + GpuLayerCount = memoryParams.GpuLayerCount, + MaxMatchesCount = memoryParams.MaxMatchesCount, + FrequencyPenalty = memoryParams.FrequencyPenalty, + Grammar = memoryParams.Grammar + }; + + private static MemoryParams ToDomain(this MemoryParamsDocument memoryParams) => new() + { + Temperature = memoryParams.Temperature, + AnswerTokens = memoryParams.AnswerTokens, + MultiModalMode = memoryParams.MultiModalMode, + ContextSize = memoryParams.ContextSize, + GpuLayerCount = memoryParams.GpuLayerCount, + MaxMatchesCount = memoryParams.MaxMatchesCount, + FrequencyPenalty = memoryParams.FrequencyPenalty, + Grammar = memoryParams.Grammar + }; +} diff --git a/src/MaIN.Infrastructure/Models/AgentContextDocument.cs b/src/MaIN.Infrastructure/Models/AgentConfigDocument.cs similarity index 77% rename from src/MaIN.Infrastructure/Models/AgentContextDocument.cs rename to src/MaIN.Infrastructure/Models/AgentConfigDocument.cs index b603c908..54bb7848 100644 --- a/src/MaIN.Infrastructure/Models/AgentContextDocument.cs +++ b/src/MaIN.Infrastructure/Models/AgentConfigDocument.cs @@ -2,11 +2,11 @@ namespace MaIN.Infrastructure.Models; -public class AgentContextDocument +internal class AgentConfigDocument { public string? Instruction { get; init; } public AgentSourceDocument? Source { get; init; } public List? Steps { get; init; } public List? Relations { get; init; } - public Mcp? McpConfig { get; set; } -} \ No newline at end of file + public Mcp? McpConfig { get; init; } +} diff --git a/src/MaIN.Infrastructure/Models/AgentDocument.cs b/src/MaIN.Infrastructure/Models/AgentDocument.cs index 727f1dd6..a4f1c22d 100644 --- a/src/MaIN.Infrastructure/Models/AgentDocument.cs +++ b/src/MaIN.Infrastructure/Models/AgentDocument.cs @@ -4,7 +4,7 @@ namespace MaIN.Infrastructure.Models; -public class AgentDocument +internal class AgentDocument { [BsonId] public required string Id { get; init; } @@ -12,7 +12,7 @@ public class AgentDocument public required string Model { get; init; } public string? Description { get; init; } public bool Started { get; init; } - public AgentContextDocument? Context { get; init; } + public AgentConfigDocument? Config { get; init; } public required string ChatId { get; set; } public int Order { get; init; } public BackendType? Backend { get; init; } @@ -20,4 +20,4 @@ public class AgentDocument public string CurrentBehaviour { get; set; } = null!; public bool Flow { get; init; } public ToolsConfiguration? ToolsConfiguration { get; set; } -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Models/AgentFlowDocument.cs b/src/MaIN.Infrastructure/Models/AgentFlowDocument.cs index a77db047..368651d1 100644 --- a/src/MaIN.Infrastructure/Models/AgentFlowDocument.cs +++ b/src/MaIN.Infrastructure/Models/AgentFlowDocument.cs @@ -2,11 +2,11 @@ namespace MaIN.Infrastructure.Models; -public class AgentFlowDocument +internal class AgentFlowDocument { [BsonId] public required string Id { get; init; } public required string Name { get; init; } public required List Agents { get; init; } public required string Description { get; init; } -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Models/AgentSourceDocument.cs b/src/MaIN.Infrastructure/Models/AgentSourceDocument.cs index 50c38437..884e6cd7 100644 --- a/src/MaIN.Infrastructure/Models/AgentSourceDocument.cs +++ b/src/MaIN.Infrastructure/Models/AgentSourceDocument.cs @@ -1,8 +1,8 @@ namespace MaIN.Infrastructure.Models; -public class AgentSourceDocument +internal class AgentSourceDocument { public string? DetailsSerialized { get; init; } public AgentSourceTypeDocument Type { get; init; } public string? AdditionalMessage { get; init; } -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Models/ChatDocument.cs b/src/MaIN.Infrastructure/Models/ChatDocument.cs index f560bf6e..ca193c77 100644 --- a/src/MaIN.Infrastructure/Models/ChatDocument.cs +++ b/src/MaIN.Infrastructure/Models/ChatDocument.cs @@ -3,7 +3,7 @@ namespace MaIN.Infrastructure.Models; -public class ChatDocument +internal class ChatDocument { [BsonId] public required string Id { get; init; } diff --git a/src/MaIN.Infrastructure/Models/InterferenceParamsDocument.cs b/src/MaIN.Infrastructure/Models/InterferenceParamsDocument.cs index 6145469a..f601abee 100644 --- a/src/MaIN.Infrastructure/Models/InterferenceParamsDocument.cs +++ b/src/MaIN.Infrastructure/Models/InterferenceParamsDocument.cs @@ -2,20 +2,20 @@ namespace MaIN.Infrastructure.Models; -public class InferenceParamsDocument +internal class InferenceParamsDocument { public float Temperature { get; set; } public int ContextSize { get; set; } - public int GpuLayerCount { get; init; } - public uint SeqMax { get; init; } + public int GpuLayerCount { get; init; } + public uint SeqMax { get; init; } public uint BatchSize { get; init; } - public uint UBatchSize { get; init; } - public bool Embeddings { get; init; } - public int TypeK { get; init; } - public int TypeV { get; init; } + public uint UBatchSize { get; init; } + public bool Embeddings { get; init; } + public int TypeK { get; init; } + public int TypeV { get; init; } public int TokensKeep { get; set; } public int MaxTokens { get; set; } public int TopK { get; init; } public float TopP { get; init; } public Grammar? Grammar { get; set; } -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Models/LLMTokenValueDocument.cs b/src/MaIN.Infrastructure/Models/LLMTokenValueDocument.cs index 32de8447..db8edb50 100644 --- a/src/MaIN.Infrastructure/Models/LLMTokenValueDocument.cs +++ b/src/MaIN.Infrastructure/Models/LLMTokenValueDocument.cs @@ -2,8 +2,8 @@ namespace MaIN.Infrastructure.Models; -public class LLMTokenValueDocument +internal class LLMTokenValueDocument { public required string Text { get; set; } public TokenType Type { get; set; } //TODO add document representation of this domain enum -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Models/MemoryParamsDocument.cs b/src/MaIN.Infrastructure/Models/MemoryParamsDocument.cs index 24f13725..84219708 100644 --- a/src/MaIN.Infrastructure/Models/MemoryParamsDocument.cs +++ b/src/MaIN.Infrastructure/Models/MemoryParamsDocument.cs @@ -2,14 +2,14 @@ namespace MaIN.Infrastructure.Models; -public class MemoryParamsDocument +internal class MemoryParamsDocument { public int ContextSize { get; set; } public int GpuLayerCount { get; set; } - public int MaxMatchesCount { get; set; } + public int MaxMatchesCount { get; set; } public float FrequencyPenalty { get; set; } - public float Temperature { get; set; } + public float Temperature { get; set; } public int AnswerTokens { get; set; } public bool MultiModalMode { get; set; } public Grammar? Grammar { get; set; } -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Models/MessageDocument.cs b/src/MaIN.Infrastructure/Models/MessageDocument.cs index 73d91c88..80478adf 100644 --- a/src/MaIN.Infrastructure/Models/MessageDocument.cs +++ b/src/MaIN.Infrastructure/Models/MessageDocument.cs @@ -1,6 +1,6 @@ namespace MaIN.Infrastructure.Models; -public class MessageDocument +internal class MessageDocument { public required string Role { get; init; } public required string Content { get; init; } @@ -11,4 +11,4 @@ public class MessageDocument public bool Tool { get; init; } public Dictionary Properties { get; init; } = []; public List Tokens { get; set; } = []; -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Repositories/Abstract/IAgentFlowRepository.cs b/src/MaIN.Infrastructure/Repositories/Abstract/IAgentFlowRepository.cs deleted file mode 100644 index 21e31470..00000000 --- a/src/MaIN.Infrastructure/Repositories/Abstract/IAgentFlowRepository.cs +++ /dev/null @@ -1,12 +0,0 @@ -using MaIN.Infrastructure.Models; - -namespace MaIN.Infrastructure.Repositories.Abstract; - -public interface IAgentFlowRepository -{ - Task> GetAllFlows(); - Task GetFlowById(string id); - Task AddFlow(AgentFlowDocument flow); - Task UpdateFlow(string id, AgentFlowDocument flow); - Task DeleteFlow(string id); -} \ No newline at end of file diff --git a/src/MaIN.Infrastructure/Repositories/Abstract/IAgentRepository.cs b/src/MaIN.Infrastructure/Repositories/Abstract/IAgentRepository.cs deleted file mode 100644 index fb3c1e0b..00000000 --- a/src/MaIN.Infrastructure/Repositories/Abstract/IAgentRepository.cs +++ /dev/null @@ -1,13 +0,0 @@ -using MaIN.Infrastructure.Models; - -namespace MaIN.Infrastructure.Repositories.Abstract; - -public interface IAgentRepository -{ - Task> GetAllAgents(); - Task GetAgentById(string id); - Task AddAgent(AgentDocument agent); - Task UpdateAgent(string id, AgentDocument agent); - Task DeleteAgent(string id); - Task Exists(string id); -} \ No newline at end of file diff --git a/src/MaIN.Infrastructure/Repositories/Abstract/IChatRepository.cs b/src/MaIN.Infrastructure/Repositories/Abstract/IChatRepository.cs deleted file mode 100644 index 8334dc08..00000000 --- a/src/MaIN.Infrastructure/Repositories/Abstract/IChatRepository.cs +++ /dev/null @@ -1,12 +0,0 @@ -using MaIN.Infrastructure.Models; - -namespace MaIN.Infrastructure.Repositories.Abstract; - -public interface IChatRepository -{ - Task> GetAllChats(); - Task GetChatById(string id); - Task AddChat(ChatDocument chat); - Task UpdateChat(string id, ChatDocument chat); - Task DeleteChat(string id); -} \ No newline at end of file diff --git a/src/MaIN.Infrastructure/Repositories/DefaultAgentFlowRepository.cs b/src/MaIN.Infrastructure/Repositories/DefaultAgentFlowRepository.cs index 855cca2e..9596c7cf 100644 --- a/src/MaIN.Infrastructure/Repositories/DefaultAgentFlowRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/DefaultAgentFlowRepository.cs @@ -1,41 +1,28 @@ -using System.Collections.Concurrent; +using MaIN.Domain.Entities.Agents.AgentSource; using MaIN.Domain.Exceptions.Flows; -using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; +using System.Collections.Concurrent; namespace MaIN.Infrastructure.Repositories; public class DefaultAgentFlowRepository : IAgentFlowRepository { - private readonly ConcurrentDictionary _flows = new(); - - public async Task> GetAllFlows() => - await Task.FromResult(_flows.Values); - - public async Task GetFlowById(string id) => - (await Task.FromResult(_flows.GetValueOrDefault(id)))!; + private readonly ConcurrentDictionary _flows = new(); - public async Task AddFlow(AgentFlowDocument flow) - { - if (!_flows.TryAdd(flow.Id, flow)) - throw new FlowAlreadyExistsException(flow.Id); - - await Task.CompletedTask; - } + public Task> GetAllFlows() => Task.FromResult(_flows.Values.AsEnumerable()); + public Task GetFlowById(string id) => Task.FromResult(_flows.GetValueOrDefault(id)); + public Task AddFlow(AgentFlow flow) => + !_flows.TryAdd(flow.Id!, flow) + ? throw new FlowAlreadyExistsException(flow.Id!) + : Task.CompletedTask; - public async Task UpdateFlow(string id, AgentFlowDocument flow) - { - if (!_flows.TryUpdate(id, flow, _flows.GetValueOrDefault(id)!)) - throw new KeyNotFoundException($"Flow with ID {id} not found."); - - await Task.CompletedTask; - } + public Task UpdateFlow(string id, AgentFlow flow) => + !_flows.TryUpdate(id, flow, _flows.GetValueOrDefault(id)!) + ? throw new KeyNotFoundException($"Flow with ID {id} not found.") + : Task.CompletedTask; - public async Task DeleteFlow(string id) - { - if (!_flows.TryRemove(id, out _)) - throw new KeyNotFoundException($"Flow with ID {id} not found."); - - await Task.CompletedTask; - } -} \ No newline at end of file + public Task DeleteFlow(string id) => + !_flows.TryRemove(id, out _) + ? throw new KeyNotFoundException($"Flow with ID {id} not found.") + : Task.CompletedTask; +} diff --git a/src/MaIN.Infrastructure/Repositories/DefaultAgentRepository.cs b/src/MaIN.Infrastructure/Repositories/DefaultAgentRepository.cs index 8a94b3ff..74727628 100644 --- a/src/MaIN.Infrastructure/Repositories/DefaultAgentRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/DefaultAgentRepository.cs @@ -1,47 +1,32 @@ -using System.Collections.Concurrent; +using MaIN.Domain.Entities.Agents; using MaIN.Domain.Exceptions.Agents; -using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; +using System.Collections.Concurrent; namespace MaIN.Infrastructure.Repositories; public class DefaultAgentRepository : IAgentRepository { - private readonly ConcurrentDictionary _agents = new(); - - public async Task> GetAllAgents() => - await Task.FromResult(_agents.Values); - - public async Task GetAgentById(string id) => - await Task.FromResult(_agents.GetValueOrDefault(id)); - - public async Task AddAgent(AgentDocument agent) - { - if (agent == null) - throw new ArgumentNullException(nameof(agent)); - - if (!_agents.TryAdd(agent.Id, agent)) - throw new AgentAlreadyExistsException(agent.Id); - - await Task.CompletedTask; - } - - public async Task UpdateAgent(string id, AgentDocument agent) - { - if (!_agents.TryUpdate(id, agent, _agents.GetValueOrDefault(id)!)) - throw new AgentNotFoundException(id); - - await Task.CompletedTask; - } - - public async Task DeleteAgent(string id) - { - if (!_agents.TryRemove(id, out _)) - throw new AgentNotFoundException(id); - - await Task.CompletedTask; - } - - public async Task Exists(string id) => - await Task.FromResult(_agents.ContainsKey(id)); -} \ No newline at end of file + private readonly ConcurrentDictionary _agents = new(); + + public Task> GetAllAgents() => Task.FromResult(_agents.Values.AsEnumerable()); + + public Task GetAgentById(string id) => Task.FromResult(_agents.GetValueOrDefault(id)); + + public Task AddAgent(Agent agent) => + !_agents.TryAdd(agent.Id, agent) + ? throw new AgentAlreadyExistsException(agent.Id) + : Task.CompletedTask; + + public Task UpdateAgent(string id, Agent agent) => + !_agents.TryUpdate(id, agent, _agents.GetValueOrDefault(id)!) + ? throw new AgentNotFoundException(id) + : Task.CompletedTask; + + public Task DeleteAgent(string id) => + !_agents.TryRemove(id, out _) + ? throw new AgentNotFoundException(id) + : Task.CompletedTask; + + public Task Exists(string id) => Task.FromResult(_agents.ContainsKey(id)); +} diff --git a/src/MaIN.Infrastructure/Repositories/DefaultChatRepository.cs b/src/MaIN.Infrastructure/Repositories/DefaultChatRepository.cs index 246c9eea..d1562ec9 100644 --- a/src/MaIN.Infrastructure/Repositories/DefaultChatRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/DefaultChatRepository.cs @@ -1,41 +1,29 @@ -using System.Collections.Concurrent; +using MaIN.Domain.Entities; using MaIN.Domain.Exceptions.Chats; -using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; +using System.Collections.Concurrent; namespace MaIN.Infrastructure.Repositories; public class DefaultChatRepository : IChatRepository { - private readonly ConcurrentDictionary _chats = new(); - - public async Task> GetAllChats() => - await Task.FromResult(_chats.Values); + private readonly ConcurrentDictionary _chats = new(); - public async Task GetChatById(string id) => - (await Task.FromResult(_chats.GetValueOrDefault(id)))!; + public Task> GetAllChats() => Task.FromResult(_chats.Values.AsEnumerable()); - public async Task AddChat(ChatDocument chat) - { - if (!_chats.TryAdd(chat.Id, chat)) - throw new ChatAlreadyExistsException(chat.Id); - - await Task.CompletedTask; - } + public Task GetChatById(string id) => Task.FromResult(_chats.GetValueOrDefault(id)); - public async Task UpdateChat(string id, ChatDocument chat) - { - if (!_chats.TryUpdate(id, chat, _chats.GetValueOrDefault(id)!)) - throw new KeyNotFoundException($"Chat with ID {id} not found."); - - await Task.CompletedTask; - } + public Task AddChat(Chat chat) => + !_chats.TryAdd(chat.Id, chat) + ? throw new ChatAlreadyExistsException(chat.Id) + : Task.CompletedTask; - public async Task DeleteChat(string id) - { - if (!_chats.TryRemove(id, out _)) - throw new KeyNotFoundException($"Chat with ID {id} not found."); - - await Task.CompletedTask; - } -} \ No newline at end of file + public Task UpdateChat(string id, Chat chat) => + !_chats.TryUpdate(id, chat, _chats.GetValueOrDefault(id)!) + ? throw new KeyNotFoundException($"Chat with ID {id} not found.") + : Task.CompletedTask; + public Task DeleteChat(string id) => + !_chats.TryRemove(id, out _) + ? throw new KeyNotFoundException($"Chat with ID {id} not found.") + : Task.CompletedTask; +} diff --git a/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemAgentFlowRepository.cs b/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemAgentFlowRepository.cs index 73a2db71..5e475f13 100644 --- a/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemAgentFlowRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemAgentFlowRepository.cs @@ -1,7 +1,9 @@ -using System.Text.Json; +using MaIN.Domain.Entities.Agents.AgentSource; using MaIN.Domain.Exceptions.Flows; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; +using System.Text.Json; namespace MaIN.Infrastructure.Repositories.FileSystem; @@ -18,47 +20,57 @@ public FileSystemAgentFlowRepository(string basePath) private string GetFilePath(string id) => Path.Combine(_directoryPath, $"{id}.json"); - public async Task> GetAllFlows() + public async Task> GetAllFlows() { var files = Directory.GetFiles(_directoryPath, "*.json"); - var flows = new List(); + var flows = new List(); foreach (var file in files) { var json = await File.ReadAllTextAsync(file); - var flow = JsonSerializer.Deserialize(json); - if (flow != null) flows.Add(flow); + var doc = JsonSerializer.Deserialize(json); + if (doc is not null) + { + flows.Add(doc.ToDomain()); + } } return flows; } - public async Task GetFlowById(string id) + public async Task GetFlowById(string id) { var filePath = GetFilePath(id); - if (!File.Exists(filePath)) return null; + if (!File.Exists(filePath)) + { + return null; + } var json = await File.ReadAllTextAsync(filePath); - return JsonSerializer.Deserialize(json); + return JsonSerializer.Deserialize(json)?.ToDomain(); } - public async Task AddFlow(AgentFlowDocument flow) + public async Task AddFlow(AgentFlow flow) { - var filePath = GetFilePath(flow.Id); + var filePath = GetFilePath(flow.Id!); if (File.Exists(filePath)) - throw new FlowAlreadyExistsException(flow.Id); + { + throw new FlowAlreadyExistsException(flow.Id!); + } - var json = JsonSerializer.Serialize(flow, JsonOptions); + var json = JsonSerializer.Serialize(flow.ToDocument(), JsonOptions); await File.WriteAllTextAsync(filePath, json); } - public async Task UpdateFlow(string id, AgentFlowDocument flow) + public async Task UpdateFlow(string id, AgentFlow flow) { var filePath = GetFilePath(id); if (!File.Exists(filePath)) + { throw new KeyNotFoundException($"Flow with ID {id} not found."); + } - var json = JsonSerializer.Serialize(flow, JsonOptions); + var json = JsonSerializer.Serialize(flow.ToDocument(), JsonOptions); await File.WriteAllTextAsync(filePath, json); } @@ -66,7 +78,9 @@ public async Task DeleteFlow(string id) { var filePath = GetFilePath(id); if (!File.Exists(filePath)) + { throw new KeyNotFoundException($"Flow with ID {id} not found."); + } await Task.Run(() => File.Delete(filePath)); } diff --git a/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemAgentRepository.cs b/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemAgentRepository.cs index 62f7e805..1b15f263 100644 --- a/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemAgentRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemAgentRepository.cs @@ -1,7 +1,9 @@ -using System.Text.Json; +using MaIN.Domain.Entities.Agents; using MaIN.Domain.Exceptions.Agents; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; +using System.Text.Json; namespace MaIN.Infrastructure.Repositories.FileSystem; @@ -18,50 +20,59 @@ public FileSystemAgentRepository(string basePath) private string GetFilePath(string id) => Path.Combine(_directoryPath, $"{id}.json"); - public async Task> GetAllAgents() + public async Task> GetAllAgents() { var files = Directory.GetFiles(_directoryPath, "*.json"); - var agents = new List(); + var agents = new List(); foreach (var file in files) { var json = await File.ReadAllTextAsync(file); - var agent = JsonSerializer.Deserialize(json); - if (agent != null) agents.Add(agent); + var doc = JsonSerializer.Deserialize(json); + if (doc is not null) + { + agents.Add(doc.ToDomain()); + } } return agents; } - public async Task GetAgentById(string id) + public async Task GetAgentById(string id) { var filePath = GetFilePath(id); - if (!File.Exists(filePath)) return null; + if (!File.Exists(filePath)) + { + return null; + } var json = await File.ReadAllTextAsync(filePath); - return JsonSerializer.Deserialize(json); + return JsonSerializer.Deserialize(json)?.ToDomain(); } - public async Task AddAgent(AgentDocument agent) + public async Task AddAgent(Agent agent) { - if (agent == null) - throw new ArgumentNullException(nameof(agent)); + ArgumentNullException.ThrowIfNull(agent); var filePath = GetFilePath(agent.Id); if (File.Exists(filePath)) + { throw new AgentAlreadyExistsException(agent.Id); + } - var json = JsonSerializer.Serialize(agent, JsonOptions); + var json = JsonSerializer.Serialize(agent.ToDocument(), JsonOptions); await File.WriteAllTextAsync(filePath, json); } - public async Task UpdateAgent(string id, AgentDocument agent) + public async Task UpdateAgent(string id, Agent agent) { var filePath = GetFilePath(id); if (!File.Exists(filePath)) + { throw new KeyNotFoundException($"Agent with ID {id} not found."); + } - var json = JsonSerializer.Serialize(agent, JsonOptions); + var json = JsonSerializer.Serialize(agent.ToDocument(), JsonOptions); await File.WriteAllTextAsync(filePath, json); } @@ -69,11 +80,13 @@ public async Task DeleteAgent(string id) { var filePath = GetFilePath(id); if (!File.Exists(filePath)) + { throw new KeyNotFoundException($"Agent with ID {id} not found."); + } await Task.Run(() => File.Delete(filePath)); } public async Task Exists(string id) => await Task.FromResult(File.Exists(GetFilePath(id))); -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemChatRepository.cs b/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemChatRepository.cs index 1748dc11..60da9a3d 100644 --- a/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemChatRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/FileSystem/FileSystemChatRepository.cs @@ -1,7 +1,9 @@ -using System.Text.Json; +using MaIN.Domain.Entities; using MaIN.Domain.Exceptions.Chats; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; +using System.Text.Json; namespace MaIN.Infrastructure.Repositories.FileSystem; @@ -18,47 +20,57 @@ public FileSystemChatRepository(string basePath) private string GetFilePath(string id) => Path.Combine(_directoryPath, $"{id}.json"); - public async Task> GetAllChats() + public async Task> GetAllChats() { var files = Directory.GetFiles(_directoryPath, "*.json"); - var chats = new List(); + var chats = new List(); foreach (var file in files) { var json = await File.ReadAllTextAsync(file); - var chat = JsonSerializer.Deserialize(json); - if (chat != null) chats.Add(chat); + var doc = JsonSerializer.Deserialize(json); + if (doc is not null) + { + chats.Add(doc.ToDomain()); + } } return chats; } - public async Task GetChatById(string id) + public async Task GetChatById(string id) { var filePath = GetFilePath(id); - if (!File.Exists(filePath)) return null; + if (!File.Exists(filePath)) + { + return null; + } var json = await File.ReadAllTextAsync(filePath); - return JsonSerializer.Deserialize(json); + return JsonSerializer.Deserialize(json)?.ToDomain(); } - public async Task AddChat(ChatDocument chat) + public async Task AddChat(Chat chat) { var filePath = GetFilePath(chat.Id); if (File.Exists(filePath)) + { throw new ChatAlreadyExistsException(chat.Id); + } - var json = JsonSerializer.Serialize(chat, JsonOptions); + var json = JsonSerializer.Serialize(chat.ToDocument(), JsonOptions); await File.WriteAllTextAsync(filePath, json); } - public async Task UpdateChat(string id, ChatDocument chat) + public async Task UpdateChat(string id, Chat chat) { var filePath = GetFilePath(id); if (!File.Exists(filePath)) + { throw new KeyNotFoundException($"Chat with ID {id} not found."); + } - var json = JsonSerializer.Serialize(chat, JsonOptions); + var json = JsonSerializer.Serialize(chat.ToDocument(), JsonOptions); await File.WriteAllTextAsync(filePath, json); } @@ -66,8 +78,10 @@ public async Task DeleteChat(string id) { var filePath = GetFilePath(id); if (!File.Exists(filePath)) + { throw new KeyNotFoundException($"Chat with ID {id} not found."); + } await Task.Run(() => File.Delete(filePath)); } -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Repositories/Mongo/MongoAgentFlowRepository.cs b/src/MaIN.Infrastructure/Repositories/Mongo/MongoAgentFlowRepository.cs index 04b91cc9..257f38eb 100644 --- a/src/MaIN.Infrastructure/Repositories/Mongo/MongoAgentFlowRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/Mongo/MongoAgentFlowRepository.cs @@ -1,5 +1,7 @@ +using MaIN.Domain.Entities.Agents.AgentSource; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; using MongoDB.Driver; namespace MaIN.Infrastructure.Repositories.Mongo; @@ -8,19 +10,18 @@ public class MongoAgentFlowRepository(IMongoDatabase database, string collection { private readonly IMongoCollection _flows = database.GetCollection(collectionName); - public async Task> GetAllFlows() => - await _flows.Find(chat => true).ToListAsync(); + public async Task> GetAllFlows() => + (await _flows.Find(flow => true).ToListAsync()).Select(d => d.ToDomain()); - public async Task GetFlowById(string id) => - await _flows.Find(flow => flow.Id == id).FirstOrDefaultAsync(); + public async Task GetFlowById(string id) => + (await _flows.Find(flow => flow.Id == id).FirstOrDefaultAsync())?.ToDomain(); - public async Task AddFlow(AgentFlowDocument flow) => - await _flows.InsertOneAsync(flow); + public async Task AddFlow(AgentFlow flow) => + await _flows.InsertOneAsync(flow.ToDocument()); + + public async Task UpdateFlow(string id, AgentFlow flow) => + await _flows.ReplaceOneAsync(x => x.Id == id, flow.ToDocument()); - public async Task UpdateFlow(string id, AgentFlowDocument flow) => - await _flows.ReplaceOneAsync(x => x.Id == id, flow); - public async Task DeleteFlow(string id) => await _flows.DeleteOneAsync(x => x.Id == id); - -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Repositories/Mongo/MongoAgentRepository.cs b/src/MaIN.Infrastructure/Repositories/Mongo/MongoAgentRepository.cs index 5134adfe..53662e45 100644 --- a/src/MaIN.Infrastructure/Repositories/Mongo/MongoAgentRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/Mongo/MongoAgentRepository.cs @@ -1,5 +1,7 @@ +using MaIN.Domain.Entities.Agents; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; using MongoDB.Driver; namespace MaIN.Infrastructure.Repositories.Mongo; @@ -8,22 +10,21 @@ public class MongoAgentRepository(IMongoDatabase database, string collectionName { private readonly IMongoCollection _agents = database.GetCollection(collectionName)!; - public async Task> GetAllAgents() => - await _agents.Find(chat => true).ToListAsync(); + public async Task> GetAllAgents() => + (await _agents.Find(agent => true).ToListAsync()).Select(d => d.ToDomain()); - public async Task GetAgentById(string id) => - await _agents.Find(agent => agent.Id == id).FirstOrDefaultAsync(); + public async Task GetAgentById(string id) => + (await _agents.Find(agent => agent.Id == id).FirstOrDefaultAsync())?.ToDomain(); + + public async Task AddAgent(Agent agent) => + await _agents.InsertOneAsync(agent.ToDocument()); + + public async Task UpdateAgent(string id, Agent agent) => + await _agents.ReplaceOneAsync(x => x.Id == id, agent.ToDocument()); - public async Task AddAgent(AgentDocument agent) => - await _agents.InsertOneAsync(agent); - - public async Task UpdateAgent(string id, AgentDocument agent) => - await _agents.ReplaceOneAsync(x => x.Id == id, agent); - public async Task DeleteAgent(string id) => await _agents.DeleteOneAsync(x => x.Id == id); - public async Task Exists(string id) => - (await _agents.CountDocumentsAsync(x => x!.Id == id)) > 0; - -} \ No newline at end of file + public async Task Exists(string id) => + (await _agents.CountDocumentsAsync(x => x.Id == id)) > 0; +} diff --git a/src/MaIN.Infrastructure/Repositories/Mongo/MongoChatRepository.cs b/src/MaIN.Infrastructure/Repositories/Mongo/MongoChatRepository.cs index a395199a..a76e079f 100644 --- a/src/MaIN.Infrastructure/Repositories/Mongo/MongoChatRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/Mongo/MongoChatRepository.cs @@ -1,5 +1,7 @@ +using MaIN.Domain.Entities; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; using MongoDB.Driver; namespace MaIN.Infrastructure.Repositories.Mongo; @@ -8,18 +10,18 @@ public class MongoChatRepository(IMongoDatabase database, string collectionName) { private readonly IMongoCollection _chats = database.GetCollection(collectionName); - public async Task> GetAllChats() => - await _chats.Find(chat => true).ToListAsync(); + public async Task> GetAllChats() => + (await _chats.Find(chat => true).ToListAsync()).Select(d => d.ToDomain()); - public async Task GetChatById(string id) => - await _chats.Find(chat => chat.Id == id).FirstOrDefaultAsync(); + public async Task GetChatById(string id) => + (await _chats.Find(chat => chat.Id == id).FirstOrDefaultAsync())?.ToDomain(); - public async Task AddChat(ChatDocument chat) => - await _chats.InsertOneAsync(chat); + public async Task AddChat(Chat chat) => + await _chats.InsertOneAsync(chat.ToDocument()); + + public async Task UpdateChat(string id, Chat chat) => + await _chats.ReplaceOneAsync(x => x.Id == id, chat.ToDocument()); - public async Task UpdateChat(string id, ChatDocument chat) => - await _chats.ReplaceOneAsync(x => x.Id == id, chat); - public async Task DeleteChat(string id) => await _chats.DeleteOneAsync(x => x.Id == id); -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Repositories/Sql/SqlAgentFlowRepository.cs b/src/MaIN.Infrastructure/Repositories/Sql/SqlAgentFlowRepository.cs index cab3f379..2c8eb4b1 100644 --- a/src/MaIN.Infrastructure/Repositories/Sql/SqlAgentFlowRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/Sql/SqlAgentFlowRepository.cs @@ -1,8 +1,10 @@ -using System.Data; -using System.Text.Json; using Dapper; +using MaIN.Domain.Entities.Agents.AgentSource; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; +using System.Data; +using System.Text.Json; namespace MaIN.Infrastructure.Repositories.Sql; @@ -19,9 +21,9 @@ private AgentFlowDocument MapAgentFlowDocument(dynamic row) { Id = row.Id, Name = row.Name, - Agents = row.Agents != null ? - JsonSerializer.Deserialize>(row.Agents.ToString(), _jsonOptions) : - new List(), + Agents = row.Agents is not null + ? JsonSerializer.Deserialize>(row.Agents.ToString(), _jsonOptions) + : new List(), Description = row.Description }; return flow; @@ -29,8 +31,7 @@ private AgentFlowDocument MapAgentFlowDocument(dynamic row) private object MapAgentFlowToParameters(AgentFlowDocument flow) { - if (flow == null) - throw new ArgumentNullException(nameof(flow)); + ArgumentNullException.ThrowIfNull(flow); return new { @@ -43,28 +44,27 @@ private object MapAgentFlowToParameters(AgentFlowDocument flow) }; } - public async Task> GetAllFlows() + public async Task> GetAllFlows() { var rows = await connection.QueryAsync(@" SELECT * FROM AgentFlows"); - return rows.Select(MapAgentFlowDocument); + return rows.Select(MapAgentFlowDocument).Select(x => x.ToDomain()); } - public async Task GetFlowById(string id) + public async Task GetFlowById(string id) { var row = await connection.QueryFirstOrDefaultAsync(@" - SELECT * FROM AgentFlows + SELECT * FROM AgentFlows WHERE Id = @Id", new { Id = id }); - return row != null ? MapAgentFlowDocument(row) : null; + return row is not null ? MapAgentFlowDocument(row).ToDomain() : null; } - public async Task AddFlow(AgentFlowDocument flow) + public async Task AddFlow(AgentFlow flow) { - if (flow == null) - throw new ArgumentNullException(nameof(flow)); + ArgumentNullException.ThrowIfNull(flow); - var parameters = MapAgentFlowToParameters(flow); + var parameters = MapAgentFlowToParameters(flow.ToDocument()); await connection.ExecuteAsync(@" INSERT INTO AgentFlows ( Id, Name, Agents, Description, CreatedAt, UpdatedAt @@ -73,14 +73,13 @@ INSERT INTO AgentFlows ( parameters); } - public async Task UpdateFlow(string id, AgentFlowDocument flow) + public async Task UpdateFlow(string id, AgentFlow flow) { - if (flow == null) - throw new ArgumentNullException(nameof(flow)); + ArgumentNullException.ThrowIfNull(flow); - var parameters = MapAgentFlowToParameters(flow); + var parameters = MapAgentFlowToParameters(flow.ToDocument()); await connection.ExecuteAsync(@" - UPDATE AgentFlows + UPDATE AgentFlows SET Name = @Name, Agents = @Agents, Description = @Description, @@ -91,12 +90,11 @@ UPDATE AgentFlows public async Task DeleteFlow(string id) => await connection.ExecuteAsync(@" - DELETE FROM AgentFlows + DELETE FROM AgentFlows WHERE Id = @Id", new { Id = id }); - // Optional: Add methods for JSON-specific queries - public async Task> GetFlowsByAgentName(string agentName) + public async Task> GetFlowsByAgentName(string agentName) { var rows = await connection.QueryAsync(@" SELECT * @@ -108,6 +106,6 @@ FROM OPENJSON(Agents) WHERE AgentData.Name = @agentName )", new { agentName }); - return rows.Select(MapAgentFlowDocument); + return rows.Select(MapAgentFlowDocument).Select(x => x.ToDomain()); } -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Repositories/Sql/SqlAgentRepository.cs b/src/MaIN.Infrastructure/Repositories/Sql/SqlAgentRepository.cs index 8b73b59c..2890556c 100644 --- a/src/MaIN.Infrastructure/Repositories/Sql/SqlAgentRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/Sql/SqlAgentRepository.cs @@ -1,25 +1,22 @@ -using System.Data; -using System.Text.Json; using Dapper; using MaIN.Domain.Configuration; +using MaIN.Domain.Entities.Agents; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; +using System.Data; +using System.Text.Json; namespace MaIN.Infrastructure.Repositories.Sql; -public class SqlAgentRepository : IAgentRepository +public class SqlAgentRepository(IDbConnection connection) : IAgentRepository { - private readonly IDbConnection _connection; + private readonly IDbConnection _connection = connection; private readonly JsonSerializerOptions? _jsonOptions = new() { PropertyNameCaseInsensitive = true }; - public SqlAgentRepository(IDbConnection connection) - { - _connection = connection; - } - private AgentDocument MapAgentDocument(dynamic row) { var agent = new AgentDocument @@ -29,15 +26,15 @@ private AgentDocument MapAgentDocument(dynamic row) Model = row.Model, Description = row.Description, Started = row.Started, - Context = row.Context != null ? - JsonSerializer.Deserialize(row.Context.ToString(), _jsonOptions) : - null, + Config = row.Context is not null + ? JsonSerializer.Deserialize(row.Context.ToString(), _jsonOptions) + : null, ChatId = row.ChatId, Order = row.Order, Backend = (BackendType)row.BackendType, - Behaviours = row.Behaviours != null ? - JsonSerializer.Deserialize>(row.Behaviours.ToString(), _jsonOptions) : - new Dictionary(), + Behaviours = row.Behaviours is not null + ? JsonSerializer.Deserialize>(row.Behaviours.ToString(), _jsonOptions) + : new Dictionary(), CurrentBehaviour = row.CurrentBehaviour, Flow = row.Flow }; @@ -46,8 +43,7 @@ private AgentDocument MapAgentDocument(dynamic row) private object MapAgentToParameters(AgentDocument agent) { - if (agent == null) - throw new ArgumentNullException(nameof(agent)); + ArgumentNullException.ThrowIfNull(agent); return new { @@ -56,40 +52,41 @@ private object MapAgentToParameters(AgentDocument agent) agent.Model, agent.Description, agent.Started, - Context = agent.Context != null ? - JsonSerializer.Serialize(agent.Context, _jsonOptions) : null, + Context = agent.Config is not null + ? JsonSerializer.Serialize(agent.Config, _jsonOptions) + : null, agent.ChatId, agent.Order, BackendType = agent.Backend ?? 0, - Behaviours = agent.Behaviours != null ? - JsonSerializer.Serialize(agent.Behaviours, _jsonOptions) : null, + Behaviours = agent.Behaviours is not null + ? JsonSerializer.Serialize(agent.Behaviours, _jsonOptions) + : null, agent.CurrentBehaviour, agent.Flow, }; } - public async Task> GetAllAgents() + public async Task> GetAllAgents() { var rows = await _connection.QueryAsync(@" SELECT * FROM Agents"); - return rows.Select(MapAgentDocument); + return rows.Select(MapAgentDocument).Select(x => x.ToDomain()); } - public async Task GetAgentById(string id) + public async Task GetAgentById(string id) { var row = await _connection.QueryFirstOrDefaultAsync(@" - SELECT * FROM Agents + SELECT * FROM Agents WHERE Id = @Id", new { Id = id }); - return row != null ? MapAgentDocument(row) : null; + return row is not null ? MapAgentDocument(row).ToDomain() : null; } - public async Task AddAgent(AgentDocument agent) + public async Task AddAgent(Agent agent) { - if (agent == null) - throw new ArgumentNullException(nameof(agent)); + ArgumentNullException.ThrowIfNull(agent); - var parameters = MapAgentToParameters(agent); + var parameters = MapAgentToParameters(agent.ToDocument()); await _connection.ExecuteAsync(@" INSERT INTO Agents ( Id, Name, Model, Description, Started, Context, @@ -102,14 +99,13 @@ INSERT INTO Agents ( parameters); } - public async Task UpdateAgent(string id, AgentDocument agent) + public async Task UpdateAgent(string id, Agent agent) { - if (agent == null) - throw new ArgumentNullException(nameof(agent)); + ArgumentNullException.ThrowIfNull(agent); - var parameters = MapAgentToParameters(agent); + var parameters = MapAgentToParameters(agent.ToDocument()); await _connection.ExecuteAsync(@" - UPDATE Agents + UPDATE Agents SET Name = @Name, Model = @Model, Description = @Description, @@ -127,28 +123,27 @@ UPDATE Agents public async Task DeleteAgent(string id) => await _connection.ExecuteAsync(@" - DELETE FROM Agents + DELETE FROM Agents WHERE Id = @Id", new { Id = id }); public async Task Exists(string id) { var count = await _connection.ExecuteScalarAsync(@" - SELECT COUNT(*) - FROM Agents + SELECT COUNT(*) + FROM Agents WHERE Id = @Id", new { Id = id }); return count > 0; } - // Optional: Add methods for JSON-specific queries - public async Task> GetAgentsByBehaviour(string key, string value) + public async Task> GetAgentsByBehaviour(string key, string value) { var rows = await _connection.QueryAsync(@" SELECT * FROM Agents WHERE JSON_VALUE(Behaviours, '$." + key + @"') = @value", new { value }); - return rows.Select(MapAgentDocument); + return rows.Select(MapAgentDocument).Select(x => x.ToDomain()); } -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Repositories/Sql/SqlChatRepository.cs b/src/MaIN.Infrastructure/Repositories/Sql/SqlChatRepository.cs index 2527102b..4089d708 100644 --- a/src/MaIN.Infrastructure/Repositories/Sql/SqlChatRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/Sql/SqlChatRepository.cs @@ -1,6 +1,8 @@ using Dapper; +using MaIN.Domain.Entities; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; using System.Data; using System.Text.Json; @@ -63,43 +65,43 @@ private object MapChatToParameters(ChatDocument chat) }; } - public async Task> GetAllChats() + public async Task> GetAllChats() { var rows = await connection.QueryAsync(@" SELECT * FROM Chats"); - return rows.Select(MapChatDocument); + return rows.Select(MapChatDocument).Select(x => x.ToDomain()); } - public async Task GetChatById(string id) + public async Task GetChatById(string id) { var row = await connection.QueryFirstOrDefaultAsync(@" - SELECT * FROM Chats + SELECT * FROM Chats WHERE Id = @Id", new { Id = id }); - return row is not null ? MapChatDocument(row) : null; + return row is not null ? MapChatDocument(row).ToDomain() : null; } - public async Task AddChat(ChatDocument chat) + public async Task AddChat(Chat chat) { ArgumentNullException.ThrowIfNull(chat); - var parameters = MapChatToParameters(chat); + var parameters = MapChatToParameters(chat.ToDocument()); await connection.ExecuteAsync(@" INSERT INTO Chats ( - Id, Name, Model, Messages, Type, Properties, + Id, Name, Model, Messages, Type, Properties, Stream, Visual, ConvState, InferenceParams, MemoryParams, Interactive ) VALUES ( - @Id, @Name, @Model, @Messages, @Type, @Properties, + @Id, @Name, @Model, @Messages, @Type, @Properties, @Visual, @ConvState, @InferenceParams, @MemoryParams, @Interactive)", parameters); } - public async Task UpdateChat(string id, ChatDocument chat) + public async Task UpdateChat(string id, Chat chat) { ArgumentNullException.ThrowIfNull(chat); - var parameters = MapChatToParameters(chat); + var parameters = MapChatToParameters(chat.ToDocument()); await connection.ExecuteAsync(@" - UPDATE Chats + UPDATE Chats SET Name = @Name, Model = @Model, Messages = @Messages, @@ -113,8 +115,7 @@ UPDATE Chats public async Task DeleteChat(string id) => await connection.ExecuteAsync(@" - DELETE FROM Chats + DELETE FROM Chats WHERE Id = @Id", new { Id = id }); - } diff --git a/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteAgentFlowRepository.cs b/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteAgentFlowRepository.cs index a9821357..77bc0428 100644 --- a/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteAgentFlowRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteAgentFlowRepository.cs @@ -1,8 +1,10 @@ -using System.Data; -using System.Text.Json; using Dapper; +using MaIN.Domain.Entities.Agents.AgentSource; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; +using System.Data; +using System.Text.Json; namespace MaIN.Infrastructure.Repositories.Sqlite; @@ -19,9 +21,9 @@ private AgentFlowDocument MapAgentFlowDocument(dynamic row) { Id = row.Id, Name = row.Name, - Agents = row.Agents != null ? - JsonSerializer.Deserialize>(row.Agents, _jsonOptions) : - new List(), + Agents = row.Agents is not null + ? JsonSerializer.Deserialize>(row.Agents, _jsonOptions) + : new List(), Description = row.Description }; return flow; @@ -29,41 +31,39 @@ private AgentFlowDocument MapAgentFlowDocument(dynamic row) private object MapAgentFlowToParameters(AgentFlowDocument flow) { - if (flow == null) - throw new ArgumentNullException(nameof(flow)); + ArgumentNullException.ThrowIfNull(flow); return new { flow.Id, flow.Name, - Agents = JsonSerializer.Serialize(flow.Agents ?? new List(), _jsonOptions), + Agents = JsonSerializer.Serialize(flow.Agents ?? [], _jsonOptions), flow.Description, CreatedAt = DateTime.UtcNow.ToString("O"), UpdatedAt = DateTime.UtcNow.ToString("O") }; } - public async Task> GetAllFlows() + public async Task> GetAllFlows() { var rows = await connection.QueryAsync( "SELECT * FROM AgentFlows"); - return rows.Select(MapAgentFlowDocument); + return rows.Select(MapAgentFlowDocument).Select(x => x.ToDomain()); } - public async Task GetFlowById(string id) + public async Task GetFlowById(string id) { var row = await connection.QueryFirstOrDefaultAsync( "SELECT * FROM AgentFlows WHERE Id = @Id", new { Id = id }); - return row != null ? MapAgentFlowDocument(row) : null; + return row is not null ? MapAgentFlowDocument(row).ToDomain() : null; } - public async Task AddFlow(AgentFlowDocument flow) + public async Task AddFlow(AgentFlow flow) { - if (flow == null) - throw new ArgumentNullException(nameof(flow)); + ArgumentNullException.ThrowIfNull(flow); - var parameters = MapAgentFlowToParameters(flow); + var parameters = MapAgentFlowToParameters(flow.ToDocument()); await connection.ExecuteAsync(@" INSERT INTO AgentFlows ( Id, Name, Agents, Description, CreatedAt, UpdatedAt @@ -72,14 +72,13 @@ INSERT INTO AgentFlows ( )", parameters); } - public async Task UpdateFlow(string id, AgentFlowDocument flow) + public async Task UpdateFlow(string id, AgentFlow flow) { - if (flow == null) - throw new ArgumentNullException(nameof(flow)); + ArgumentNullException.ThrowIfNull(flow); - var parameters = MapAgentFlowToParameters(flow); + var parameters = MapAgentFlowToParameters(flow.ToDocument()); await connection.ExecuteAsync(@" - UPDATE AgentFlows + UPDATE AgentFlows SET Name = @Name, Agents = @Agents, Description = @Description, @@ -91,4 +90,4 @@ public async Task DeleteFlow(string id) => await connection.ExecuteAsync( "DELETE FROM AgentFlows WHERE Id = @Id", new { Id = id }); -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteAgentRepository.cs b/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteAgentRepository.cs index e95bd292..51de02cd 100644 --- a/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteAgentRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteAgentRepository.cs @@ -1,9 +1,11 @@ -using System.Data; -using System.Text.Json; using Dapper; using MaIN.Domain.Configuration; +using MaIN.Domain.Entities.Agents; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; +using System.Data; +using System.Text.Json; namespace MaIN.Infrastructure.Repositories.Sqlite; @@ -23,15 +25,15 @@ private AgentDocument MapAgentDocument(dynamic row) Model = row.Model, Description = row.Description, Started = Convert.ToBoolean((int)row.Started), - Context = row.Context != null ? - JsonSerializer.Deserialize(row.Context, _jsonOptions) : - null, + Config = row.Context is not null + ? JsonSerializer.Deserialize(row.Context, _jsonOptions) + : null, ChatId = row.ChatId, Order = (int)row.Order, Backend = (BackendType)row.BackendType, - Behaviours = row.Behaviours != null ? - JsonSerializer.Deserialize>(row.Behaviours, _jsonOptions) : - new Dictionary(), + Behaviours = row.Behaviours is not null + ? JsonSerializer.Deserialize>(row.Behaviours, _jsonOptions) + : new Dictionary(), CurrentBehaviour = row.CurrentBehaviour, Flow = Convert.ToBoolean((int)row.Flow) }; @@ -40,8 +42,7 @@ private AgentDocument MapAgentDocument(dynamic row) private object MapAgentToParameters(AgentDocument agent) { - if (agent == null) - throw new ArgumentNullException(nameof(agent)); + ArgumentNullException.ThrowIfNull(agent); return new { @@ -50,42 +51,39 @@ private object MapAgentToParameters(AgentDocument agent) agent.Model, agent.Description, Started = agent.Started ? 1 : 0, - Context = agent.Context != null ? - JsonSerializer.Serialize(agent.Context, _jsonOptions) : null, + Context = agent.Config is not null ? JsonSerializer.Serialize(agent.Config, _jsonOptions) : null, agent.ChatId, agent.Order, BackendType = agent.Backend, - Behaviours = agent.Behaviours != null ? - JsonSerializer.Serialize(agent.Behaviours, _jsonOptions) : null, + Behaviours = agent.Behaviours is not null ? JsonSerializer.Serialize(agent.Behaviours, _jsonOptions) : null, agent.CurrentBehaviour, Flow = agent.Flow ? 1 : 0 }; } - public async Task> GetAllAgents() + public async Task> GetAllAgents() { var rows = await connection.QueryAsync( "SELECT * FROM Agents"); - return rows.Select(MapAgentDocument); + return rows.Select(MapAgentDocument).Select(x => x.ToDomain()); } - public async Task GetAgentById(string id) + public async Task GetAgentById(string id) { var row = await connection.QueryFirstOrDefaultAsync( "SELECT * FROM Agents WHERE Id = @Id", new { Id = id }); - return row != null ? MapAgentDocument(row) : null; + return row is not null ? MapAgentDocument(row).ToDomain() : null; } - public async Task AddAgent(AgentDocument agent) + public async Task AddAgent(Agent agent) { - if (agent == null) - throw new ArgumentNullException(nameof(agent)); + ArgumentNullException.ThrowIfNull(agent); - var parameters = MapAgentToParameters(agent); + var parameters = MapAgentToParameters(agent.ToDocument()); await connection.ExecuteAsync(@" INSERT INTO Agents ( - Id, Name, Model, Description, Started, Context, + Id, Name, Model, Description, Started, Context, ChatId, [Order], Behaviours, CurrentBehaviour, Flow ) VALUES ( @Id, @Name, @Model, @Description, @Started, @Context, @@ -93,14 +91,13 @@ INSERT INTO Agents ( )", parameters); } - public async Task UpdateAgent(string id, AgentDocument agent) + public async Task UpdateAgent(string id, Agent agent) { - if (agent == null) - throw new ArgumentNullException(nameof(agent)); + ArgumentNullException.ThrowIfNull(agent); - var parameters = MapAgentToParameters(agent); + var parameters = MapAgentToParameters(agent.ToDocument()); await connection.ExecuteAsync(@" - UPDATE Agents + UPDATE Agents SET Name = @Name, Model = @Model, Description = @Description, @@ -126,4 +123,4 @@ public async Task Exists(string id) new { Id = id }); return count > 0; } -} \ No newline at end of file +} diff --git a/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteChatRepository.cs b/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteChatRepository.cs index 420bd319..6f81a55c 100644 --- a/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteChatRepository.cs +++ b/src/MaIN.Infrastructure/Repositories/Sqlite/SqliteChatRepository.cs @@ -1,7 +1,8 @@ using Dapper; using MaIN.Domain.Entities; +using MaIN.Infrastructure.Mappers; using MaIN.Infrastructure.Models; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; using System.Data; using System.Text.Json; @@ -34,7 +35,7 @@ private ChatDocument MapChatDocument(dynamic row) ? JsonSerializer.Deserialize(row.InferenceParams, _jsonOptions) : default, MemoryParams = row.MemoryParams is not null - ? JsonSerializer.Deserialize(row.MemoryParams, _jsonOptions) + ? JsonSerializer.Deserialize(row.MemoryParams, _jsonOptions) : default, Properties = row.Properties is not null ? JsonSerializer.Deserialize>(row.Properties, _jsonOptions) @@ -61,34 +62,34 @@ private object MapChatToParameters(ChatDocument chat) => Interactive = chat.Interactive ? 1 : 0 }; - public async Task> GetAllChats() + public async Task> GetAllChats() { var rows = await connection.QueryAsync( "SELECT * FROM Chats"); - return rows.Select(MapChatDocument); + return rows.Select(MapChatDocument).Select(x => x.ToDomain()); } - public async Task GetChatById(string id) + public async Task GetChatById(string id) { var row = await connection.QueryFirstOrDefaultAsync( "SELECT * FROM Chats WHERE Id = @Id", new { Id = id }); - return row is not null ? MapChatDocument(row) : null; + return row is not null ? MapChatDocument(row).ToDomain() : null; } - public async Task AddChat(ChatDocument chat) + public async Task AddChat(Chat chat) { - var parameters = MapChatToParameters(chat); + var parameters = MapChatToParameters(chat.ToDocument()); await connection.ExecuteAsync(@" - INSERT INTO Chats (Id, Name, Model, Messages, [Type], Properties, Visual, ConvState, InferenceParams, MemoryParams, Interactive) VALUES (@Id, @Name, @Model, @Messages, @Type, @Properties, + INSERT INTO Chats (Id, Name, Model, Messages, [Type], Properties, Visual, ConvState, InferenceParams, MemoryParams, Interactive) VALUES (@Id, @Name, @Model, @Messages, @Type, @Properties, @Visual, @ConvState, @InferenceParams, @MemoryParams, @Interactive)", parameters); } - public async Task UpdateChat(string id, ChatDocument chat) + public async Task UpdateChat(string id, Chat chat) { - var parameters = MapChatToParameters(chat); + var parameters = MapChatToParameters(chat.ToDocument()); await connection.ExecuteAsync(@" - UPDATE Chats + UPDATE Chats SET Name = @Name, Model = @Model, Messages = @Messages, diff --git a/src/MaIN.Services/Bootstrapper.cs b/src/MaIN.Services/Bootstrapper.cs index 7eefd3f2..6e218c2c 100644 --- a/src/MaIN.Services/Bootstrapper.cs +++ b/src/MaIN.Services/Bootstrapper.cs @@ -1,6 +1,5 @@ using MaIN.Domain.Configuration; using MaIN.Domain.Entities; -using MaIN.Infrastructure; using MaIN.Services.Constants; using MaIN.Services.Services; using MaIN.Services.Services.Abstract; @@ -64,9 +63,6 @@ public static IServiceCollection ConfigureMaIN( // Register the step processor serviceCollection.AddSingleton(); - // Register the infrastructure - serviceCollection.ConfigureInfrastructure(configuration); - return serviceCollection; } diff --git a/src/MaIN.Services/Dtos/Rag/AgentContextDto.cs b/src/MaIN.Services/Dtos/Rag/AgentConfigDto.cs similarity index 93% rename from src/MaIN.Services/Dtos/Rag/AgentContextDto.cs rename to src/MaIN.Services/Dtos/Rag/AgentConfigDto.cs index d6024042..5d40d598 100644 --- a/src/MaIN.Services/Dtos/Rag/AgentContextDto.cs +++ b/src/MaIN.Services/Dtos/Rag/AgentConfigDto.cs @@ -1,9 +1,9 @@ -using System.Text.Json.Serialization; using MaIN.Services.Dtos.Rag.AgentSource; +using System.Text.Json.Serialization; namespace MaIN.Services.Dtos.Rag; -public class AgentContextDto +public class AgentConfigDto { [JsonPropertyName("instruction")] public string Instruction { get; init; } = null!; @@ -16,5 +16,4 @@ public class AgentContextDto [JsonPropertyName("relations")] public List? Relations { get; init; } - -} \ No newline at end of file +} diff --git a/src/MaIN.Services/Dtos/Rag/AgentDto.cs b/src/MaIN.Services/Dtos/Rag/AgentDto.cs index bd432424..3fb0aae4 100644 --- a/src/MaIN.Services/Dtos/Rag/AgentDto.cs +++ b/src/MaIN.Services/Dtos/Rag/AgentDto.cs @@ -15,13 +15,13 @@ public class AgentDto public string? Description { get; init; } [JsonPropertyName("started")] public bool Started { get; init; } - [JsonPropertyName("context")] - public AgentContextDto Context { get; init; } = null!; + [JsonPropertyName("config")] + public AgentConfigDto Config { get; init; } = null!; [JsonPropertyName("order")] public int Order { get; init; } [JsonPropertyName("behaviours")] public Dictionary Behaviours { get; init; } = []; [JsonPropertyName("currentBehaviour")] public string CurrentBehaviour { get; init; } = null!; - [JsonPropertyName("flow")] public bool Flow { get; init; } -} \ No newline at end of file + [JsonPropertyName("flow")] public bool Flow { get; init; } +} diff --git a/src/MaIN.Services/MaIN.Services.csproj b/src/MaIN.Services/MaIN.Services.csproj index 9e0ad478..f9ab3244 100644 --- a/src/MaIN.Services/MaIN.Services.csproj +++ b/src/MaIN.Services/MaIN.Services.csproj @@ -9,7 +9,6 @@ - diff --git a/src/MaIN.Services/Mappers/AgentFlowMapper.cs b/src/MaIN.Services/Mappers/AgentFlowMapper.cs index b376d8a5..f5c37fc9 100644 --- a/src/MaIN.Services/Mappers/AgentFlowMapper.cs +++ b/src/MaIN.Services/Mappers/AgentFlowMapper.cs @@ -1,5 +1,4 @@ using MaIN.Domain.Entities.Agents.AgentSource; -using MaIN.Infrastructure.Models; using MaIN.Services.Dtos.Rag; namespace MaIN.Services.Mappers; @@ -25,31 +24,4 @@ public static AgentFlow ToDomain(this AgentFlowDto agentFlow) => Description = agentFlow.Description, Agents = agentFlow.Agents.Select(x => x.ToDomain()).ToList() }; - - public static AgentFlow ToDomain(this AgentFlowDocument agentFlow) => - new() - { - Id = agentFlow.Id, - Name = agentFlow.Name, - Description = agentFlow.Description, - Agents = agentFlow.Agents.Select(x => x.ToDomain()).ToList() - }; - - public static AgentFlowDocument ToDocument(this AgentFlow agentFlow) => - new() - { - Id = agentFlow.Id!, - Name = agentFlow.Name, - Description = agentFlow.Description!, - Agents = agentFlow.Agents.Select(x => x.ToDocument()).ToList() - }; - - public static AgentFlow FromDocument(this AgentFlowDocument agentFlow) => - new() - { - Id = agentFlow.Id, - Name = agentFlow.Name, - Description = agentFlow.Description, - Agents = agentFlow.Agents.Select(x => x.ToDomain()).ToList() - }; -} \ No newline at end of file +} diff --git a/src/MaIN.Services/Mappers/AgentMapper.cs b/src/MaIN.Services/Mappers/AgentMapper.cs index 87503f8c..a28bcd87 100644 --- a/src/MaIN.Services/Mappers/AgentMapper.cs +++ b/src/MaIN.Services/Mappers/AgentMapper.cs @@ -1,7 +1,5 @@ -using System.Text.Json; using MaIN.Domain.Entities.Agents; using MaIN.Domain.Entities.Agents.AgentSource; -using MaIN.Infrastructure.Models; using MaIN.Services.Dtos.Rag; using MaIN.Services.Dtos.Rag.AgentSource; @@ -21,20 +19,20 @@ public static AgentDto ToDto(this Agent agent) Description = agent.Description, Behaviours = agent.Behaviours, CurrentBehaviour = agent.CurrentBehaviour, - Context = agent.Context.ToDto() + Config = agent.Config.ToDto() }; - public static AgentContextDto ToDto(this AgentData agentContext) + public static AgentConfigDto ToDto(this AgentConfig agentConfig) => new() { - Instruction = agentContext.Instruction!, - Relations = agentContext.Relations, - Steps = agentContext.Steps ?? [], - Source = (agentContext.Source is not null ? new AgentSourceDto() + Instruction = agentConfig.Instruction!, + Relations = agentConfig.Relations, + Steps = agentConfig.Steps ?? [], + Source = (agentConfig.Source is not null ? new AgentSourceDto() { - Details = agentContext.Source?.Details, - AdditionalMessage = agentContext?.Source?.AdditionalMessage, - Type = Enum.Parse(agentContext?.Source?.Type.ToString()!) + Details = agentConfig.Source?.Details, + AdditionalMessage = agentConfig?.Source?.AdditionalMessage, + Type = Enum.Parse(agentConfig?.Source?.Type.ToString()!) } : null)! }; @@ -50,98 +48,20 @@ public static Agent ToDomain(this AgentDto agent) Description = agent.Description, Behaviours = agent.Behaviours, CurrentBehaviour = agent.CurrentBehaviour, - Context = agent.Context.ToDomain() + Config = agent.Config.ToDomain() }; - public static AgentData ToDomain(this AgentContextDto agentContextDto) + public static AgentConfig ToDomain(this AgentConfigDto agentConfigDto) => new() { - Instruction = agentContextDto.Instruction, - Relations = agentContextDto?.Relations, - Source = agentContextDto?.Source is not null ? new AgentSource() + Instruction = agentConfigDto.Instruction, + Relations = agentConfigDto?.Relations, + Source = agentConfigDto?.Source is not null ? new AgentSource() { - Details = agentContextDto?.Source?.Details, - AdditionalMessage = agentContextDto?.Source?.AdditionalMessage, - Type = Enum.Parse(agentContextDto?.Source?.Type.ToString()!) + Details = agentConfigDto?.Source?.Details, + AdditionalMessage = agentConfigDto?.Source?.AdditionalMessage, + Type = Enum.Parse(agentConfigDto?.Source?.Type.ToString()!) } : null, - Steps = agentContextDto!.Steps + Steps = agentConfigDto!.Steps }; - - private static AgentSourceDetailsBase MapDetailsToType(object? details, AgentSourceTypeDto? sourceDetailsType) - { - return sourceDetailsType switch - { - AgentSourceTypeDto.Text => (AgentTextSourceDetails)details!, - AgentSourceTypeDto.File => (AgentFileSourceDetails)details!, - AgentSourceTypeDto.API => (AgentApiSourceDetails)details!, - AgentSourceTypeDto.Web => (AgentWebSourceDetails)details!, - //TBD add all types - _ => new() - }; - } - - public static AgentContextDocument ToDocument(this AgentData context) - => new() - { - Instruction = context.Instruction, - Relations = context.Relations?.ToList(), - Steps = context.Steps!.ToList(), - McpConfig = context.McpConfig, - Source = context.Source is not null ? new AgentSourceDocument() - { - DetailsSerialized = JsonSerializer.Serialize(context.Source.Details), - AdditionalMessage = context.Source.AdditionalMessage, - Type = Enum.Parse(context.Source.Type.ToString()) - } : null - }; - - public static AgentDocument ToDocument(this Agent agent) - => new() - { - Id = agent.Id, - Name = agent.Name, - Model = agent.Model, - Order = agent.Order, - Started = agent.Started, - Flow = agent.Flow, - ToolsConfiguration = agent.ToolsConfiguration, - Backend = agent.Backend, - ChatId = agent.ChatId, - Description = agent.Description, - Behaviours = agent.Behaviours, - CurrentBehaviour = agent.CurrentBehaviour, - Context = agent.Context.ToDocument() - }; - - public static Agent ToDomain(this AgentDocument agent) - => new() - { - Id = agent.Id, - Name = agent.Name, - Model = agent.Model, - Started = agent.Started, - Order = agent.Order, - Flow = agent.Flow, - ToolsConfiguration = agent.ToolsConfiguration, - Backend = agent.Backend, - Description = agent.Description, - Behaviours = agent.Behaviours, - CurrentBehaviour = agent.CurrentBehaviour, - Context = agent.Context!.ToDomain() - }; - - public static AgentData ToDomain(this AgentContextDocument agentContextDocument) - => new() - { - Instruction = agentContextDocument.Instruction, - Relations = agentContextDocument.Relations, - McpConfig = agentContextDocument.McpConfig, - Source = new AgentSource - { - AdditionalMessage = agentContextDocument.Source?.AdditionalMessage, - Details = agentContextDocument.Source?.DetailsSerialized, - Type = Enum.Parse(agentContextDocument.Source?.Type.ToString() ?? AgentSourceType.Text.ToString()) - }, - Steps = agentContextDocument.Steps - }; -} \ No newline at end of file +} diff --git a/src/MaIN.Services/Mappers/ChatMapper.cs b/src/MaIN.Services/Mappers/ChatMapper.cs index 802d34bb..3955beca 100644 --- a/src/MaIN.Services/Mappers/ChatMapper.cs +++ b/src/MaIN.Services/Mappers/ChatMapper.cs @@ -1,7 +1,5 @@ -using LLama.Batched; using MaIN.Domain.Entities; using MaIN.Domain.Models; -using MaIN.Infrastructure.Models; using MaIN.Services.Dtos; using MaIN.Services.Services.ImageGenServices; using FileInfo = MaIN.Domain.Entities.FileInfo; @@ -67,145 +65,4 @@ private static Message ToDomain(this MessageDto message) Extension = x.Extension }).ToList() }; - - private static MessageDocument ToDocument(this Message message) - => new() - { - Content = message.Content, - Role = message.Role, - Time = message.Time, - MessageType = message.Type.ToString(), - Images = message.Image, - Tokens = [.. message.Tokens.Select(x => x.ToDocument())], - Properties = message.Properties, - Tool = message.Tool, - Files = (message.Files?.Select(x => x.Content).ToArray() ?? [])! - }; - - public static ChatDocument ToDocument(this Chat chat) - => new() - { - Id = chat.Id, - Name = chat.Name, - Model = chat.ModelId, - Messages = [.. chat.Messages.Select(m => m.ToDocument())], - ImageGen = chat.ImageGen, - ToolsConfiguration = chat.ToolsConfiguration, - MemoryParams = chat.MemoryParams.ToDocument(), - InferenceParams = chat.InterferenceParams.ToDocument(), - ConvState = chat.ConversationState, - Properties = chat.Properties, - Interactive = chat.Interactive, - Translate = chat.Translate, - Type = Enum.Parse(chat.Type.ToString()) - }; - - public static Chat ToDomain(this ChatDocument chat) - => new() - { - Id = chat.Id, - Name = chat.Name, - ModelId = chat.Model, - Messages = [.. chat.Messages.Select(m => m.ToDomain())], - ImageGen = chat.ImageGen, - Properties = chat.Properties, - ToolsConfiguration = chat.ToolsConfiguration, - ConversationState = chat.ConvState as Conversation.State, - MemoryParams = chat.MemoryParams!.ToDomain(), - InterferenceParams = chat.InferenceParams!.ToDomain(), - Interactive = chat.Interactive, - Translate = chat.Translate, - Type = Enum.Parse(chat.Type.ToString()) - }; - - private static Message ToDomain(this MessageDocument message) - => new() - { - Content = message.Content, - Tool = message.Tool, - Time = message.Time, - Type = Enum.Parse(message.MessageType), - Tokens = [.. message.Tokens.Select(x => x.ToDomain())], - Role = message.Role, - Image = message.Images, - Properties = message.Properties, - }; - - private static LLMTokenValueDocument ToDocument(this LLMTokenValue llmTokenValue) - => new() - { - Text = llmTokenValue.Text, - Type = llmTokenValue.Type - }; - - private static LLMTokenValue ToDomain(this LLMTokenValueDocument llmTokenValue) - => new() - { - Text = llmTokenValue.Text, - Type = llmTokenValue.Type - }; - - private static InferenceParams ToDomain(this InferenceParamsDocument inferenceParams) - => new() - { - Temperature = inferenceParams.Temperature, - ContextSize = inferenceParams.ContextSize, - GpuLayerCount = inferenceParams.GpuLayerCount, - SeqMax = inferenceParams.SeqMax, - BatchSize = inferenceParams.BatchSize, - UBatchSize = inferenceParams.UBatchSize, - Embeddings = inferenceParams.Embeddings, - TypeK = inferenceParams.TypeK, - TypeV = inferenceParams.TypeV, - TokensKeep = inferenceParams.TokensKeep, - MaxTokens = inferenceParams.MaxTokens, - TopK = inferenceParams.TopK, - TopP = inferenceParams.TopP, - Grammar = inferenceParams.Grammar - }; - - private static MemoryParams ToDomain(this MemoryParamsDocument memoryParams) - => new() - { - Temperature = memoryParams.Temperature, - AnswerTokens = memoryParams.AnswerTokens, - MultiModalMode = memoryParams.MultiModalMode, - ContextSize = memoryParams.ContextSize, - GpuLayerCount = memoryParams.GpuLayerCount, - MaxMatchesCount = memoryParams.MaxMatchesCount, - FrequencyPenalty = memoryParams.FrequencyPenalty, - Grammar = memoryParams.Grammar - }; - - private static InferenceParamsDocument ToDocument(this InferenceParams inferenceParams) - => new() - { - Temperature = inferenceParams.Temperature, - ContextSize = inferenceParams.ContextSize, - GpuLayerCount = inferenceParams.GpuLayerCount, - SeqMax = inferenceParams.SeqMax, - BatchSize = inferenceParams.BatchSize, - UBatchSize = inferenceParams.UBatchSize, - Embeddings = inferenceParams.Embeddings, - TypeK = inferenceParams.TypeK, - TypeV = inferenceParams.TypeV, - TokensKeep = inferenceParams.TokensKeep, - MaxTokens = inferenceParams.MaxTokens, - TopK = inferenceParams.TopK, - TopP = inferenceParams.TopP, - Grammar = inferenceParams.Grammar - }; - - private static MemoryParamsDocument ToDocument(this MemoryParams memoryParams) - => new() - { - Temperature = memoryParams.Temperature, - AnswerTokens = memoryParams.AnswerTokens, - MultiModalMode = memoryParams.MultiModalMode, - ContextSize = memoryParams.ContextSize, - GpuLayerCount = memoryParams.GpuLayerCount, - MaxMatchesCount = memoryParams.MaxMatchesCount, - FrequencyPenalty = memoryParams.FrequencyPenalty, - Grammar = memoryParams.Grammar - }; } diff --git a/src/MaIN.Services/Services/Abstract/IStepProcessor.cs b/src/MaIN.Services/Services/Abstract/IStepProcessor.cs index 3de00256..867be90d 100644 --- a/src/MaIN.Services/Services/Abstract/IStepProcessor.cs +++ b/src/MaIN.Services/Services/Abstract/IStepProcessor.cs @@ -1,16 +1,16 @@ using MaIN.Domain.Entities; +using MaIN.Domain.Entities.Agents; using MaIN.Domain.Entities.Agents.Knowledge; using MaIN.Domain.Entities.Tools; using MaIN.Domain.Models; -using MaIN.Infrastructure.Models; using Microsoft.Extensions.Logging; namespace MaIN.Services.Services.Abstract; public interface IStepProcessor { - Task ProcessSteps(AgentContextDocument context, - AgentDocument agent, + Task ProcessSteps(AgentConfig context, + Agent agent, Knowledge? knowledge, Chat chat, Func? callback, @@ -18,4 +18,4 @@ Task ProcessSteps(AgentContextDocument context, Func notifyProgress, Func updateChat, ILogger logger); -} \ No newline at end of file +} diff --git a/src/MaIN.Services/Services/AgentFlowService.cs b/src/MaIN.Services/Services/AgentFlowService.cs index b6937111..db1fffd7 100644 --- a/src/MaIN.Services/Services/AgentFlowService.cs +++ b/src/MaIN.Services/Services/AgentFlowService.cs @@ -1,7 +1,6 @@ using MaIN.Domain.Entities.Agents.AgentSource; using MaIN.Domain.Exceptions.Agents; -using MaIN.Infrastructure.Repositories.Abstract; -using MaIN.Services.Mappers; +using MaIN.Domain.Repositories; using MaIN.Services.Services.Abstract; namespace MaIN.Services.Services; @@ -11,26 +10,20 @@ public class AgentFlowService(IAgentFlowRepository flowRepository, IAgentService public async Task GetFlowById(string id) { var flow = await flowRepository.GetFlowById(id); - if (flow is null) - { - throw new AgentFlowNotFoundException(id); - } - - return flow.ToDomain(); + return flow is null ? throw new AgentFlowNotFoundException(id) : flow; } - public async Task> GetAllFlows() - => (await flowRepository.GetAllFlows()).Select(x => x.ToDomain()).ToList(); + public async Task> GetAllFlows() => [.. await flowRepository.GetAllFlows()]; public async Task CreateFlow(AgentFlow flow) { flow.Id ??= Guid.NewGuid().ToString(); - await flowRepository.AddFlow(flow.ToDocument()); + await flowRepository.AddFlow(flow); foreach (var agent in flow.Agents) { await agentService.CreateAgent(agent, true); } - + return flow; } @@ -41,7 +34,7 @@ public async Task DeleteFlow(string id) { await agentService.DeleteAgent(agent.Id); } - + await flowRepository.DeleteFlow(id); } -} \ No newline at end of file +} diff --git a/src/MaIN.Services/Services/AgentService.cs b/src/MaIN.Services/Services/AgentService.cs index 4b92ed30..80d6af48 100644 --- a/src/MaIN.Services/Services/AgentService.cs +++ b/src/MaIN.Services/Services/AgentService.cs @@ -6,9 +6,8 @@ using MaIN.Domain.Exceptions.Agents; using MaIN.Domain.Models; using MaIN.Domain.Models.Abstract; -using MaIN.Infrastructure.Repositories.Abstract; +using MaIN.Domain.Repositories; using MaIN.Services.Constants; -using MaIN.Services.Mappers; using MaIN.Services.Services.Abstract; using MaIN.Services.Services.ImageGenServices; using MaIN.Services.Services.LLMService.Factory; @@ -42,11 +41,6 @@ public async Task Process( { var agent = await agentRepository.GetAgentById(agentId) ?? throw new AgentNotFoundException(agentId); - if (agent.Context is null) - { - throw new AgentContextNotFoundException(agentId); - } - await notificationService.DispatchNotification( NotificationMessageBuilder.ProcessingStarted( agentId, @@ -57,7 +51,7 @@ await notificationService.DispatchNotification( try { chat = await stepProcessor.ProcessSteps( - agent.Context, + agent.Config, agent, knowledge, chat, @@ -69,7 +63,7 @@ await notificationService.DispatchNotification( NotificationMessageBuilder.CreateActorProgress(id, status, progress, behaviour, details), "ReceiveAgentUpdate"); //TODO prepare static lookup for magic string :) }, - async c => await chatRepository.UpdateChat(c.Id, c.ToDocument()), + async c => await chatRepository.UpdateChat(c.Id, c), logger ); @@ -125,7 +119,7 @@ public async Task CreateAgent(Agent agent, bool flow = false, bool intera var startCommand = new StartCommand { Chat = chat, - InitialPrompt = agent.Context.Instruction + InitialPrompt = agent.Config.Instruction }; await commandDispatcher.DispatchAsync(startCommand); @@ -134,11 +128,11 @@ public async Task CreateAgent(Agent agent, bool flow = false, bool intera agent.Flow = flow; agent.ChatId = chat.Id; agent.Behaviours ??= []; - agent.Behaviours.Add("Default", agent.Context.Instruction!); + agent.Behaviours.Add("Default", agent.Config.Instruction!); agent.CurrentBehaviour = "Default"; - await chatRepository.AddChat(chat.ToDocument()); - await agentRepository.AddAgent(agent.ToDocument()); + await chatRepository.AddChat(chat); + await agentRepository.AddAgent(agent); return agent; } @@ -148,14 +142,14 @@ public async Task GetChatByAgent(string agentId) var agent = await agentRepository.GetAgentById(agentId) ?? throw new AgentNotFoundException(agentId); var chat = await chatRepository.GetChatById(agent.ChatId); - return chat!.ToDomain(); + return chat!; } public async Task Restart(string agentId) { var agent = await agentRepository.GetAgentById(agentId) ?? throw new AgentNotFoundException(agentId); - var chat = (await chatRepository.GetChatById(agent.ChatId))!.ToDomain(); + var chat = (await chatRepository.GetChatById(agent.ChatId))!; var backend = ModelRegistry.TryGetById(chat.ModelId, out var model) ? model!.Backend : maInSettings.BackendType; @@ -163,15 +157,15 @@ public async Task Restart(string agentId) await llmService.CleanSessionCache(chat.Id!); AgentStateManager.ClearState(agent, chat); - await chatRepository.UpdateChat(chat.Id!, chat.ToDocument()); + await chatRepository.UpdateChat(chat.Id!, chat); await agentRepository.UpdateAgent(agent.Id, agent); return chat; } - public async Task> GetAgents() => [.. (await agentRepository.GetAllAgents()).Select(x => x.ToDomain())]; + public async Task> GetAgents() => [.. await agentRepository.GetAllAgents()]; - public async Task GetAgentById(string id) => (await agentRepository.GetAgentById(id))?.ToDomain(); + public async Task GetAgentById(string id) => await agentRepository.GetAgentById(id); public async Task DeleteAgent(string id) { diff --git a/src/MaIN.Services/Services/ChatService.cs b/src/MaIN.Services/Services/ChatService.cs index 275bd1a3..5b1ad06e 100644 --- a/src/MaIN.Services/Services/ChatService.cs +++ b/src/MaIN.Services/Services/ChatService.cs @@ -3,8 +3,7 @@ using MaIN.Domain.Exceptions.Chats; using MaIN.Domain.Models; using MaIN.Domain.Models.Abstract; -using MaIN.Infrastructure.Repositories.Abstract; -using MaIN.Services.Mappers; +using MaIN.Domain.Repositories; using MaIN.Services.Services.Abstract; using MaIN.Services.Services.ImageGenServices; using MaIN.Services.Services.LLMService; @@ -24,7 +23,7 @@ public class ChatService( public async Task Create(Chat chat) { chat.Type = ChatType.Conversation; - await chatProvider.AddChat(chat.ToDocument()); + await chatProvider.AddChat(chat); } public async Task Completions( @@ -93,14 +92,14 @@ public async Task Completions( originalMessages.Add(result!.Message); chat.Messages = originalMessages; - await chatProvider.UpdateChat(chat.Id!, chat.ToDocument()); + await chatProvider.UpdateChat(chat.Id!, chat); return result; } public async Task Delete(string id) { - var chatDoc = await chatProvider.GetChatById(id); - var backend = chatDoc is not null && ModelRegistry.TryGetById(chatDoc.Model, out var model) + var chat = await chatProvider.GetChatById(id); + var backend = chat is not null && ModelRegistry.TryGetById(chat.ModelId, out var model) ? model!.Backend : settings.BackendType; var llmService = llmServiceFactory.CreateService(backend); @@ -110,9 +109,9 @@ public async Task Delete(string id) public async Task GetById(string id) { - var chatDocument = await chatProvider.GetChatById(id); - return chatDocument is null ? throw new ChatNotFoundException(id) : chatDocument.ToDomain(); + var chat = await chatProvider.GetChatById(id); + return chat is null ? throw new ChatNotFoundException(id) : chat; } - public async Task> GetAll() => [.. (await chatProvider.GetAllChats()).Select(x => x.ToDomain())]; + public async Task> GetAll() => [.. await chatProvider.GetAllChats()]; } diff --git a/src/MaIN.Services/Services/Models/Commands/FetchCommand.cs b/src/MaIN.Services/Services/Models/Commands/FetchCommand.cs index a565b881..34482560 100644 --- a/src/MaIN.Services/Services/Models/Commands/FetchCommand.cs +++ b/src/MaIN.Services/Services/Models/Commands/FetchCommand.cs @@ -8,7 +8,7 @@ namespace MaIN.Services.Services.Models.Commands; public class FetchCommand : BaseCommand, ICommand { public string? Filter { get; init; } - public required AgentData Context { get; init; } + public required AgentConfig Context { get; init; } public string CommandName => "FETCH_DATA"; public Chat? MemoryChat { get; set; } public FetchResponseType ResponseType { get; set; } @@ -18,4 +18,4 @@ public enum FetchResponseType { AS_Answer = 1, AS_System = 2 -} \ No newline at end of file +} diff --git a/src/MaIN.Services/Services/Models/StepContext.cs b/src/MaIN.Services/Services/Models/StepContext.cs index 2b13b1a7..89a75574 100644 --- a/src/MaIN.Services/Services/Models/StepContext.cs +++ b/src/MaIN.Services/Services/Models/StepContext.cs @@ -1,14 +1,14 @@ using MaIN.Domain.Entities; +using MaIN.Domain.Entities.Agents; using MaIN.Domain.Entities.Agents.Knowledge; using MaIN.Domain.Entities.Tools; using MaIN.Domain.Models; -using MaIN.Infrastructure.Models; namespace MaIN.Services.Services.Models; public class StepContext { - public required AgentDocument Agent { get; init; } + public required Agent Agent { get; init; } public required Chat Chat { get; init; } public required Message RedirectMessage { get; init; } public required List TagsToReplaceWithFilter { get; init; } @@ -20,4 +20,4 @@ public class StepContext public Knowledge? Knowledge { get; set; } public Func? Callback { get; set; } public Func? ToolCallback { get; set; } -} \ No newline at end of file +} diff --git a/src/MaIN.Services/Services/StepProcessor.cs b/src/MaIN.Services/Services/StepProcessor.cs index e15cc374..4bedb72e 100644 --- a/src/MaIN.Services/Services/StepProcessor.cs +++ b/src/MaIN.Services/Services/StepProcessor.cs @@ -1,8 +1,8 @@ using MaIN.Domain.Entities; +using MaIN.Domain.Entities.Agents; using MaIN.Domain.Entities.Agents.Knowledge; using MaIN.Domain.Entities.Tools; using MaIN.Domain.Models; -using MaIN.Infrastructure.Models; using MaIN.Services.Services.Abstract; using MaIN.Services.Services.Models; using Microsoft.Extensions.Logging; @@ -15,8 +15,8 @@ public class StepProcessor : IStepProcessor public StepProcessor(IEnumerable stepHandlers) { - _stepHandlers = new Dictionary(); - + _stepHandlers = []; + foreach (var handler in stepHandlers) { foreach (var supportedStep in handler.SupportedSteps) @@ -26,8 +26,8 @@ public StepProcessor(IEnumerable stepHandlers) } } - public async Task ProcessSteps(AgentContextDocument context, - AgentDocument agent, + public async Task ProcessSteps(AgentConfig context, + Agent agent, Knowledge? knowledge, Chat chat, Func? callbackToken, @@ -44,7 +44,7 @@ public async Task ProcessSteps(AgentContextDocument context, stepCount++; var lastStep = stepCount.Equals(context.Steps.Count); logger.LogInformation("Processing step: {Step} on agent {agent}", step, agent.Name); - + var (stepName, arguments) = ParseStep(step); var handler = GetStepHandler(stepName); @@ -70,14 +70,14 @@ public async Task ProcessSteps(AgentContextDocument context, { redirectMessage = result.RedirectMessage ?? redirectMessage; } - + chat = result.Chat; await updateChat(chat); } CleanupBehaviors(agent, tagsToReplaceWithFilter); - + return chat; } @@ -92,7 +92,7 @@ private IStepHandler GetStepHandler(string stepName) => ? handler : throw new InvalidOperationException($"Unknown step: {stepName}"); - private static void CleanupBehaviors(AgentDocument agent, List tagsToReplaceWithFilter) + private static void CleanupBehaviors(Agent agent, List tagsToReplaceWithFilter) { foreach (var key in agent.Behaviours.Keys.ToList()) { @@ -101,4 +101,4 @@ private static void CleanupBehaviors(AgentDocument agent, List tagsToRep (current, tag) => current.Replace(tag, "@filter@")); } } -} \ No newline at end of file +} diff --git a/src/MaIN.Services/Services/Steps/BecomeStepHandler.cs b/src/MaIN.Services/Services/Steps/BecomeStepHandler.cs index 2313e11b..901c9f85 100644 --- a/src/MaIN.Services/Services/Steps/BecomeStepHandler.cs +++ b/src/MaIN.Services/Services/Steps/BecomeStepHandler.cs @@ -20,8 +20,8 @@ public async Task Handle(StepContext context) } var newBehaviour = context.Arguments[0]; - var messageFilter = context.Agent.Behaviours.GetValueOrDefault(newBehaviour) ?? - context.Agent.Context!.Instruction; + var messageFilter = context.Agent.Behaviours.GetValueOrDefault(newBehaviour) + ?? context.Agent.Config!.Instruction; if (context.Chat.Properties.TryGetValue("data_filter", out var filterQuery)) { @@ -31,7 +31,7 @@ public async Task Handle(StepContext context) } context.Agent.CurrentBehaviour = newBehaviour; - context.Chat.Messages[0].Content = messageFilter ?? context.Agent.Context!.Instruction!; + context.Chat.Messages[0].Content = messageFilter ?? context.Agent.Config!.Instruction!; await context.NotifyProgress("true", context.Agent.Id, null, context.Agent.CurrentBehaviour, StepName); diff --git a/src/MaIN.Services/Services/Steps/FechDataStepHandler.cs b/src/MaIN.Services/Services/Steps/FechDataStepHandler.cs index 894a67ca..bd74e401 100644 --- a/src/MaIN.Services/Services/Steps/FechDataStepHandler.cs +++ b/src/MaIN.Services/Services/Steps/FechDataStepHandler.cs @@ -3,7 +3,6 @@ using MaIN.Domain.Exceptions; using MaIN.Domain.Exceptions.Agents; using MaIN.Domain.Models.Abstract; -using MaIN.Services.Mappers; using MaIN.Services.Services.Abstract; using MaIN.Services.Services.Models; using MaIN.Services.Services.Models.Commands; @@ -30,7 +29,7 @@ public async Task Handle(StepContext context) { Chat = context.Chat, Filter = filter ?? string.Empty, - Context = context.Agent.Context!.ToDomain(), + Context = context.Agent.Config!, ResponseType = respondAsSystem ? FetchResponseType.AS_System : FetchResponseType.AS_Answer, MemoryChat = CreateMemoryChat(context, filter) }; diff --git a/src/MaIN.Services/Utils/AgentStateManager.cs b/src/MaIN.Services/Utils/AgentStateManager.cs index f863daa0..3effa2a5 100644 --- a/src/MaIN.Services/Utils/AgentStateManager.cs +++ b/src/MaIN.Services/Utils/AgentStateManager.cs @@ -1,24 +1,24 @@ using MaIN.Domain.Entities; -using MaIN.Infrastructure.Models; +using MaIN.Domain.Entities.Agents; using MaIN.Services.Services.ImageGenServices; namespace MaIN.Services.Utils; public static class AgentStateManager { - public static void ClearState(AgentDocument agent, Chat chat) + public static void ClearState(Agent agent, Chat chat) { agent.CurrentBehaviour = "Default"; chat.Properties.Clear(); - + if (chat.ModelId == ImageGenService.LocalImageModels.FLUX) { chat.Messages = []; } else { - chat.Messages[0].Content = agent.Context!.Instruction!; - chat.Messages = chat.Messages.Take(1).ToList(); + chat.Messages[0].Content = agent.Config!.Instruction!; + chat.Messages = [.. chat.Messages.Take(1)]; } } -} \ No newline at end of file +}