diff --git a/app/MindWork AI Studio/Tools/ERIClient/ERIClientBase.cs b/app/MindWork AI Studio/Tools/ERIClient/ERIClientBase.cs
index 7d8f0cbe8..9b616d85f 100644
--- a/app/MindWork AI Studio/Tools/ERIClient/ERIClientBase.cs
+++ b/app/MindWork AI Studio/Tools/ERIClient/ERIClientBase.cs
@@ -9,7 +9,7 @@ public abstract class ERIClientBase(IERIDataSource dataSource) : IDisposable
{
protected readonly IERIDataSource DataSource = dataSource;
- internal static readonly JsonSerializerOptions JSON_OPTIONS = new()
+ internal static readonly JsonSerializerOptions JSON_OPTIONS = new JsonSerializerOptions
{
WriteIndented = true,
AllowTrailingCommas = true,
@@ -20,8 +20,9 @@ public abstract class ERIClientBase(IERIDataSource dataSource) : IDisposable
Converters =
{
new JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseUpper),
- }
- };
+ },
+ TypeInfoResolver = ERIClientJsonContext.Default,
+ }.AsReadOnly();
protected readonly HttpClient HttpClient = ExternalHttpClientTimeout.CreateHttpClient(new Uri($"{dataSource.Hostname}:{dataSource.Port}"), ExternalHttpTrustPolicy.ALLOW_CUSTOM_ROOTS_WHEN_HOST_WHITELISTED);
diff --git a/app/MindWork AI Studio/Tools/ERIClient/ERIClientJsonContext.cs b/app/MindWork AI Studio/Tools/ERIClient/ERIClientJsonContext.cs
new file mode 100644
index 000000000..30db29e2b
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/ERIClientJsonContext.cs
@@ -0,0 +1,23 @@
+using System.Text.Json.Serialization;
+
+using AIStudio.Tools.ERIClient.DataModel;
+
+namespace AIStudio.Tools.ERIClient;
+
+///
+/// The contracts with which System.Text.Json reads and writes the calls to ERI servers, built at compile time.
+///
+[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
+
+// The request:
+[JsonSerializable(typeof(RetrievalRequest))]
+
+// The answers:
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(AuthResponse))]
+[JsonSerializable(typeof(DataSourceInfo))]
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(SecurityRequirements))]
+internal sealed partial class ERIClientJsonContext : JsonSerializerContext;
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/WebSearch/WebSearchJson.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/WebSearch/WebSearchJson.cs
index 6ac1d24aa..136c31e8a 100644
--- a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/WebSearch/WebSearchJson.cs
+++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/WebSearch/WebSearchJson.cs
@@ -14,10 +14,11 @@ namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations.WebSearch;
///
internal static class WebSearchJson
{
- public static readonly JsonSerializerOptions OPTIONS = new()
+ public static readonly JsonSerializerOptions OPTIONS = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
- };
+ TypeInfoResolver = WebSearchJsonContext.Default,
+ }.AsReadOnly();
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/WebSearch/WebSearchJsonContext.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/WebSearch/WebSearchJsonContext.cs
new file mode 100644
index 000000000..8185029af
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/WebSearch/WebSearchJsonContext.cs
@@ -0,0 +1,21 @@
+using System.Text.Json.Serialization;
+
+using AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations.WebSearch.Staan;
+using AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations.WebSearch.Tavily;
+
+namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations.WebSearch;
+
+///
+/// The contracts with which System.Text.Json reads and writes the calls to the search services, built at
+/// compile time.
+///
+///
+/// SearXNG is missing on purpose: its answers differ between instances, so its client reads them as a tree
+/// of JSON nodes instead.
+///
+[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
+[JsonSerializable(typeof(StaanSearchRequest))]
+[JsonSerializable(typeof(StaanSearchResponse))]
+[JsonSerializable(typeof(TavilySearchRequest))]
+[JsonSerializable(typeof(TavilySearchResponse))]
+internal sealed partial class WebSearchJsonContext : JsonSerializerContext;
\ No newline at end of file
diff --git a/app/Tests/Serialization/JsonCoverageTests.cs b/app/Tests/Serialization/JsonCoverageTests.cs
index e40776b90..716585793 100644
--- a/app/Tests/Serialization/JsonCoverageTests.cs
+++ b/app/Tests/Serialization/JsonCoverageTests.cs
@@ -18,6 +18,8 @@ public sealed class JsonCoverageTests
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.ProviderAnswers))]
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.RuntimeRequests))]
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.RuntimeAnswers))]
+ [TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.ServiceRequests))]
+ [TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.ServiceAnswers))]
public void EveryContractComesFromSourceGeneration(JsonTestRoot root)
{
var typesWithoutGeneratedContract = JsonTypeGraph.Collect(root.Type, root.Options)