Generated the JSON contracts of providers, the runtime, and services at compile time (#1150)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-11-03 07:59:30 +01:00
1 parent e954881fda
commit 24e3c22db3
140 files changed
+1415 -292

No files matched your search

@@ -8,5 +8,5 @@ internal sealed record StaanQueryInfo
/// <summary>
/// The query Staan searched for after correcting it, or empty when it searched what it was given.
/// </summary>
public string AlteredQuery { get; init; } = string.Empty;
public string AlteredQuery { get; set; } = string.Empty;
}
@@ -16,15 +16,15 @@ internal sealed record StaanSearchRequest
/// What to search for. Staan rejects a query longer than 400 characters.
/// </summary>
[JsonPropertyName("q")]
public required string Query { get; init; }
public required string Query { get; set; }
/// <summary>
/// The market to search in. Staan offers de-de, en-us, and fr-fr, and defaults to fr-fr.
/// </summary>
public string? Market { get; init; }
public string? Market { get; set; }
/// <summary>
/// Where in the result list to start, in steps of ten up to 30, or null for the first page.
/// </summary>
public int? Offset { get; init; }
public int? Offset { get; set; }
}
@@ -10,7 +10,7 @@ namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations.WebSearch.
/// </remarks>
internal sealed record StaanSearchResponse
{
public StaanQueryInfo? Query { get; init; }
public StaanQueryInfo? Query { get; set; }
public StaanWebSection? Web { get; init; }
public StaanWebSection? Web { get; set; }
}
@@ -10,9 +10,9 @@ namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations.WebSearch.
/// </remarks>
internal sealed record StaanSearchResult
{
public string Title { get; init; } = string.Empty;
public string Title { get; set; } = string.Empty;
public string Url { get; init; } = string.Empty;
public string Url { get; set; } = string.Empty;
public string Snippet { get; init; } = string.Empty;
public string Snippet { get; set; } = string.Empty;
}
@@ -5,5 +5,5 @@ namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations.WebSearch.
/// </summary>
internal sealed record StaanWebSection
{
public IReadOnlyList<StaanSearchResult> Results { get; init; } = [];
public IReadOnlyList<StaanSearchResult> Results { get; set; } = [];
}
@@ -10,35 +10,35 @@ namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations.WebSearch.
/// </remarks>
internal sealed record TavilySearchRequest
{
public required string Query { get; init; }
public required string Query { get; set; }
/// <summary>
/// How thoroughly to search. A basic search costs one credit, an advanced one costs two.
/// </summary>
public required string SearchDepth { get; init; }
public required string SearchDepth { get; set; }
/// <summary>
/// The most hits to return, at most 20.
/// </summary>
public int? MaxResults { get; init; }
public int? MaxResults { get; set; }
/// <summary>
/// How far back to look: day, week, month, or year, or null for no restriction.
/// </summary>
public string? TimeRange { get; init; }
public string? TimeRange { get; set; }
/// <summary>
/// The language to search in, as an ISO 639-1 code, or null for no restriction.
/// </summary>
public string? Language { get; init; }
public string? Language { get; set; }
/// <summary>
/// Whether the language is a requirement rather than a preference. Needs the language field.
/// </summary>
public bool? FilterByLanguage { get; init; }
public bool? FilterByLanguage { get; set; }
/// <summary>
/// Whether to filter explicit results or null to leave the decision to Tavily.
/// </summary>
public bool? SafeSearch { get; init; }
public bool? SafeSearch { get; set; }
}
@@ -10,5 +10,5 @@ namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations.WebSearch.
/// </remarks>
internal sealed record TavilySearchResponse
{
public IReadOnlyList<TavilySearchResult> Results { get; init; } = [];
public IReadOnlyList<TavilySearchResult> Results { get; set; } = [];
}
@@ -11,12 +11,12 @@ namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations.WebSearch.
/// </remarks>
internal sealed record TavilySearchResult
{
public string Title { get; init; } = string.Empty;
public string Title { get; set; } = string.Empty;
public string Url { get; init; } = string.Empty;
public string Url { get; set; } = string.Empty;
/// <summary>
/// The excerpt of the page that matched, which is what other services call a snippet.
/// </summary>
public string Content { get; init; } = string.Empty;
public string Content { get; set; } = string.Empty;
}
@@ -14,10 +14,11 @@ namespace AIStudio.Tools.ToolCallingSystem.ToolCallingImplementations.WebSearch;
/// </remarks>
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();
}
@@ -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;
/// <summary>
/// The contracts with which System.Text.Json reads and writes the calls to the search services, built at
/// compile time.
/// </summary>
/// <remarks>
/// SearXNG is missing on purpose: its answers differ between instances, so its client reads them as a tree
/// of JSON nodes instead.
/// </remarks>
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(StaanSearchRequest))]
[JsonSerializable(typeof(StaanSearchResponse))]
[JsonSerializable(typeof(TavilySearchRequest))]
[JsonSerializable(typeof(TavilySearchResponse))]
internal sealed partial class WebSearchJsonContext : JsonSerializerContext;
@@ -80,7 +80,8 @@ public sealed class ToolParameterSchemaBuilder
["additionalProperties"] = false,
};
return JsonSerializer.Deserialize<JsonElement>(schema.ToJsonString());
using var document = JsonDocument.Parse(schema.ToJsonString());
return document.RootElement.Clone();
}
private ToolParameterSchemaBuilder Add(string name, string jsonType, string description, bool isRequired, IReadOnlyList<string>? allowedValues = null)