Skip to content

Commit ad0014c

Browse files
committed
[#19] Fix conflicts after merging main into feature branch, fix unit tests
1 parent f0fe24c commit ad0014c

File tree

9 files changed

+36
-58
lines changed

9 files changed

+36
-58
lines changed

Examples/Examples/Program.cs

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ async Task RunSelectedExample(IServiceProvider serviceProvider)
132132
Console.WriteLine("║ Error ║");
133133
Console.WriteLine("╚════════════════════════════════════════════════════════════════════╝");
134134
Console.ResetColor();
135-
136-
Console.WriteLine(ex.Message);
135+
136+
Console.WriteLine(ex.Message);
137137
}
138138
}
139139
else
@@ -189,51 +189,12 @@ public class ExampleRegistry(IServiceProvider serviceProvider)
189189
("\u25a0 GroqCloud Chat", serviceProvider.GetRequiredService<ChatExampleGroqCloud>()),
190190
("\u25a0 Anthropic Chat", serviceProvider.GetRequiredService<ChatExampleAnthropic>()),
191191
("\u25a0 xAI Chat", serviceProvider.GetRequiredService<ChatExampleXai>()),
192+
("\u25a0 Ollama Chat", serviceProvider.GetRequiredService<ChatExampleOllama>()),
192193
("\u25a0 McpClient example", serviceProvider.GetRequiredService<McpExample>()),
193194
("\u25a0 McpAgent example", serviceProvider.GetRequiredService<McpAgentsExample>()),
194195
("\u25a0 Chat with TTS example", serviceProvider.GetRequiredService<ChatWithTextToSpeechExample>()),
195196
("\u25a0 McpAgent example", serviceProvider.GetRequiredService<McpAgentsExample>())
196197
];
197198
}
198-
("\u25a0 Basic Chat", serviceProvider.GetRequiredService<ChatExample>()),
199-
("\u25a0 Chat with Files", serviceProvider.GetRequiredService<ChatWithFilesExample>()),
200-
("\u25a0 Chat with custom grammar", serviceProvider.GetRequiredService<ChatCustomGrammarExample>()),
201-
("\u25a0 Chat with Files from stream", serviceProvider.GetRequiredService<ChatWithFilesFromStreamExample>()),
202-
("\u25a0 Chat with Vision", serviceProvider.GetRequiredService<ChatWithVisionExample>()),
203-
("\u25a0 Chat with Tools (simple)", serviceProvider.GetRequiredService<ChatExampleToolsSimple>()),
204-
("\u25a0 Chat with Image Generation", serviceProvider.GetRequiredService<ChatWithImageGenExample>()),
205-
("\u25a0 Chat from Existing", serviceProvider.GetRequiredService<ChatFromExistingExample>()),
206-
("\u25a0 Chat with reasoning", serviceProvider.GetRequiredService<ChatWithReasoningExample>()),
207-
("\u25a0 Basic Agent", serviceProvider.GetRequiredService<AgentExample>()),
208-
("\u25a0 Conversation Agent", serviceProvider.GetRequiredService<AgentConversationExample>()),
209-
("\u25a0 Agent with Redirect", serviceProvider.GetRequiredService<AgentWithRedirectExample>()),
210-
("\u25a0 Agent with Redirect (Multi backends)", serviceProvider.GetRequiredService<MultiBackendAgentWithRedirectExample>()),
211-
("\u25a0 Agent with Redirect Image", serviceProvider.GetRequiredService<AgentWithRedirectImageExample>()),
212-
("\u25a0 Agent with Become", serviceProvider.GetRequiredService<AgentWithBecomeExample>()),
213-
("\u25a0 Agent with Tools (advanced)", serviceProvider.GetRequiredService<AgentExampleTools>()),
214-
("\u25a0 Agent with Knowledge", serviceProvider.GetRequiredService<AgentWithKnowledgeFileExample>()),
215-
("\u25a0 Agent with Web Knowledge", serviceProvider.GetRequiredService<AgentWithKnowledgeWebExample>()),
216-
("\u25a0 Agent with Mcp Knowledge", serviceProvider.GetRequiredService<AgentWithKnowledgeMcpExample>()),
217-
("\u25a0 Agent with API Data Source", serviceProvider.GetRequiredService<AgentWithApiDataSourceExample>()),
218-
("\u25a0 Agents Talking to Each Other", serviceProvider.GetRequiredService<AgentTalkingToEachOtherExample>()),
219-
("\u25a0 Agents Composed as Flow", serviceProvider.GetRequiredService<AgentsComposedAsFlowExample>()),
220-
("\u25a0 Agents Flow Loaded", serviceProvider.GetRequiredService<AgentsFlowLoadedExample>()),
221-
("\u25a0 OpenAi Chat", serviceProvider.GetRequiredService<ChatExampleOpenAi>()),
222-
("\u25a0 OpenAi Chat with image", serviceProvider.GetRequiredService<ChatWithImageGenOpenAiExample>()),
223-
("\u25a0 OpenAi Agent with Web Data Source", serviceProvider.GetRequiredService<AgentWithWebDataSourceOpenAiExample>()),
224-
("\u25a0 Gemini Chat", serviceProvider.GetRequiredService<ChatExampleGemini>()),
225-
("\u25a0 Gemini Chat with grammar", serviceProvider.GetRequiredService<ChatGrammarExampleGemini>()),
226-
("\u25a0 Gemini Chat with image", serviceProvider.GetRequiredService<ChatWithImageGenGeminiExample>()),
227-
("\u25a0 Gemini Chat with files", serviceProvider.GetRequiredService<ChatWithFilesExampleGemini>()),
228-
("\u25a0 DeepSeek Chat with reasoning", serviceProvider.GetRequiredService<ChatWithReasoningDeepSeekExample>()),
229-
("\u25a0 GroqCloud Chat", serviceProvider.GetRequiredService<ChatExampleGroqCloud>()),
230-
("\u25a0 Anthropic Chat", serviceProvider.GetRequiredService<ChatExampleAnthropic>()),
231-
("\u25a0 xAI Chat", serviceProvider.GetRequiredService<ChatExampleXai>()),
232-
("\u25a0 Ollama Chat", serviceProvider.GetRequiredService<ChatExampleOllama>()),
233-
("\u25a0 McpClient example", serviceProvider.GetRequiredService<McpExample>()),
234-
("\u25a0 McpAgent example", serviceProvider.GetRequiredService<McpAgentsExample>()),
235-
("\u25a0 Chat with TTS example", serviceProvider.GetRequiredService<ChatWithTextToSpeechExample>()),
236-
("\u25a0 McpAgent example", serviceProvider.GetRequiredService<McpAgentsExample>())
237-
};
238-
}
199+
};
239200
}

src/MaIN.Core.UnitTests/AgentContextTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using MaIN.Domain.Entities;
33
using MaIN.Domain.Entities.Agents;
44
using MaIN.Domain.Entities.Agents.Knowledge;
5+
using MaIN.Domain.Exceptions.Agents;
56
using MaIN.Services.Services.Abstract;
67
using MaIN.Services.Services.Models;
78
using Moq;
@@ -220,7 +221,7 @@ public async Task FromExisting_ShouldThrowArgumentExceptionWhenAgentNotFound()
220221
.ReturnsAsync((Agent)null!);
221222

222223
// Act & Assert
223-
await Assert.ThrowsAsync<ArgumentException>(() =>
224+
await Assert.ThrowsAsync<AgentNotFoundException>(() =>
224225
AgentContext.FromExisting(_mockAgentService.Object, nonExistentAgentId));
225226
}
226227
}

src/MaIN.Core.UnitTests/FlowContextTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Moq;
66
using MaIN.Domain.Entities.Agents.AgentSource;
77
using MaIN.Domain.Entities.Agents.Knowledge;
8+
using MaIN.Domain.Exceptions.Flows;
89

910
namespace MaIN.Core.UnitTests;
1011

@@ -196,6 +197,6 @@ public async Task FromExisting_ShouldThrowArgumentExceptionWhenFlowNotFound()
196197
.ReturnsAsync((AgentFlow)null!);
197198

198199
// Act & Assert
199-
await Assert.ThrowsAsync<ArgumentException>(() => _flowContext.FromExisting(nonExistentFlowId));
200+
await Assert.ThrowsAsync<FlowNotFoundException>(() => _flowContext.FromExisting(nonExistentFlowId));
200201
}
201202
}

src/MaIN.Core/Hub/Contexts/FlowContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ public async Task<IFlowContext> FromExisting(string flowId)
234234
{
235235
var existingFlow = await _flowService.GetFlowById(flowId);
236236
return existingFlow == null
237-
? throw new FlowFoundException(flowId)
237+
? throw new FlowNotFoundException(flowId)
238238
: this;
239239
}
240240
}

src/MaIN.Domain/Exceptions/Flows/FlowFoundException.cs renamed to src/MaIN.Domain/Exceptions/Flows/FlowNotFoundException.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace MaIN.Domain.Exceptions.Flows;
44

5-
public class FlowFoundException(string flowId)
5+
public class FlowNotFoundException(string flowId)
66
: MaINCustomException($"Flow with id: '{flowId}' not found.")
77
{
88
public override string PublicErrorMessage => "Flow not found.";

src/MaIN.InferPage/Program.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@
8080

8181
case "xai":
8282
Utils.Xai = true;
83-
apiKeyVariable = "XAI_API_KEY";
84-
apiName = "Xai";
83+
apiKeyVariable = LLMApiRegistry.Xai.ApiKeyEnvName;
84+
apiName = LLMApiRegistry.Xai.ApiName;
8585
break;
8686

8787
case "ollama":
8888
Utils.Ollama = true;
89-
apiKeyVariable = "OLLAMA_API_KEY";
90-
apiName = "Ollama";
89+
apiKeyVariable = LLMApiRegistry.Ollama.ApiKeyEnvName;
90+
apiName = LLMApiRegistry.Ollama.ApiName;
9191
break;
9292
}
9393

src/MaIN.Services/Services/LLMService/OllamaService.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using MaIN.Services.Constants;
55
using MaIN.Services.Services.Abstract;
66
using MaIN.Services.Services.LLMService.Memory;
7+
using MaIN.Services.Services.LLMService.Utils;
78
using MaIN.Services.Services.Models;
89
using Microsoft.Extensions.Logging;
910

@@ -20,17 +21,19 @@ public sealed class OllamaService(
2021
{
2122
private readonly MaINSettings _settings = settings ?? throw new ArgumentNullException(nameof(settings));
2223

23-
private bool HasApiKey => !string.IsNullOrEmpty(_settings.OllamaKey) || !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("OLLAMA_API_KEY"));
24+
private bool HasApiKey => !string.IsNullOrEmpty(_settings.OllamaKey) || !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(LLMApiRegistry.Ollama.ApiKeyEnvName));
2425

2526
protected override string HttpClientName => HasApiKey ? ServiceConstants.HttpClients.OllamaClient : ServiceConstants.HttpClients.OllamaLocalClient;
2627
protected override string ChatCompletionsUrl => HasApiKey ? ServiceConstants.ApiUrls.OllamaOpenAiChatCompletions : ServiceConstants.ApiUrls.OllamaLocalOpenAiChatCompletions;
2728
protected override string ModelsUrl => HasApiKey ? ServiceConstants.ApiUrls.OllamaModels : ServiceConstants.ApiUrls.OllamaLocalModels;
2829

2930
protected override string GetApiKey()
3031
{
31-
return _settings.OllamaKey ?? Environment.GetEnvironmentVariable("OLLAMA_API_KEY") ?? string.Empty;
32+
return _settings.OllamaKey ?? Environment.GetEnvironmentVariable(LLMApiRegistry.Ollama.ApiKeyEnvName) ?? string.Empty;
3233
}
3334

35+
protected override string GetApiName() => LLMApiRegistry.Ollama.ApiName;
36+
3437
protected override void ValidateApiKey()
3538
{
3639
// No validation required - local Ollama doesn't need an API key

src/MaIN.Services/Services/LLMService/OpenAiCompatibleService.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ private async Task HandleApiError(HttpResponseMessage response, CancellationToke
675675
{
676676
var errorResponseBody = await response.Content.ReadAsStringAsync(cancellationToken);
677677
var errorMessage = ExtractApiErrorMessage(errorResponseBody);
678-
678+
679679
throw new LLMApiException(GetApiName(), response.StatusCode, errorMessage ?? errorResponseBody);
680680
}
681681

@@ -684,8 +684,18 @@ private async Task HandleApiError(HttpResponseMessage response, CancellationToke
684684
try
685685
{
686686
using var jasonDocument = JsonDocument.Parse(json);
687-
if (jasonDocument.RootElement.TryGetProperty("error", out var error) &&
688-
error.TryGetProperty("message", out var message))
687+
688+
if (jasonDocument.RootElement.ValueKind == JsonValueKind.Array)
689+
{
690+
var firstElement = jasonDocument.RootElement[0];
691+
if (firstElement.TryGetProperty("error", out var arrayError) &&
692+
arrayError.TryGetProperty("message", out var arrayMessage))
693+
{
694+
return arrayMessage.GetString();
695+
}
696+
}
697+
else if (jasonDocument.RootElement.TryGetProperty("error", out var error) &&
698+
error.TryGetProperty("message", out var message))
689699
{
690700
return message.GetString();
691701
}
@@ -694,8 +704,9 @@ private async Task HandleApiError(HttpResponseMessage response, CancellationToke
694704
{
695705
// If the response is not a valid JSON or doesn't match the expected schema,
696706
// we fall back to the raw response body in the calling method.
707+
return null;
697708
}
698-
709+
699710
return null;
700711
}
701712

src/MaIN.Services/Services/LLMService/Utils/LLMApiRegistry.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ public static class LLMApiRegistry
77
public static readonly LLMApiRegistryEntry Deepseek = new("Deepseek", "DEEPSEEK_API_KEY");
88
public static readonly LLMApiRegistryEntry Groq = new("GroqCloud", "GROQ_API_KEY");
99
public static readonly LLMApiRegistryEntry Anthropic = new("Anthropic", "ANTHROPIC_API_KEY");
10-
public static readonly LLMApiRegistryEntry Xai = new("xAI", "XAI_API_KEY");
10+
public static readonly LLMApiRegistryEntry Xai = new("Xai", "XAI_API_KEY");
11+
public static readonly LLMApiRegistryEntry Ollama = new("Ollama", "OLLAMA_API_KEY");
1112
}
1213

1314
public record LLMApiRegistryEntry(string ApiName, string ApiKeyEnvName);

0 commit comments

Comments
 (0)