diff --git a/Directory.Packages.props b/Directory.Packages.props
index 227ce36d..ea7d4ce2 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -19,7 +19,13 @@
+
+
+
+
+
+
diff --git a/Linq2GraphQL.CI.slnf b/Linq2GraphQL.CI.slnf
index 2d1cb93a..e99fb3e6 100644
--- a/Linq2GraphQL.CI.slnf
+++ b/Linq2GraphQL.CI.slnf
@@ -7,6 +7,7 @@
"src\\Linq2GraphQL.Client.AI\\Linq2GraphQL.Client.AI.csproj",
"src\\Linq2GraphQL.Generator\\Linq2GraphQL.Generator.csproj",
"test\\Linq2GraphQL.Console\\Linq2GraphQL.Console.csproj",
+ "test\\Linq2GraphQL.Agent.Sample\\Linq2GraphQL.Agent.Sample.csproj",
"test\\Linq2GraphQL.TestClient\\Linq2GraphQL.TestClient.csproj",
"test\\Linq2GraphQL.TestClientNullable\\Linq2GraphQL.TestClientNullable.csproj",
"test\\Linq2GraphQL.TestServer\\Linq2GraphQL.TestServer.csproj",
diff --git a/Linq2GraphQL.Release.slnf b/Linq2GraphQL.Release.slnf
index 11123000..995fee41 100644
--- a/Linq2GraphQL.Release.slnf
+++ b/Linq2GraphQL.Release.slnf
@@ -4,6 +4,7 @@
"projects": [
"src\\Linq2GraphQL.Client\\Linq2GraphQL.Client.csproj",
"src\\Linq2GraphQL.Client.Subscriptions\\Linq2GraphQL.Client.Subscriptions.csproj",
+ "src\\Linq2GraphQL.Client.AI\\Linq2GraphQL.Client.AI.csproj",
"src\\Linq2GraphQL.Generator\\Linq2GraphQL.Generator.csproj"
]
}
diff --git a/Linq2GraphQL.sln b/Linq2GraphQL.sln
index 7dd648b8..4a03ce81 100644
--- a/Linq2GraphQL.sln
+++ b/Linq2GraphQL.sln
@@ -30,6 +30,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Linq2GraphQL.TestClientNull
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Linq2GraphQL.Console", "test\Linq2GraphQL.Console\Linq2GraphQL.Console.csproj", "{058B468F-CE72-4CFF-8847-87CEED642C4E}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Linq2GraphQL.Agent.Sample", "test\Linq2GraphQL.Agent.Sample\Linq2GraphQL.Agent.Sample.csproj", "{6E3C2B71-4D8A-4F1E-9B57-2A9C0D4E8F13}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Linq2GraphQL.Generator", "src\Linq2GraphQL.Generator\Linq2GraphQL.Generator.csproj", "{C0E1A444-A834-4FC0-8436-38066EA8D37D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Linq2GraphQL.Client", "src\Linq2GraphQL.Client\Linq2GraphQL.Client.csproj", "{B2EAACC4-0B04-458B-B425-DE83BED807EA}"
@@ -96,6 +98,10 @@ Global
{058B468F-CE72-4CFF-8847-87CEED642C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{058B468F-CE72-4CFF-8847-87CEED642C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{058B468F-CE72-4CFF-8847-87CEED642C4E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6E3C2B71-4D8A-4F1E-9B57-2A9C0D4E8F13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6E3C2B71-4D8A-4F1E-9B57-2A9C0D4E8F13}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6E3C2B71-4D8A-4F1E-9B57-2A9C0D4E8F13}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6E3C2B71-4D8A-4F1E-9B57-2A9C0D4E8F13}.Release|Any CPU.Build.0 = Release|Any CPU
{C0E1A444-A834-4FC0-8436-38066EA8D37D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C0E1A444-A834-4FC0-8436-38066EA8D37D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C0E1A444-A834-4FC0-8436-38066EA8D37D}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -132,6 +138,7 @@ Global
{F9EAFD31-9AF1-47DF-9C78-003C7AC67C5D} = {5BE1963B-E57D-4CF5-B03E-644D8F39B4D2}
{C1908816-34E7-4B41-9E39-2283C59DB017} = {5BE1963B-E57D-4CF5-B03E-644D8F39B4D2}
{058B468F-CE72-4CFF-8847-87CEED642C4E} = {5BE1963B-E57D-4CF5-B03E-644D8F39B4D2}
+ {6E3C2B71-4D8A-4F1E-9B57-2A9C0D4E8F13} = {5BE1963B-E57D-4CF5-B03E-644D8F39B4D2}
{C0E1A444-A834-4FC0-8436-38066EA8D37D} = {F646B02D-53FC-4C88-8941-2255A2F4DAF6}
{A941BD4C-8B04-4273-AC0B-CF86D71D7E0B} = {884758A6-B667-4CA0-B186-AFB6331A24A5}
{3C66EF43-E66D-46DE-B2BB-434E7FC20487} = {884758A6-B667-4CA0-B186-AFB6331A24A5}
diff --git a/README.md b/README.md
index 8b0d0dcf..163b383c 100644
--- a/README.md
+++ b/README.md
@@ -237,6 +237,44 @@ var launches = await userClient.Query.Launches().Select().ExecuteAsync();
`WithAccessToken` sets `Authorization: Bearer ` and asks the delegate for the token on every request;
`WithRequestConfiguration` takes any hook.
+## Agent mode (preview)
+
+`Linq2GraphQL.Client.AI` lets an AI agent query your API in plain GraphQL, limited to the operations you
+allow. Generate the client with `--agent` (`-ag`) so it carries the schema, then turn it into tools for
+Microsoft.Extensions.AI:
+
+```cs
+var tools = spaceXClient.AsAgentTools(o =>
+{
+ o.AllowQuery(c => c.Query.Launches);
+ o.AllowQuery(c => c.Query.Rockets);
+ o.Describe(l => l.Details, "Free-text mission summary; may be empty.");
+ o.Instructions("Dates are UTC.");
+ o.AccessToken = ct => tokens.GetAccessTokenForUserAsync(user, ct);
+ o.OnQuery(log => logger.LogInformation("{Query} {Errors}", log.Query, log.ValidationErrors));
+});
+
+var response = await chatClient.GetResponseAsync(question, new ChatOptions { Tools = [..tools] });
+```
+
+The agent gets four tools: `search_schema`, `describe_operation`, `describe_type` and `graphql_query`. It
+sees only the allowed operations and the types they reach, and every query is validated against that
+scope before it is sent. The server stays responsible for authorization; give the agent a down-scoped or
+on-behalf-of token.
+
+`test/Linq2GraphQL.Agent.Sample` runs an agent against the test server. It uses Azure AI Foundry through
+your Azure sign-in (`az login`, no keys), or any OpenAI-compatible endpoint such as Ollama:
+
+```powershell
+dotnet user-secrets --project test/Linq2GraphQL.Agent.Sample set Agent:Endpoint "https://.cognitiveservices.azure.com/"
+dotnet user-secrets --project test/Linq2GraphQL.Agent.Sample set Agent:Deployment ""
+dotnet run --project test/Linq2GraphQL.Agent.Sample # chat
+dotnet run --project test/Linq2GraphQL.Agent.Sample -- eval # run questions.json and report
+```
+
+For Ollama, set `Agent:Provider` to `OpenAICompatible` and `Agent:Endpoint` to `http://localhost:11434/v1/`.
+Add `--verbose` to see each tool call. See [the design doc](docs/design/agent-mode.md) for the full picture.
+
## Safe Mode
Turning on *SafeMode* will make the client before the first request to do an introspection query to the endpoint. The
diff --git a/docs/design/agent-mode.md b/docs/design/agent-mode.md
index b64e9f1d..5b316b3c 100644
--- a/docs/design/agent-mode.md
+++ b/docs/design/agent-mode.md
@@ -1,6 +1,6 @@
# Linq2GraphQL Agent Mode Design
-**Status:** in progress. Plan steps 1-3 (the groundwork, SDL input and SDL output) are implemented. The AI package is being built in slices: (1) package skeleton and scoped schema, (2) renderer, (3) validator, (4) the four tools, (5) the `AsAgentTools` adapter, (6) sample and regression harness. Slices 1 to 4 are merged; slice 5 (the adapter) is in review. See [Plan](#plan-and-risks).
+**Status:** in progress. Plan steps 1-3 (the groundwork, SDL input and SDL output) are implemented. The AI package is being built in slices: (1) package skeleton and scoped schema, (2) renderer, (3) validator, (4) the four tools, (5) the `AsAgentTools` adapter, (6) sample and regression harness. Slices 1 to 5 are merged; slice 6 (the sample and regression harness) is in review. See [Plan](#plan-and-risks).
## Summary
@@ -420,7 +420,7 @@ Subscriptions stay out entirely; they don't fit the request/response shape of to
1. **Core prerequisites** (done): the per-request hook and the schema cache-key fix.
2. **SDL input in the generator** (done): it introduced GraphQL-Parser.
3. **SDL output** (done): the `--agent` flag, `IGraphSchemaSource`, and derived clients for per-user tokens. `[Description]` attributes and the two extra introspection fields shipped with step 2.
-4. **Preview and pilots:** the first version as a prerelease package (`-preview`), complete enough to run end to end, with a runnable sample against the test server. Usefulness depends on the use case, so it is evaluated in one or two pilot apps with a real schema and real users, ideally different ones (interactive and background, small and large schema). The evaluation is part of the product: `OnQuery` logs (questions, queries, validation errors, tool calls per answer), simple user feedback per answer in the pilot app, and which questions the team moves to dedicated tools. The pilots can start before step 3 by using an exported `schema.graphql`.
+4. **Preview and pilots:** the first version as a prerelease package (`-preview`), complete enough to run end to end, with a runnable sample against the test server. Usefulness depends on the use case, so it is evaluated in one or two pilot apps with a real schema and real users, ideally different ones (interactive and background, small and large schema). The evaluation is part of the product: `OnQuery` logs (questions, queries, validation errors, tool calls per answer), simple user feedback per answer in the pilot app, and which questions the team moves to dedicated tools. The pilots can start before step 3 by using an exported `schema.graphql`. The sample (`test/Linq2GraphQL.Agent.Sample`) runs a chat loop against the in-process test server, with Azure AI Foundry (Entra ID, no keys) or any OpenAI-compatible endpoint such as Ollama, and an `eval` mode that runs a question set and reports pass rate, tool calls, rejected queries and tokens; it is the regression harness for prompt and tool changes. CI runs the loop without a model: a scripted chat client replays tool calls through Microsoft.Extensions.AI's function invocation (`AgentLoopTests`).
5. **Decide from the pilots:** did the teams get a working agent quickly, were users satisfied with the answers, where did it fail (filters, paging, large schemas), and what did they specialise? If it holds up, release `Linq2GraphQL.Client.AI`. If not, the core and generator improvements still stand.
**Risks**
diff --git a/test/Linq2GraphQL.Agent.Sample/AgentSampleApp.cs b/test/Linq2GraphQL.Agent.Sample/AgentSampleApp.cs
new file mode 100644
index 00000000..4f570247
--- /dev/null
+++ b/test/Linq2GraphQL.Agent.Sample/AgentSampleApp.cs
@@ -0,0 +1,205 @@
+using System.Diagnostics;
+using System.Text.Json;
+using Linq2GraphQL.Client;
+using Linq2GraphQL.Client.AI;
+using Linq2GraphQL.TestClient;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+
+namespace Linq2GraphQL.Agent.Sample;
+
+///
+/// A small agent over the test GraphQL server, built with AsAgentTools.
+/// chat talk to the agent (the default)
+/// eval [file] run the questions in questions.json and report answer rate, tool calls and tokens
+/// The test server runs in-process unless Agent:ServerUrl points at a running one.
+///
+public static class AgentSampleApp
+{
+ private const string SystemPrompt =
+ "You answer questions about the data behind a GraphQL API, using the tools. If you are unsure which " +
+ "operation or field to use, call describe_operation, describe_type or search_schema before querying. " +
+ "If a query is rejected, fix every error listed and try again. Answer briefly, with the values you found.";
+
+ public static async Task Main(string[] args)
+ {
+ var configuration = new ConfigurationBuilder()
+ .SetBasePath(AppContext.BaseDirectory)
+ .AddJsonFile("appsettings.json", optional: true)
+ .AddUserSecrets(typeof(AgentSampleApp).Assembly, optional: true)
+ .AddEnvironmentVariables("LINQ2GRAPHQL_")
+ .Build();
+
+ var settings = AgentSettings.From(configuration, out var problem);
+ if (settings == null)
+ {
+ Console.Error.WriteLine(problem);
+ Console.Error.WriteLine("""
+
+ Set the model to use, for example with user secrets (stored outside the repository):
+
+ dotnet user-secrets --project test/Linq2GraphQL.Agent.Sample set Agent:Endpoint "https://.cognitiveservices.azure.com/"
+ dotnet user-secrets --project test/Linq2GraphQL.Agent.Sample set Agent:Deployment ""
+
+ Azure AI Foundry signs in with your own account (az login or Visual Studio); no key is needed.
+ For another OpenAI-compatible endpoint, such as Ollama, also set Agent:Provider to
+ OpenAICompatible and, if the endpoint needs one, Agent:ApiKey.
+ Environment variables work too: LINQ2GRAPHQL_Agent__Endpoint and so on.
+ """);
+ return 1;
+ }
+
+ using var server = StartServer(configuration["Agent:ServerUrl"], out var httpClient);
+ var client = new SampleClient(httpClient, Options.Create(new GraphClientOptions()),
+ new ServiceCollection().AddMemoryCache().BuildServiceProvider());
+ var chat = ChatClientFactory.Create(settings);
+ var verbose = args.Contains("--verbose");
+
+ var mode = args.FirstOrDefault(e => !e.StartsWith("--")) ?? "chat";
+ return mode switch
+ {
+ "chat" => await ChatAsync(chat, client, verbose),
+ "eval" => await EvalAsync(chat, client, args.Skip(1).FirstOrDefault(e => !e.StartsWith("--")) ?? "questions.json", verbose),
+ _ => Usage()
+ };
+ }
+
+ ///
+ /// The agent's scope over the test schema. Everything the agent sees comes from here.
+ ///
+ internal static IList Tools(SampleClient client, Action? log) => client.AsAgentTools(o =>
+ {
+ o.Instructions("Dates are UTC.");
+ o.AllowQuery(c => c.Query.Hello).Describe("Greets someone by name; a quick way to test the API.");
+ o.AllowQuery(c => c.Query.Customers).Describe("All customers with their orders.");
+ o.AllowQuery(c => c.Query.Orders).Describe("Orders, paged and filterable.");
+ o.AllowQuery(c => c.Query.Animals).Describe("The animals: pigs and spiders.");
+ o.Describe("A customer account.");
+ o.Example("Customer statuses", "Every customer's name and status",
+ c => c.Query.Customers().Select(e => e.Select(x => new { x.CustomerName, x.Status })));
+ if (log != null)
+ {
+ o.OnQuery(log);
+ }
+ });
+
+ private static async Task ChatAsync(IChatClient chat, SampleClient client, bool verbose)
+ {
+ var tools = Tools(client, verbose ? PrintQuery : null);
+ var options = new ChatOptions { Tools = [..tools] };
+ var history = new List { new(ChatRole.System, SystemPrompt) };
+
+ Console.WriteLine("Ask about customers, orders or animals. An empty line ends the chat.");
+ while (true)
+ {
+ Console.Write("\n> ");
+ var question = Console.ReadLine();
+ if (string.IsNullOrWhiteSpace(question))
+ {
+ return 0;
+ }
+
+ history.Add(new ChatMessage(ChatRole.User, question));
+ var response = await chat.GetResponseAsync(history, options);
+ history.AddMessages(response);
+ Console.WriteLine(response.Text);
+ }
+ }
+
+ private static async Task EvalAsync(IChatClient chat, SampleClient client, string file, bool verbose)
+ {
+ var path = Path.IsPathRooted(file) ? file : Path.Combine(AppContext.BaseDirectory, file);
+ var questions = JsonSerializer.Deserialize>(await File.ReadAllTextAsync(path),
+ new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) ?? [];
+
+ var results = new List();
+ foreach (var question in questions)
+ {
+ var queries = new List();
+ var tools = Tools(client, log =>
+ {
+ queries.Add(log);
+ if (verbose)
+ {
+ PrintQuery(log);
+ }
+ });
+
+ var watch = Stopwatch.StartNew();
+ var response = await chat.GetResponseAsync(
+ [new ChatMessage(ChatRole.System, SystemPrompt), new ChatMessage(ChatRole.User, question.Question)],
+ new ChatOptions { Tools = [..tools] });
+
+ var answer = response.Text;
+ var result = new EvalResult(
+ question.Question,
+ question.Expected.All(e => answer.Contains(e, StringComparison.OrdinalIgnoreCase)),
+ response.Messages.SelectMany(e => e.Contents).OfType().Count(),
+ queries.Count(e => !e.WasSent),
+ response.Usage?.TotalTokenCount ?? 0,
+ watch.Elapsed,
+ answer);
+ results.Add(result);
+
+ Console.WriteLine($"{(result.Correct ? "PASS" : "FAIL")} tools {result.ToolCalls,2} rejected {result.RejectedQueries} " +
+ $"tokens {result.Tokens,6} {result.Duration.TotalSeconds,5:0.0}s {result.Question}");
+ if (!result.Correct)
+ {
+ Console.WriteLine($" expected: {string.Join(", ", question.Expected)}");
+ Console.WriteLine($" answer: {answer.ReplaceLineEndings(" ")}");
+ }
+ }
+
+ Console.WriteLine();
+ Console.WriteLine($"Answered {results.Count(e => e.Correct)} of {results.Count} correctly; " +
+ $"{results.Average(e => e.ToolCalls):0.0} tool calls, " +
+ $"{results.Average(e => e.Tokens):0} tokens and " +
+ $"{results.Average(e => e.Duration.TotalSeconds):0.0}s per question on average.");
+
+ var report = Path.Combine(AppContext.BaseDirectory, $"eval-{DateTime.UtcNow:yyyyMMdd-HHmmss}.json");
+ await File.WriteAllTextAsync(report, JsonSerializer.Serialize(results, new JsonSerializerOptions { WriteIndented = true }));
+ Console.WriteLine($"Details: {report}");
+
+ return results.All(e => e.Correct) ? 0 : 2;
+ }
+
+ private static IDisposable StartServer(string? serverUrl, out HttpClient httpClient)
+ {
+ if (!string.IsNullOrWhiteSpace(serverUrl))
+ {
+ httpClient = new HttpClient { BaseAddress = new Uri(serverUrl) };
+ return httpClient;
+ }
+
+ var application = new WebApplicationFactory();
+ httpClient = application.CreateClient(new() { BaseAddress = new Uri("https://localhost/graphql/") });
+ return application;
+ }
+
+ private static void PrintQuery(AgentQueryLog log)
+ {
+ var color = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.DarkGray;
+ Console.WriteLine($" [{(log.WasSent ? "sent" : "rejected")}] {log.Query.ReplaceLineEndings(" ")}");
+ foreach (var error in log.ValidationErrors.Concat(log.Errors))
+ {
+ Console.WriteLine($" {error}");
+ }
+
+ Console.ForegroundColor = color;
+ }
+
+ private static int Usage()
+ {
+ Console.Error.WriteLine("Usage: Linq2GraphQL.Agent.Sample [chat | eval [questions.json]] [--verbose]");
+ return 1;
+ }
+
+ private sealed record EvalQuestion(string Question, string[] Expected);
+
+ private sealed record EvalResult(string Question, bool Correct, int ToolCalls, int RejectedQueries, long Tokens,
+ TimeSpan Duration, string Answer);
+}
diff --git a/test/Linq2GraphQL.Agent.Sample/ChatClientFactory.cs b/test/Linq2GraphQL.Agent.Sample/ChatClientFactory.cs
new file mode 100644
index 00000000..2617fdd3
--- /dev/null
+++ b/test/Linq2GraphQL.Agent.Sample/ChatClientFactory.cs
@@ -0,0 +1,82 @@
+using System.ClientModel;
+using System.ClientModel.Primitives;
+using Azure.Identity;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Configuration;
+using OpenAI;
+
+namespace Linq2GraphQL.Agent.Sample;
+
+///
+/// Builds the chat client from the "Agent" configuration section. Nothing secret lives in the repository:
+/// Azure AI Foundry signs in with your own Entra ID account through DefaultAzureCredential (az login, Visual
+/// Studio), and an API key, when one is needed, comes from user secrets or an environment variable.
+///
+internal static class ChatClientFactory
+{
+ private const string CognitiveServicesScope = "https://cognitiveservices.azure.com/.default";
+
+ public static IChatClient Create(AgentSettings settings)
+ {
+ var options = new OpenAIClientOptions { Endpoint = settings.ClientEndpoint };
+
+ var client = settings.Provider switch
+ {
+ // Entra ID sign-in goes through the SDK's token-policy constructor, which it still marks as
+ // evaluation-only. It works against Foundry's OpenAI-compatible v1 endpoint.
+#pragma warning disable OPENAI001
+ AgentProvider.AzureFoundry when string.IsNullOrWhiteSpace(settings.ApiKey) =>
+ new OpenAIClient(new BearerTokenPolicy(new DefaultAzureCredential(), CognitiveServicesScope), options),
+#pragma warning restore OPENAI001
+ AgentProvider.AzureFoundry => new OpenAIClient(new ApiKeyCredential(settings.ApiKey!), options),
+ _ => new OpenAIClient(new ApiKeyCredential(string.IsNullOrWhiteSpace(settings.ApiKey) ? "not-used" : settings.ApiKey), options)
+ };
+
+ return client.GetChatClient(settings.Deployment).AsIChatClient()
+ .AsBuilder()
+ .UseFunctionInvocation()
+ .Build();
+ }
+}
+
+internal enum AgentProvider
+{
+ /// A deployment in Azure AI Foundry or Azure OpenAI, through its OpenAI-compatible v1 endpoint.
+ AzureFoundry,
+
+ /// Any OpenAI-compatible endpoint, for example Ollama on http://localhost:11434/v1/.
+ OpenAICompatible
+}
+
+internal sealed record AgentSettings(AgentProvider Provider, string Endpoint, string Deployment, string? ApiKey)
+{
+ ///
+ /// The endpoint the OpenAI client talks to: Foundry's resource endpoint gets its OpenAI-compatible
+ /// openai/v1/ path, other endpoints are used as given.
+ ///
+ public Uri ClientEndpoint => Provider == AgentProvider.AzureFoundry && !Endpoint.Contains("/openai/v1", StringComparison.OrdinalIgnoreCase)
+ ? new Uri(Endpoint.TrimEnd('/') + "/openai/v1/")
+ : new Uri(Endpoint);
+
+ public static AgentSettings? From(IConfiguration configuration, out string problem)
+ {
+ var section = configuration.GetSection("Agent");
+ var endpoint = section["Endpoint"];
+ var deployment = section["Deployment"];
+
+ if (!Enum.TryParse(section["Provider"] ?? nameof(AgentProvider.AzureFoundry), true, out var provider))
+ {
+ problem = $"Agent:Provider must be {nameof(AgentProvider.AzureFoundry)} or {nameof(AgentProvider.OpenAICompatible)}.";
+ return null;
+ }
+
+ if (string.IsNullOrWhiteSpace(endpoint) || string.IsNullOrWhiteSpace(deployment))
+ {
+ problem = "Agent:Endpoint and Agent:Deployment are not set.";
+ return null;
+ }
+
+ problem = "";
+ return new AgentSettings(provider, endpoint, deployment, section["ApiKey"]);
+ }
+}
diff --git a/test/Linq2GraphQL.Agent.Sample/Linq2GraphQL.Agent.Sample.csproj b/test/Linq2GraphQL.Agent.Sample/Linq2GraphQL.Agent.Sample.csproj
new file mode 100644
index 00000000..3659928d
--- /dev/null
+++ b/test/Linq2GraphQL.Agent.Sample/Linq2GraphQL.Agent.Sample.csproj
@@ -0,0 +1,35 @@
+
+
+
+ Exe
+ net10.0
+ enable
+ enable
+ linq2graphql-agent-sample
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Linq2GraphQL.Agent.Sample/appsettings.json b/test/Linq2GraphQL.Agent.Sample/appsettings.json
new file mode 100644
index 00000000..ef9d7080
--- /dev/null
+++ b/test/Linq2GraphQL.Agent.Sample/appsettings.json
@@ -0,0 +1,8 @@
+{
+ "Agent": {
+ "Provider": "AzureFoundry",
+ "Endpoint": "",
+ "Deployment": "",
+ "ServerUrl": ""
+ }
+}
diff --git a/test/Linq2GraphQL.Agent.Sample/packages.lock.json b/test/Linq2GraphQL.Agent.Sample/packages.lock.json
new file mode 100644
index 00000000..9855a09b
--- /dev/null
+++ b/test/Linq2GraphQL.Agent.Sample/packages.lock.json
@@ -0,0 +1,1039 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net10.0": {
+ "Azure.Identity": {
+ "type": "Direct",
+ "requested": "[1.21.0, )",
+ "resolved": "1.21.0",
+ "contentHash": "GeFv8sGwRKvDKwI2WFy8r0mhmlxEVZg24Sit2NogTjiSO8RVjllWM65OT6e1sKjOvG8V74y7hAbaELUUPjZQSw==",
+ "dependencies": {
+ "Azure.Core": "1.53.0"
+ }
+ },
+ "Microsoft.AspNetCore.Mvc.Testing": {
+ "type": "Direct",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "BJi3rpYETlh0wd14Lg5Is9MWvEf55TAGd7yo+xGHuEZp7ololyvftbQZ1i7ZuITA7DgNPJED6EMhFSWycq7SBg==",
+ "dependencies": {
+ "Microsoft.AspNetCore.TestHost": "10.0.11",
+ "Microsoft.Extensions.DependencyModel": "10.0.11",
+ "Microsoft.Extensions.Hosting": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.AI": {
+ "type": "Direct",
+ "requested": "[10.10.0, )",
+ "resolved": "10.10.0",
+ "contentHash": "XKvtDUD3KySkvA5UpS+UF67M5rcqiXjAQchTZZ26WnavVKXxwlUTVdK/Ju0tc/25+16AVUdNl8cnVVGX/tx03A==",
+ "dependencies": {
+ "Microsoft.Extensions.AI.Abstractions": "10.10.0",
+ "Microsoft.Extensions.Caching.Abstractions": "10.0.12",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.12",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.12",
+ "System.Numerics.Tensors": "10.0.12"
+ }
+ },
+ "Microsoft.Extensions.AI.OpenAI": {
+ "type": "Direct",
+ "requested": "[10.10.0, )",
+ "resolved": "10.10.0",
+ "contentHash": "Z5uwqIJ0tGp50P+ark1/qb7wFa6inIRKvaR3L9Frtf7M9uGIil/cz4k9S7va8HMrXzE/xjIJqd6A9cJ7WlMpgg==",
+ "dependencies": {
+ "Microsoft.Extensions.AI.Abstractions": "10.10.0",
+ "OpenAI": "2.13.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration": {
+ "type": "Direct",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "wlhRqZW8LcJPa+vk2oLAc/REXDItHtkFQdf/QcXYGZbZOO13izcsKY1pCvuFQYwUiZD+hwSZwsKASjqT+BNaVg==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Primitives": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Configuration.EnvironmentVariables": {
+ "type": "Direct",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "KICyU3eVi5jvloKm01EXV69L97H/zkhISVtV98cIuzuFOxNx3xTUVcXqvWTz3aq7OvUuDB/MFlPFjmxRaKF7/A==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.11",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Json": {
+ "type": "Direct",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "nSPrT8U/cNoB4coqkmnanAMK9PsL7lsjG+LLUKEwHRFwS6E78b8S1wdv/y88EOxBhasWov1rLd7RTHmmsYPOLg==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.11",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Configuration.FileExtensions": "10.0.11",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Configuration.UserSecrets": {
+ "type": "Direct",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "BRliLdUowglV8GS+J1G/QsSofCJYYFg3U8QZx0ACRn+a91az/Qnpy+h6PyHS94WgV2TSazX5D/cuuk6wnCJatw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Configuration.Json": "10.0.11",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.11",
+ "Microsoft.Extensions.FileProviders.Physical": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Direct",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "PSmotV19c7E3lKed++uYo1kSiXFI+uTl37CBSrhq+CfLC3FCHjG7R91+xPnNehQfHS1b0Tzo/CCLPWH3qaEheg==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11"
+ }
+ },
+ "Nerdbank.GitVersioning": {
+ "type": "Direct",
+ "requested": "[3.8.118, )",
+ "resolved": "3.8.118",
+ "contentHash": "cRaG+ICcECG+CzbtQyUV2WftH7yl2B02AjYGGNScXx8TwYavZYwhCewBTiC0qTcsac7m6AzBUYna5xzBWmTGYw=="
+ },
+ "OpenAI": {
+ "type": "Direct",
+ "requested": "[2.14.0, )",
+ "resolved": "2.14.0",
+ "contentHash": "AeyC3GxbrJ7KRoWDyFeNSUOQQWD9AnNvM7LYQijCcXcqjyr53aGRcf5GBLExcSBzIs0RWYHe+NbzPrHTeuU5zA==",
+ "dependencies": {
+ "System.ClientModel": "1.15.0"
+ }
+ },
+ "Azure.Core": {
+ "type": "Transitive",
+ "resolved": "1.53.0",
+ "contentHash": "x9c/toFMOtRrlTdFuE7rlGCVAduQzWVfKmLz5juj41zJAXEhYD5hluiUyyAEzJ6OxpBnKtiaBztzwpZITAVjtg==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "10.0.3",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.3",
+ "Microsoft.Extensions.Hosting.Abstractions": "10.0.3",
+ "Microsoft.Identity.Client": "4.83.1",
+ "Microsoft.Identity.Client.Extensions.Msal": "4.83.1",
+ "System.ClientModel": "1.10.0",
+ "System.Memory.Data": "10.0.3"
+ }
+ },
+ "ChilliCream.Nitro.App": {
+ "type": "Transitive",
+ "resolved": "32.0.2",
+ "contentHash": "wSD2dFFraVpIsQDiy31k1vkGWYAGdzNVXOhtOIujMt/ADAzfkEbJUsPyF4qoktFspepN4VrAN7DMS8QRqkEhTg==",
+ "dependencies": {
+ "Yarp.ReverseProxy": "2.3.0"
+ }
+ },
+ "GreenDonut": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "nzv5xP1krDEqhq4GekXWdKlvGPb0NM8JF3B0WpEqIS/tVG7U3sBaQuGCMSNJ02kvrtcde+YEPYtcTh7Y0SJ+CA==",
+ "dependencies": {
+ "GreenDonut.Abstractions": "16.6.4",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.ObjectPool": "10.0.0"
+ }
+ },
+ "GreenDonut.Abstractions": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "egSQAz8BbFmLqOWtX0s/xlaqz/43fHUzdu/9TjpZ3s4F8FIVgO4rBfKNFWt2nsba9tvT1AW2WbAaf+3pY6IN0w=="
+ },
+ "GreenDonut.Data": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "kYYLxAEPJl0/vdWF2i5pNs6pndGbuiz8OFAyUovfsu2Guo3dSomkU91PC0kpOeToXoQyRDdjz3GUKNBFnT9PQw==",
+ "dependencies": {
+ "GreenDonut": "16.6.4",
+ "GreenDonut.Data.Abstractions": "16.6.4"
+ }
+ },
+ "GreenDonut.Data.Abstractions": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "Ao8i3nm86+vRKlpctKoWvZ4OdjSLPAQmWp3VMFmCuMVF3rbsVR8TxLRcAG/2/B6VdbGQyOO8tJUGSAooncu28g==",
+ "dependencies": {
+ "GreenDonut.Abstractions": "16.6.4",
+ "GreenDonut.Data.Primitives": "16.6.4"
+ }
+ },
+ "GreenDonut.Data.Primitives": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "p3185VDDm5xV6ZQrkJWkmYaPCVE2BIg6up6R6DrQKnCwIMv3VDzFgNLnVu2eNqoj3iEplBZJBdk1OzvYZO3Xdg=="
+ },
+ "HotChocolate": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "bvEKPvyd0OhZd5usrPxWcGToM860SOlupW+edNobvZiyltlcxnZkfZ7u8Vx8MNtA0OswLyjaL1RI3+JashlE/g==",
+ "dependencies": {
+ "HotChocolate.Authorization": "16.6.4",
+ "HotChocolate.CostAnalysis": "16.6.4",
+ "HotChocolate.Execution.Projections": "16.6.4",
+ "HotChocolate.Types": "16.6.4",
+ "HotChocolate.Types.CursorPagination": "16.6.4",
+ "HotChocolate.Types.CursorPagination.Extensions": "16.6.4",
+ "HotChocolate.Types.Mutations": "16.6.4",
+ "HotChocolate.Types.Queries": "16.6.4",
+ "HotChocolate.Validation": "16.6.4"
+ }
+ },
+ "HotChocolate.Abstractions": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "1ELetbKeMEJXK1D/G9kR55XGF4FkaYS8zvLkWIl/3s75BWPTk97vzC/EBgTEC5Q/Wj7zmBDUwdA7a9noezeoFw==",
+ "dependencies": {
+ "HotChocolate.Execution.Abstractions": "16.6.4",
+ "HotChocolate.Language": "16.6.4",
+ "HotChocolate.Primitives": "16.6.4"
+ }
+ },
+ "HotChocolate.AspNetCore.Pipeline": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "j3T4SnePMXVbrOyniu9SFvA7jOfHlcVjEeyvEh60UD/xaPIP1+L5WofDpP1088JwwvLlpYCWdyEmXhNoFy8Q+g==",
+ "dependencies": {
+ "ChilliCream.Nitro.App": "32.0.2",
+ "HotChocolate.Caching.Memory": "16.6.4",
+ "HotChocolate.PersistedOperations.Abstractions": "16.6.4",
+ "HotChocolate.Transport.Formatters": "16.6.4",
+ "HotChocolate.Transport.Sockets": "16.6.4"
+ }
+ },
+ "HotChocolate.Authorization": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "2TIXgq49SYmfC+NMV+poOq83JeScz0ZkEhHSgv91lNDTZINz06DlxcCrlsf2q+ns8fIS3rbnnHJswBzobE+qUA==",
+ "dependencies": {
+ "HotChocolate.Types": "16.6.4"
+ }
+ },
+ "HotChocolate.Caching.Memory": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "oEOWL5+6wVG7HQHil5EydXcCdV296ZSuUO27mZYAxq5wMx9aX9D/ZkUOWU3To1vo75w767tqrr7+OEGWjPxuiA=="
+ },
+ "HotChocolate.CostAnalysis": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "LcrorDRmMdWjRyCOxnYbqIuDB/qdP5oFXBw4gkgNdnjov0C7BGz5z0M074OvgdzsnqQYb7iDWcaPPtZq6zCVxA==",
+ "dependencies": {
+ "HotChocolate.Types": "16.6.4"
+ }
+ },
+ "HotChocolate.Execution.Abstractions": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "pmaAsn6q4C/elx0SVnTGYWZxy3AqY5V7FYf/3CR8fq7i4rMKH/hHe/qfIoAzC6Phbg1tacHlT2YBeOAssQ3GoA==",
+ "dependencies": {
+ "HotChocolate.Features": "16.6.4",
+ "HotChocolate.Language.SyntaxTree": "16.6.4",
+ "HotChocolate.Language.Web": "16.6.4",
+ "HotChocolate.Primitives": "16.6.4",
+ "HotChocolate.Text.Json": "16.6.4",
+ "HotChocolate.Types.Abstractions": "16.6.4",
+ "HotChocolate.Utilities.Buffers": "16.6.4",
+ "HotChocolate.Utilities.Tasks": "16.6.4",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "HotChocolate.Execution.Configuration.Abstractions": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "OP16Y71IuSuBhGuTNo3gujdBF5HP1WmZYtNV6bUpCv/r4r7dG8rKQYxd2nlnPfTeiFQsvZyqGNKQLxATwxOiCQ==",
+ "dependencies": {
+ "HotChocolate.Abstractions": "16.6.4",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "HotChocolate.Execution.Operation.Abstractions": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "yfXI/ps/VYFyVtj3Z29ImoSLxGfn5OTRXmhkpQtKhQLTiFA8DbxU8/swXRx8bTJL8YS3AOAdPn5qiZBD6rz93Q==",
+ "dependencies": {
+ "HotChocolate.Features": "16.6.4",
+ "HotChocolate.Types.Abstractions": "16.6.4"
+ }
+ },
+ "HotChocolate.Execution.Pipeline": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "ZaJ48M13jKTsVphND7rK+JvWkxM3oDmYLL/JDNj0zjMqMH77PQSLVALK/OOKSI0HxhDbKWdVSvUMKg7MoXrJ5A==",
+ "dependencies": {
+ "HotChocolate.Execution.Abstractions": "16.6.4",
+ "HotChocolate.Validation": "16.6.4",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "HotChocolate.Execution.Projections": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "9cqrsEdbY8JfKgLgRGvM3rBfrC7fvb6rl+kORlXVMOvxDTbL75vrvmKyTHC1HmlJdQ56wTUq33Y6ycEJdoCwNw==",
+ "dependencies": {
+ "GreenDonut.Data": "16.6.4",
+ "GreenDonut.Data.Abstractions": "16.6.4",
+ "GreenDonut.Data.Primitives": "16.6.4",
+ "HotChocolate.Caching.Memory": "16.6.4",
+ "HotChocolate.Execution.Configuration.Abstractions": "16.6.4",
+ "HotChocolate.Types": "16.6.4"
+ }
+ },
+ "HotChocolate.Features": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "0SGN2IDkopXsaxaN0qT+Ww5d/Y+yV4ZvG+xCKU0CvWlTnrq6JrpgeZcJF594EwJnXB4Zja3Wn1piKFEh0ewPDw=="
+ },
+ "HotChocolate.Fusion.Language": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "euXggAJYrOhpd0OpDXLZOQ49AocNkIYUCVEoU6403EDTN46PnaDz2ltGnhcYk8bI1qMq0nm+ZbcmREcdRJfonQ=="
+ },
+ "HotChocolate.Fusion.Utilities": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "HDz/NdyIDNCfUx2JvInVbsr4F3f9a8jyXlnM5mbGV0caZv8Hr1ozyY9NOyltZtkomdk0TKXVN8YaxBWnfwMBLA==",
+ "dependencies": {
+ "HotChocolate.Execution.Abstractions": "16.6.4",
+ "HotChocolate.Fusion.Language": "16.6.4",
+ "HotChocolate.Language": "16.6.4",
+ "HotChocolate.Types.Abstractions": "16.6.4"
+ }
+ },
+ "HotChocolate.Language": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "oLEo6gvXVcKN/sDOSKxB0pFYBId1OSdKB+yxVRzg88M3q8N2uq89Q0P7fnpwUuiobay511gvXXihYaBxNt3xVA==",
+ "dependencies": {
+ "HotChocolate.Language.SyntaxTree": "16.6.4",
+ "HotChocolate.Language.Utf8": "16.6.4",
+ "HotChocolate.Language.Visitors": "16.6.4",
+ "HotChocolate.Language.Web": "16.6.4"
+ }
+ },
+ "HotChocolate.Language.SyntaxTree": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "BDsJMdv6LjYEfGVQiAVhSf50xbAIrigoZUzjUoncbXGXzrfAJaVsGkZs6mR1z0UcTWrlSNoFRosxbtY07iPnCg==",
+ "dependencies": {
+ "HotChocolate.Utilities.Buffers": "16.6.4",
+ "Microsoft.Extensions.ObjectPool": "10.0.0"
+ }
+ },
+ "HotChocolate.Language.Utf8": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "Ria0zRrpy4nXVvuczx14Vbe+8jdVPPryUlKjfUVUZCmU9Ntif/XhaFmVYo3HtS+FVkFHSRA1o0DeTXEoDnzX9Q==",
+ "dependencies": {
+ "HotChocolate.Language.SyntaxTree": "16.6.4",
+ "HotChocolate.Language.Utf8.SyntaxTree": "16.6.4",
+ "HotChocolate.Utilities.Buffers": "16.6.4"
+ }
+ },
+ "HotChocolate.Language.Utf8.SyntaxTree": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "2nnk9e2GT4N8HlVXvtYYOEJysPUiZMQnjtSnLSltW9YC1VW/E4IGnxxJ2Gt7Mj+4yUSlQ+61DnzOD+UtSF09Kg==",
+ "dependencies": {
+ "HotChocolate.Language.SyntaxTree": "16.6.4",
+ "HotChocolate.Utilities.Buffers": "16.6.4"
+ }
+ },
+ "HotChocolate.Language.Visitors": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "MWHB8709Ho2bQkIXuzTGKw91L9z675poWJ1lg6BGmdg3/ZnfsXGAv8cdP/cA4UzB1rOtYJTqrh2YP7xywHvwCQ==",
+ "dependencies": {
+ "HotChocolate.Language.SyntaxTree": "16.6.4"
+ }
+ },
+ "HotChocolate.Language.Web": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "7GWlN019RYlbGJ88j9gw34exwD562PsiJ49zs8RALAzJnmC000KgH5vHikUbPVU5eeO8nUunyCEQafdgypY68A==",
+ "dependencies": {
+ "HotChocolate.Language.Utf8": "16.6.4",
+ "HotChocolate.Language.Visitors": "16.6.4"
+ }
+ },
+ "HotChocolate.PersistedOperations.Abstractions": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "oUpPCiwIfrlk7Cswh+c9J+iRnmNIbRlA7EmGeL/nOR93xSMiCd9zgrkAtBggP4SdyESY9dD628lQZb8AkqXZdw==",
+ "dependencies": {
+ "HotChocolate.Execution.Abstractions": "16.6.4"
+ }
+ },
+ "HotChocolate.PersistedOperations.Pipeline": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "h1VeBRoKQVg5BZnhLHwUHhGApOa8Rk31s64PNG1darAqUnX9v8ZNd/oiv+cQ6CabraQHmbvvvR2DfE/XGsygcA==",
+ "dependencies": {
+ "HotChocolate.PersistedOperations.Abstractions": "16.6.4",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "HotChocolate.Primitives": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "u4FkIs8tKYWJ3I0vTEDPXaPhy4zfhFNZNWqef3tRPGpnQe1rg+7FdM+V1bNs6j94ucY8fX5DTNDJy9OGVe4e3g==",
+ "dependencies": {
+ "HotChocolate.Language": "16.6.4"
+ }
+ },
+ "HotChocolate.Subscriptions": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "L9CzlWy1cHZFixMWyZmtbI5pmqlfwHjGBjF0+pVnbJJaYQv2eSc4Q/8kdQjkhdGuhewPtC44OAMki1br9/Azpw==",
+ "dependencies": {
+ "HotChocolate.Abstractions": "16.6.4",
+ "HotChocolate.Execution.Configuration.Abstractions": "16.6.4",
+ "HotChocolate.Utilities": "16.6.4"
+ }
+ },
+ "HotChocolate.Subscriptions.InMemory": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "/3Tm/h3jw+nrv5CHtszE3iAnG3n3odP842QrTid7mxrEmaMEqE74RA00wTmFaO/bbepCnmymXLxox31nC30TAQ==",
+ "dependencies": {
+ "HotChocolate.Execution.Configuration.Abstractions": "16.6.4",
+ "HotChocolate.Subscriptions": "16.6.4",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "HotChocolate.Text.Json": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "sBxtzPsvDjsw9V9VKy/NomlPE1ruprKHU5iTuHJUZ2i20Ihvq4ouxff0O7yCD1iA32NCaLNL3zvNJagZNV/nTQ=="
+ },
+ "HotChocolate.Transport.Formatters": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "fl16wIiX4FAbSs2TSUM7yorg3awV2cUDNBMN9LU/mPcEN9yzgNN7FsIKQdl1TiqiXSAz5/ihVtBqLJBliws8uw==",
+ "dependencies": {
+ "HotChocolate.Execution.Abstractions": "16.6.4",
+ "HotChocolate.Utilities.Buffers": "16.6.4",
+ "HotChocolate.Utilities.Tasks": "16.6.4"
+ }
+ },
+ "HotChocolate.Transport.Sockets": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "g67fURnanTGuLJwWxRG4E5PJfl+K6TZx8afNc6u+flbbwmTR+7TKEx7b/ZrlzqxCSqASA4H+KN3h4/3nILT+gQ=="
+ },
+ "HotChocolate.Types": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "UEpl+u8WuvQOK1vdlq+2uucLPQpuNXbzt27ij8xcEwOfZAimYC8dGep4MIb1ItdNk2X7PaOegGPQXWoh+oxSiQ==",
+ "dependencies": {
+ "GreenDonut": "16.6.4",
+ "GreenDonut.Data.Primitives": "16.6.4",
+ "HotChocolate.Abstractions": "16.6.4",
+ "HotChocolate.Caching.Memory": "16.6.4",
+ "HotChocolate.Execution.Abstractions": "16.6.4",
+ "HotChocolate.Execution.Configuration.Abstractions": "16.6.4",
+ "HotChocolate.Execution.Operation.Abstractions": "16.6.4",
+ "HotChocolate.Execution.Pipeline": "16.6.4",
+ "HotChocolate.Features": "16.6.4",
+ "HotChocolate.Fusion.Language": "16.6.4",
+ "HotChocolate.Fusion.Utilities": "16.6.4",
+ "HotChocolate.PersistedOperations.Abstractions": "16.6.4",
+ "HotChocolate.PersistedOperations.Pipeline": "16.6.4",
+ "HotChocolate.Text.Json": "16.6.4",
+ "HotChocolate.Transport.Formatters": "16.6.4",
+ "HotChocolate.Types.Abstractions": "16.6.4",
+ "HotChocolate.Utilities": "16.6.4",
+ "HotChocolate.Utilities.Base36": "16.6.4",
+ "HotChocolate.Utilities.DependencyInjection": "16.6.4",
+ "Microsoft.Extensions.DependencyInjection": "10.0.0",
+ "Microsoft.Extensions.ObjectPool": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "HotChocolate.Types.Abstractions": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "KrftIDiSImZmhQv+Johy6cGOzIKizZS4TbsJwzlSINrUtj/L8G7RVvFaUTl/iYXYIdganPopITsSCu+fs3UIVA==",
+ "dependencies": {
+ "HotChocolate.Features": "16.6.4",
+ "HotChocolate.Primitives": "16.6.4"
+ }
+ },
+ "HotChocolate.Types.CursorPagination": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "hNoVzFKkZGzTofL0nPtMeqFpv6+zy2jqY9Ef3vnJuzSwCjD08g4SJNt947ViksDoqMUVPtH3xjZMiOS2vN9Z6w==",
+ "dependencies": {
+ "HotChocolate.Execution.Configuration.Abstractions": "16.6.4",
+ "HotChocolate.Types": "16.6.4"
+ }
+ },
+ "HotChocolate.Types.CursorPagination.Extensions": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "uaWfK7+/WpYF/zOoeLF+QutSVHP3hQEW+MKHRc76Fg4tuhDxSw6c7rW3wEbOys7W1kAgnKfeVWtYkQCj4ifBBg==",
+ "dependencies": {
+ "GreenDonut.Data": "16.6.4",
+ "HotChocolate.Types.CursorPagination": "16.6.4"
+ }
+ },
+ "HotChocolate.Types.Errors": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "S9KNljhZe94L/OQse+VsVwwIUunoyjBv4IvTfjCPy/6IWvc96q6Pkw5wC9C42X32PrCPqTsXL6vsc7G8mQLh3A==",
+ "dependencies": {
+ "HotChocolate.Types": "16.6.4"
+ }
+ },
+ "HotChocolate.Types.Mutations": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "l5umZs2JyB3wq8giyucXLKmKkaFEZxidzhaiZ2DsxXq969v0OlgZiGxdU5puMUJ1XNrWtQUocnURgo8tqOg/pg==",
+ "dependencies": {
+ "HotChocolate.Types": "16.6.4",
+ "HotChocolate.Types.Errors": "16.6.4"
+ }
+ },
+ "HotChocolate.Types.Queries": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "WiMtlmgToK8/GLFR5zdUT9YdSmpU2kkDTd7l+56r1TB934+2Qp2hzl0zd6THCPx4Hd9BocwMjrUggSCgnDuDng==",
+ "dependencies": {
+ "HotChocolate.Types": "16.6.4",
+ "HotChocolate.Types.Errors": "16.6.4"
+ }
+ },
+ "HotChocolate.Types.Scalars.Upload": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "GWkhJth8tpx3zF8xXu7oxXB+aeTGclwDZR8/kA0CI/efsIRbAj5k13HxTN7WG9/b7/SdV+iJer6pRS1J1fWOYQ==",
+ "dependencies": {
+ "HotChocolate.Types": "16.6.4"
+ }
+ },
+ "HotChocolate.Utilities": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "8kg+EoA7eS0uIOR/06CzKcEaZprWAxecwUkHFS2cOys7uRkXaxjgVfzwz1wARkAXEHhaMhFEQvVjHghQGQodYA==",
+ "dependencies": {
+ "HotChocolate.Utilities.Buffers": "16.6.4",
+ "HotChocolate.Utilities.Tasks": "16.6.4",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "HotChocolate.Utilities.Base36": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "i0zQoDkaSXR07627r1l7SQ0psF9zOa7CUsmR7vrSmwhBItYe2AVR6z4M58JDo1MoHR5Nt6Mp8Y0dgrOL6OM6zg=="
+ },
+ "HotChocolate.Utilities.Buffers": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "oeadDwUfn3oF97oNwF3QD3gEoOPOxl/sKwFGKj9BXNwgQnm9ho4DRFZrY0v4Gk78sGEsSxzfK8YlUz7pl5aAXA=="
+ },
+ "HotChocolate.Utilities.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "1mw7EmE6mF/Ui+LGW1cyVPm0Rvko+szyU5q3AsH5NmiT+9iEEReLm3h716nF9f4RsYGnuNdXuUt1+eE6tfs/AQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "10.0.0"
+ }
+ },
+ "HotChocolate.Utilities.Tasks": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "/zsN3ARuQe39QWMEMlaQCV4Td4kSa4Ppzh979YeXATB7S039QyDyExgtzsPw2gu0WamuH+hqPsGdo3hSRqqUIQ=="
+ },
+ "HotChocolate.Validation": {
+ "type": "Transitive",
+ "resolved": "16.6.4",
+ "contentHash": "H104wO+jzcY8OhZE9QEKWs5NGtC4Kj04oJOsgJ+do3KI2go9fKNtrHKfJLFfuR6HaREn6SDqswYViiR4BGItSg==",
+ "dependencies": {
+ "HotChocolate.Execution.Abstractions": "16.6.4",
+ "HotChocolate.Types.Abstractions": "16.6.4",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.AspNetCore.TestHost": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "IVGNbZVxLuL80y7cmXYfhIFoTGneHkp4D7xXarYe6V/wjo8/2qiSLUwWax1/h2eHtJ3Y5cuqmtpOyWMnXIsUMA=="
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "10.0.3",
+ "contentHash": "TV62UsrJZPX6gbt3c4WrtXh7bmaDIcMqf9uft1cc4L6gJXOU07hDGEh+bFQh/L2Az0R1WVOkiT66lFqS6G2NmA=="
+ },
+ "Microsoft.Extensions.Caching.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.12",
+ "contentHash": "sI3A6MUAyZwccLnwq0cXuRmC3WBtXieimBWafXSfhRJ4jnM2uGVXrqImDDVyW27u4vVaTOGlJxNJd8d1FGvCNQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.12"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "fVi053xdpda9Em7vSkmgVxO/PtgC2m78ekReKWsgcyskqY0U82Bz/MONwxpGzI0hElYKJfw+fupqMVeKW3fSaA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Binder": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "rFn8RuszZn3qquPVkDytMUlPc2+rXl9MCoygwc1XmAgC5vg5/oXJ8hkOosOrLoBLsqdTy4lFwP6iQdPS9uSYOA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.11",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Configuration.CommandLine": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "1KHr/1L56llwQ/yI0tAisEA31UpPsn8aasjASIwELOaN4JIUcbjuQBMdFOIzfNBBeULoUa0XfBe5QDtRRUY+fg==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.11",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.12",
+ "contentHash": "9/qymSh7hVDMGTGwrLz8MRp5zRyXy9adGDOs4HwRdnLil3oZGYuWeZjbmHgCQ9BL1qBroVfgUK3U/nb61617Cw=="
+ },
+ "Microsoft.Extensions.DependencyModel": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "PJPtFYsZ+r+uz9qqXWUTEyKeJ1EiBGIJtqavkg9ZXijjGSFAk4Fgi5sqIxj+uAyLZwEKgexDUQXhWhvU6l3+og=="
+ },
+ "Microsoft.Extensions.Diagnostics": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "HT70uGPxMLqqnOzKMcnQtDmeV4r0KHr4qVCLhP7SXil9jMEm8sQXwcybxVVFGXZJ1V44xV0mLqQ54aZbcR2OiQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.11",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Diagnostics.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "se7Kx8QpJEt+nf26L4qIVAofGTDr1wbexxsh/Fm3Xc04xUkqUXK06KUS7FLwSQYSjqb7q9n+T7MEcXYBhI1Y5g==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Options": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.FileProviders.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "JOjac6SQQgZmdmB8WGEw61/7siqMZoWJMkmq2p1goJGxqI59lO6oB4bOl0jNsbaPBdYy5Mlkb+6U7T4+CjnD8Q==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.FileProviders.Physical": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "Tq/UqMaczePv9yWwSsJZRgKtgA46djVR5xHj/lZBCueQ3ag8f9v5mu0EdhrNx7tXxNk+Y9OurG2oKuSKINjr0A==",
+ "dependencies": {
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.11",
+ "Microsoft.Extensions.FileSystemGlobbing": "10.0.11",
+ "Microsoft.Extensions.Primitives": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.FileSystemGlobbing": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "2i6rtW/B5rCnWCnhdmWWEmaM9O0HD0zsPY9eRqa++y4tclI3Uw8zvGbBvhY/LjAdtf8gUHhUPcAWj3DRlWMXmQ=="
+ },
+ "Microsoft.Extensions.Hosting": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "eIDa/Rl+93aj17gMlFsJJx+LhBvb3CP0Mu1PeVYkDp2Y3S4Jock8UynfGQEcx7lrlq+gKW+ECQJHbro/LTPDEQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.11",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Configuration.Binder": "10.0.11",
+ "Microsoft.Extensions.Configuration.CommandLine": "10.0.11",
+ "Microsoft.Extensions.Configuration.EnvironmentVariables": "10.0.11",
+ "Microsoft.Extensions.Configuration.FileExtensions": "10.0.11",
+ "Microsoft.Extensions.Configuration.Json": "10.0.11",
+ "Microsoft.Extensions.Configuration.UserSecrets": "10.0.11",
+ "Microsoft.Extensions.DependencyInjection": "10.0.11",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Diagnostics": "10.0.11",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.11",
+ "Microsoft.Extensions.FileProviders.Physical": "10.0.11",
+ "Microsoft.Extensions.Hosting.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Logging": "10.0.11",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Logging.Configuration": "10.0.11",
+ "Microsoft.Extensions.Logging.Console": "10.0.11",
+ "Microsoft.Extensions.Logging.Debug": "10.0.11",
+ "Microsoft.Extensions.Logging.EventLog": "10.0.11",
+ "Microsoft.Extensions.Logging.EventSource": "10.0.11",
+ "Microsoft.Extensions.Options": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Hosting.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "pwtpF7iF/NNaOBcX+pvMZ7y2+JAVbH5KkNrH9uMZtuVxVJsFTDiWiCR7Tk3HVptsAijaetipUZVRVK2LLq+nvA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.11",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.12",
+ "contentHash": "+24lC4plfbEDNfLAdTV/SWKS7dW+16X4HdydO3R++134kSNTzcbYA4KpR1Hdh6uWisB8Za3AzwyOn+K+NxWIug==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.12"
+ }
+ },
+ "Microsoft.Extensions.Logging.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "S7LvLeVHKNPaY2NMyxW7c2TBGsLgxoSUBCV5Ev5iN8kgC7EPR2UB7eW7vHsElGMcIUDwRmoxLfvGDynCn3q6EA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.11",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Configuration.Binder": "10.0.11",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Logging": "10.0.11",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Options": "10.0.11",
+ "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Logging.Debug": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "wr+j1bjdFXhc8lKTLoq+RbwFM8M+orcMS9xrcqLmDGOxJcXpKizEeE5h6v/GKwCZV02FmhaA7OlNjoq072jZpQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Logging": "10.0.11",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Logging.EventLog": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "Eck9GpCCpvZ3f6L7IUlN+mPtRVefnf7PsiIG5vi61QawPtLNCEAv2TPD/M3SojcU0PFaef+BxiVGPOShFHtDog==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Logging": "10.0.11",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Options": "10.0.11",
+ "System.Diagnostics.EventLog": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Logging.EventSource": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "hs6QWECLLohi2VKqUvSGRUvrg7eXR1DqKL95Jrtz3cdD2g2nBA+yJPdRQLZ7SLmnTZWycxfMDK2s0ho+rfst5w==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Logging": "10.0.11",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Options": "10.0.11",
+ "Microsoft.Extensions.Primitives": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.ObjectPool": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "bpeCq0IYmVLACyEUMzFIOQX+zZUElG1t+nu1lSxthe7B+1oNYking7b91305+jNB6iwojp9fqTY9O+Nh7ULQxg=="
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "eY1GAKcTfD2maP27J84X9IovT3yjHJ2dVDzPmDg6/XqYvt3jMzJhtfQCLjG9pVsZGAd+8DQ2QrjaDcs2+VQLGw==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Primitives": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Options.ConfigurationExtensions": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "syEhXQ/sEaSBFaqzlp9gDGHX/nk6gkQkh1sIUpBO1mlBj3Phu1rmb4ML1uCiyPW9N6Kxfxv3y5FGObC+bV01Qw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Configuration.Binder": "10.0.11",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Options": "10.0.11",
+ "Microsoft.Extensions.Primitives": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "10.0.12",
+ "contentHash": "dYfCLR52UA+3DL7C4I/pvSaRPkNqxrUAQmbFL2u0zvYKKzqgrFCJl08Df+F1aYc8leu9JvpC9bsURUdpExcBXQ=="
+ },
+ "Microsoft.Identity.Client": {
+ "type": "Transitive",
+ "resolved": "4.83.1",
+ "contentHash": "jOLIrZ3cynoqHLLO1cXplFFabrhrMEYs/EuKHvmCyrOm1axqiVFT6nCSnHxk7w5+d2BeQfCdM12Yf/0X7OeS1g==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "8.14.0"
+ }
+ },
+ "Microsoft.Identity.Client.Extensions.Msal": {
+ "type": "Transitive",
+ "resolved": "4.83.1",
+ "contentHash": "I3k4J4Hj4KbLEFanjeUzzDOVecukETaTgEkJ7h2pP/Yazs6SLp6TVUTo/Eo+ptPXMwvc+iX7rBFtMSUrA7R+Mg==",
+ "dependencies": {
+ "Microsoft.Identity.Client": "4.83.1",
+ "System.Security.Cryptography.ProtectedData": "4.5.0"
+ }
+ },
+ "Microsoft.IdentityModel.Abstractions": {
+ "type": "Transitive",
+ "resolved": "8.14.0",
+ "contentHash": "iwbCpSjD3ehfTwBhtSNEtKPK0ICun6ov7Ibx6ISNA9bfwIyzI2Siwyi9eJFCJBwxowK9xcA1mj+jBWiigeqgcQ=="
+ },
+ "Microsoft.IO.RecyclableMemoryStream": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "irv0HuqoH8Ig5i2fO+8dmDNdFdsrO+DoQcedwIlb810qpZHBNQHZLW7C/AHBQDgLLpw2T96vmMAy/aE4Yj55Sg=="
+ },
+ "System.ClientModel": {
+ "type": "Transitive",
+ "resolved": "1.15.0",
+ "contentHash": "y6zQLInrpX+oGL1gXM04DrUSu1O1esWxt4rD/zrujTnzIFChn/noD1OiVVpTrU8ZvglwqO2Uw038svUR3SiAOg==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.9",
+ "Microsoft.Extensions.Hosting.Abstractions": "10.0.9",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.9",
+ "System.Memory.Data": "10.0.9"
+ }
+ },
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "10.0.11",
+ "contentHash": "QTXEoQBzz00SFWbo7nAg1Ogd4f99lwqcO9uAJ7MYSLEUR28f6As32QktrqG2Fr9cfAfd1GjLyGYspE7Ipj7P6w=="
+ },
+ "System.IO.Hashing": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "ne1843evDugl0md7Fjzy6QjJrzsjh46ZKbhf8GwBXb5f/gw97J4bxMs0NQKifDuThh/f0bZ0e62NPl1jzTuRqA=="
+ },
+ "System.Memory.Data": {
+ "type": "Transitive",
+ "resolved": "10.0.9",
+ "contentHash": "YweovHiLUoEdbr2Xv8eRqCSkTu1vMms4a6xBHaQiMSFVy32PL+hXv6Vhol2NWOmLHjaVgTyhJ3R52U6JxS6w3Q=="
+ },
+ "System.Numerics.Tensors": {
+ "type": "Transitive",
+ "resolved": "10.0.12",
+ "contentHash": "17brFrnQHV/XMMazXNqFq4GkvzWy8yzDPo5Gb8TT8zJtMFbUqDycOCyPCp9F+eMc4L75kcCKRZqaeBHMwLCL9Q=="
+ },
+ "System.Reactive": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "31kfaW4ZupZzPsI5PVe77VhnvFF55qgma7KZr/E0iFTs6fmdhhG8j0mgEx620iLTey1EynOkEfnyTjtNEpJzGw=="
+ },
+ "System.Security.Cryptography.ProtectedData": {
+ "type": "Transitive",
+ "resolved": "4.5.0",
+ "contentHash": "wLBKzFnDCxP12VL9ANydSYhk59fC4cvOr9ypYQLPnAj48NQIhqnjdD2yhP8yEKyBJEjERWS9DisKL7rX5eU25Q=="
+ },
+ "Yarp.ReverseProxy": {
+ "type": "Transitive",
+ "resolved": "2.3.0",
+ "contentHash": "gxtkN3a+9biu9V9Zd5NaTO6VZWXAnS2mhQ0R/VXmSPoTuiQNZsakKikrKpDtKxrL5nUYzbRsHtl40WNq+ZBKKg==",
+ "dependencies": {
+ "System.IO.Hashing": "8.0.0"
+ }
+ },
+ "linq2graphql.client": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.Extensions.Caching.Memory": "[10.0.11, )",
+ "Microsoft.Extensions.Http": "[10.0.11, )"
+ }
+ },
+ "linq2graphql.client.ai": {
+ "type": "Project",
+ "dependencies": {
+ "GraphQL-Parser": "[9.5.1, )",
+ "Linq2GraphQL.Client": "[1.0.0, )",
+ "Microsoft.Extensions.AI.Abstractions": "[10.10.0, )"
+ }
+ },
+ "linq2graphql.client.subscriptions": {
+ "type": "Project",
+ "dependencies": {
+ "Linq2GraphQL.Client": "[1.0.0, )",
+ "Websocket.Client": "[5.3.0, )"
+ }
+ },
+ "linq2graphql.testclient": {
+ "type": "Project",
+ "dependencies": {
+ "Linq2GraphQL.Client": "[1.0.0, )",
+ "Linq2GraphQL.Client.Subscriptions": "[1.0.0, )"
+ }
+ },
+ "linq2graphql.testserver": {
+ "type": "Project",
+ "dependencies": {
+ "HotChocolate.AspNetCore": "[16.6.4, )",
+ "HotChocolate.Data": "[16.6.4, )",
+ "HotChocolate.Types.Analyzers": "[16.6.4, )",
+ "Linq2GraphQL.TestServer.Shared": "[1.0.0, )"
+ }
+ },
+ "linq2graphql.testserver.shared": {
+ "type": "Project",
+ "dependencies": {
+ "HotChocolate.AspNetCore": "[16.6.4, )",
+ "HotChocolate.Data": "[16.6.4, )"
+ }
+ },
+ "GraphQL-Parser": {
+ "type": "CentralTransitive",
+ "requested": "[9.5.1, )",
+ "resolved": "9.5.1",
+ "contentHash": "pUYpupTsVyNcKemko8f0iknJa2z/oZsfzwb4crgEFN9/pKf3k35gxVXDDOkD3NVPF1ea6GUV0jgxkjCozFj7Fg=="
+ },
+ "HotChocolate.AspNetCore": {
+ "type": "CentralTransitive",
+ "requested": "[16.6.4, )",
+ "resolved": "16.6.4",
+ "contentHash": "sxqZ+B2asfW/vAznKNl+xP+sf8eR3h4lRKYrmDtJPTAbJ4Z8+rWW6DNqbFyoU1LAl1teTbRwPaGPxEqYKumA2Q==",
+ "dependencies": {
+ "ChilliCream.Nitro.App": "32.0.2",
+ "HotChocolate": "16.6.4",
+ "HotChocolate.AspNetCore.Pipeline": "16.6.4",
+ "HotChocolate.Subscriptions.InMemory": "16.6.4",
+ "HotChocolate.Transport.Formatters": "16.6.4",
+ "HotChocolate.Transport.Sockets": "16.6.4",
+ "HotChocolate.Types.Scalars.Upload": "16.6.4",
+ "HotChocolate.Utilities.DependencyInjection": "16.6.4"
+ }
+ },
+ "HotChocolate.Data": {
+ "type": "CentralTransitive",
+ "requested": "[16.6.4, )",
+ "resolved": "16.6.4",
+ "contentHash": "ruKaYosX4yTOAVeDEQfHFSjuIhmCeQpq3ritskH8i74wn8hKhPRsFA9iFPom3qpiZkCJxsCIPQZumGJGf6xpkQ==",
+ "dependencies": {
+ "GreenDonut.Data": "16.6.4",
+ "GreenDonut.Data.Abstractions": "16.6.4",
+ "GreenDonut.Data.Primitives": "16.6.4",
+ "HotChocolate.Execution.Operation.Abstractions": "16.6.4",
+ "HotChocolate.Execution.Projections": "16.6.4",
+ "HotChocolate.Types": "16.6.4",
+ "HotChocolate.Types.CursorPagination.Extensions": "16.6.4"
+ }
+ },
+ "HotChocolate.Types.Analyzers": {
+ "type": "CentralTransitive",
+ "requested": "[16.6.4, )",
+ "resolved": "16.6.4",
+ "contentHash": "bigjWuAkEQvxoQCrUzAvowiqS7YrTciape6++hB9YpA2cFH5RQnG+xyTo/MvWCN5jSvnW4izvdae9mhxtfhZZA=="
+ },
+ "Microsoft.Extensions.AI.Abstractions": {
+ "type": "CentralTransitive",
+ "requested": "[10.10.0, )",
+ "resolved": "10.10.0",
+ "contentHash": "frBHj2ckpevA+KdDLikxv8oxGPrJiyTvaiblYp+vtVEt0q6J73XP5m2SICm86nFK6rl+L1GCKxIy4S5Lb3p2kQ=="
+ },
+ "Microsoft.Extensions.Caching.Memory": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "el1g0mBEbDBGY2bT9mcSfrTWO8QlPdq2nOCnvQugioOFwHV+bVBMeiakoI0dNOdj8d6Hi9K6HY2xzRUWJiDR3w==",
+ "dependencies": {
+ "Microsoft.Extensions.Caching.Abstractions": "10.0.11",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Options": "10.0.11",
+ "Microsoft.Extensions.Primitives": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Configuration.FileExtensions": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "mDW7KVFB05M6jiRUyaZiOMWhS31n5HlSZwoYctHAZAucD4sMDJ70IxOmkGDt6RpstchD+keWBjhdzcMpSkWvWQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.11",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.11",
+ "Microsoft.Extensions.FileProviders.Physical": "10.0.11",
+ "Microsoft.Extensions.Primitives": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Http": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "ujx8RvcKzkxPFBguwgiygbwWVHVK0P7HFlNJ6I0JBRb28tzwe42jixBoA+dGmqG9IHepPVcm04vv2IDnU93ekA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Diagnostics": "10.0.11",
+ "Microsoft.Extensions.Logging": "10.0.11",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Options": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "nUOJwgFkSiLHiVGFpU22pIJtuWYewuSYQ3JVuP/gdK8ASMT807Px+TYQiRWs6uSsOmoyFTaVCwKXTasczV6BpA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "10.0.11",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Options": "10.0.11"
+ }
+ },
+ "Microsoft.Extensions.Logging.Console": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "dFc0yDudyD1iIg6z9XT7ofsT3hVO7Y4ylrxGHIVRR0GaZ4CUk4ujOrMoy7wWEdNHZhvJooySg6hZpOxyS8zEVA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Logging": "10.0.11",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Logging.Configuration": "10.0.11",
+ "Microsoft.Extensions.Options": "10.0.11"
+ }
+ },
+ "Websocket.Client": {
+ "type": "CentralTransitive",
+ "requested": "[5.3.0, )",
+ "resolved": "5.3.0",
+ "contentHash": "uhdDM+gruCEhHRCKCoyali1HJp0wSS/HBs5X9XZwULNKM2y5ML188TsvcEgWEFOx0NOaHfGNtfoC0cd1p2NOIg==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "8.0.0",
+ "Microsoft.IO.RecyclableMemoryStream": "3.0.0",
+ "System.Reactive": "6.0.0"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Linq2GraphQL.Agent.Sample/questions.json b/test/Linq2GraphQL.Agent.Sample/questions.json
new file mode 100644
index 00000000..518e504c
--- /dev/null
+++ b/test/Linq2GraphQL.Agent.Sample/questions.json
@@ -0,0 +1,10 @@
+[
+ { "question": "Say hello to Magnus using the API.", "expected": ["Hello, Magnus!"] },
+ { "question": "Which customers are active?", "expected": ["Universal Ltd"] },
+ { "question": "What is the status of the customer Jocke Pocke?", "expected": ["disabled"] },
+ { "question": "How many orders does Universal Ltd have?", "expected": ["2"] },
+ { "question": "Which customer has an order delivered to Garden Inc?", "expected": ["Universal Ltd"] },
+ { "question": "What is the price of item 12345 on Universal Ltd's orders?", "expected": ["56.4"] },
+ { "question": "What is the name of the spider, and how many legs does it have?", "expected": ["Imse", "8"] },
+ { "question": "Which animal is the fastest?", "expected": ["Imse"] }
+]
diff --git a/test/Linq2GraphQL.Tests/AgentLoopTests.cs b/test/Linq2GraphQL.Tests/AgentLoopTests.cs
new file mode 100644
index 00000000..cb4db86c
--- /dev/null
+++ b/test/Linq2GraphQL.Tests/AgentLoopTests.cs
@@ -0,0 +1,114 @@
+using System.Runtime.CompilerServices;
+using System.Text.Json;
+using Linq2GraphQL.Client.AI;
+using Linq2GraphQL.TestClient;
+using Microsoft.Extensions.AI;
+using Shouldly;
+
+namespace Linq2GraphQL.Tests;
+
+///
+/// Runs the whole agent loop in CI without a model: a scripted chat client plays the model's part, asking for
+/// tool calls in a fixed order, and Microsoft.Extensions.AI's function invocation runs the real tools against
+/// the test server. It checks the wiring end to end, not answer quality; that is what the sample's eval mode
+/// does with a real model.
+///
+public class AgentLoopTests : IClassFixture
+{
+ private readonly SampleClient client;
+
+ public AgentLoopTests(SampleClientFixture fixture)
+ {
+ client = fixture.sampleClient;
+ }
+
+ private IList Tools() => client.AsAgentTools(o =>
+ {
+ o.AllowQuery(c => c.Query.Customers);
+ o.AllowQuery(c => c.Query.Animals);
+ });
+
+ [Fact]
+ public async Task ScriptedAgent_ExploresQueriesAndAnswers()
+ {
+ var model = new ScriptedChatClient(
+ Call("search_schema", new { text = "customer" }),
+ Call("describe_operation", new { names = new[] { "customers" } }),
+ Call("graphql_query", new { query = "{ customers { customerName status } }" }),
+ Answer());
+
+ var response = await Agent(model).GetResponseAsync("Which customers are active?", new ChatOptions { Tools = [..Tools()] });
+
+ model.ToolResults.Count.ShouldBe(3);
+ model.ToolResults[0].ShouldContain("operation customers");
+ model.ToolResults[1].ShouldContain("Starter query:");
+ response.Text.ShouldContain("Universal Ltd");
+ response.Text.ShouldContain("ACTIVE");
+ }
+
+ [Fact]
+ public async Task ScriptedAgent_FixesARejectedQuery()
+ {
+ var model = new ScriptedChatClient(
+ Call("graphql_query", new { query = "{ animals { name } }" }),
+ Call("graphql_query", new { query = "{ animals { nodes { name } } }" }),
+ Answer());
+
+ var response = await Agent(model).GetResponseAsync("Name the animals.", new ChatOptions { Tools = [..Tools()] });
+
+ model.ToolResults[0].ShouldContain("validationErrors");
+ model.ToolResults[0].ShouldContain("This field is paged");
+ response.Text.ShouldContain("Kalle");
+ response.Text.ShouldContain("Imse");
+ }
+
+ private static IChatClient Agent(IChatClient model) => model.AsBuilder().UseFunctionInvocation().Build();
+
+ private static Func Call(string tool, object arguments) => step =>
+ new ChatResponse(new ChatMessage(ChatRole.Assistant,
+ [
+ new FunctionCallContent($"call-{step}", tool,
+ JsonSerializer.Deserialize>(JsonSerializer.Serialize(arguments)))
+ ]));
+
+ ///
+ /// The final turn: answers with the last tool result, so the test can see the data flowed back.
+ ///
+ private static Func Answer() => _ => null!;
+
+ private sealed class ScriptedChatClient(params Func[] script) : IChatClient
+ {
+ private int step;
+
+ public List ToolResults { get; } = [];
+
+ public Task GetResponseAsync(IEnumerable messages, ChatOptions? options = null,
+ CancellationToken cancellationToken = default)
+ {
+ var results = messages.SelectMany(e => e.Contents).OfType()
+ .Select(e => e.Result is JsonElement { ValueKind: JsonValueKind.String } text ? text.GetString()! : e.Result?.ToString() ?? "")
+ .ToList();
+ ToolResults.Clear();
+ ToolResults.AddRange(results);
+
+ var response = script[step](step);
+ step++;
+ return Task.FromResult(response ?? new ChatResponse(new ChatMessage(ChatRole.Assistant, ToolResults.LastOrDefault() ?? "")));
+ }
+
+ public async IAsyncEnumerable GetStreamingResponseAsync(IEnumerable messages,
+ ChatOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
+ {
+ foreach (var update in (await GetResponseAsync(messages, options, cancellationToken)).ToChatResponseUpdates())
+ {
+ yield return update;
+ }
+ }
+
+ public object? GetService(Type serviceType, object? serviceKey = null) => null;
+
+ public void Dispose()
+ {
+ }
+ }
+}
diff --git a/test/Linq2GraphQL.Tests/Linq2GraphQL.Tests.csproj b/test/Linq2GraphQL.Tests/Linq2GraphQL.Tests.csproj
index dcc85674..dc40db00 100644
--- a/test/Linq2GraphQL.Tests/Linq2GraphQL.Tests.csproj
+++ b/test/Linq2GraphQL.Tests/Linq2GraphQL.Tests.csproj
@@ -11,6 +11,7 @@
+
diff --git a/test/Linq2GraphQL.Tests/packages.lock.json b/test/Linq2GraphQL.Tests/packages.lock.json
index a37a9b2f..b5ead633 100644
--- a/test/Linq2GraphQL.Tests/packages.lock.json
+++ b/test/Linq2GraphQL.Tests/packages.lock.json
@@ -19,6 +19,19 @@
"Microsoft.Extensions.Hosting": "10.0.11"
}
},
+ "Microsoft.Extensions.AI": {
+ "type": "Direct",
+ "requested": "[10.10.0, )",
+ "resolved": "10.10.0",
+ "contentHash": "XKvtDUD3KySkvA5UpS+UF67M5rcqiXjAQchTZZ26WnavVKXxwlUTVdK/Ju0tc/25+16AVUdNl8cnVVGX/tx03A==",
+ "dependencies": {
+ "Microsoft.Extensions.AI.Abstractions": "10.10.0",
+ "Microsoft.Extensions.Caching.Abstractions": "10.0.12",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.12",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.12",
+ "System.Numerics.Tensors": "10.0.12"
+ }
+ },
"Microsoft.NET.Test.Sdk": {
"type": "Direct",
"requested": "[17.14.1, )",
@@ -548,10 +561,10 @@
},
"Microsoft.Extensions.Caching.Abstractions": {
"type": "Transitive",
- "resolved": "10.0.11",
- "contentHash": "vUl798SmruTqqlt/xH2gDk3tJlhk6k3HdOXAHirlRfbNKDym4g/kRpUL9S4sl6F6FsOTOMW+ZsDapqlZMOOiEw==",
+ "resolved": "10.0.12",
+ "contentHash": "sI3A6MUAyZwccLnwq0cXuRmC3WBtXieimBWafXSfhRJ4jnM2uGVXrqImDDVyW27u4vVaTOGlJxNJd8d1FGvCNQ==",
"dependencies": {
- "Microsoft.Extensions.Primitives": "10.0.11"
+ "Microsoft.Extensions.Primitives": "10.0.12"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
@@ -580,30 +593,10 @@
"Microsoft.Extensions.Configuration.Abstractions": "10.0.11"
}
},
- "Microsoft.Extensions.Configuration.EnvironmentVariables": {
- "type": "Transitive",
- "resolved": "10.0.11",
- "contentHash": "KICyU3eVi5jvloKm01EXV69L97H/zkhISVtV98cIuzuFOxNx3xTUVcXqvWTz3aq7OvUuDB/MFlPFjmxRaKF7/A==",
- "dependencies": {
- "Microsoft.Extensions.Configuration": "10.0.11",
- "Microsoft.Extensions.Configuration.Abstractions": "10.0.11"
- }
- },
- "Microsoft.Extensions.Configuration.UserSecrets": {
- "type": "Transitive",
- "resolved": "10.0.11",
- "contentHash": "BRliLdUowglV8GS+J1G/QsSofCJYYFg3U8QZx0ACRn+a91az/Qnpy+h6PyHS94WgV2TSazX5D/cuuk6wnCJatw==",
- "dependencies": {
- "Microsoft.Extensions.Configuration.Abstractions": "10.0.11",
- "Microsoft.Extensions.Configuration.Json": "10.0.11",
- "Microsoft.Extensions.FileProviders.Abstractions": "10.0.11",
- "Microsoft.Extensions.FileProviders.Physical": "10.0.11"
- }
- },
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
- "resolved": "10.0.11",
- "contentHash": "/a1aJz4m7ylhEDf25ugQChLQoN5XwoGjWw/BoR/ZWWKsO1v4DdJElS1uyngahz4B/eOzjFk1KNTkarRLE5wsIg=="
+ "resolved": "10.0.12",
+ "contentHash": "9/qymSh7hVDMGTGwrLz8MRp5zRyXy9adGDOs4HwRdnLil3oZGYuWeZjbmHgCQ9BL1qBroVfgUK3U/nb61617Cw=="
},
"Microsoft.Extensions.DependencyModel": {
"type": "Transitive",
@@ -695,10 +688,10 @@
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
- "resolved": "10.0.11",
- "contentHash": "Ljd0Uxoq5XpScD2Bg0nM/r3mwx7Ao5Uq24eo2ARxbGvqJ7Zht6rt2cJtwVRH4Cv+1ZVMdXz6TB43KbpmsxRrvQ==",
+ "resolved": "10.0.12",
+ "contentHash": "+24lC4plfbEDNfLAdTV/SWKS7dW+16X4HdydO3R++134kSNTzcbYA4KpR1Hdh6uWisB8Za3AzwyOn+K+NxWIug==",
"dependencies": {
- "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11"
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.12"
}
},
"Microsoft.Extensions.Logging.Configuration": {
@@ -778,8 +771,8 @@
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
- "resolved": "10.0.11",
- "contentHash": "SXcz+kF+4Oo9b1+55zntpJFYfwb1jw66ioxptyNOOTDc8g2FHnBFWjZpsWfCvZIhzr0x+4e2trVTs4OKwQfBtw=="
+ "resolved": "10.0.12",
+ "contentHash": "dYfCLR52UA+3DL7C4I/pvSaRPkNqxrUAQmbFL2u0zvYKKzqgrFCJl08Df+F1aYc8leu9JvpC9bsURUdpExcBXQ=="
},
"Microsoft.IO.RecyclableMemoryStream": {
"type": "Transitive",
@@ -823,6 +816,11 @@
"System.CodeDom": "6.0.0"
}
},
+ "System.Numerics.Tensors": {
+ "type": "Transitive",
+ "resolved": "10.0.12",
+ "contentHash": "17brFrnQHV/XMMazXNqFq4GkvzWy8yzDPo5Gb8TT8zJtMFbUqDycOCyPCp9F+eMc4L75kcCKRZqaeBHMwLCL9Q=="
+ },
"System.Reactive": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -1035,6 +1033,16 @@
"Microsoft.Extensions.Primitives": "10.0.11"
}
},
+ "Microsoft.Extensions.Configuration.EnvironmentVariables": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "KICyU3eVi5jvloKm01EXV69L97H/zkhISVtV98cIuzuFOxNx3xTUVcXqvWTz3aq7OvUuDB/MFlPFjmxRaKF7/A==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.11",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11"
+ }
+ },
"Microsoft.Extensions.Configuration.FileExtensions": {
"type": "CentralTransitive",
"requested": "[10.0.11, )",
@@ -1060,6 +1068,18 @@
"Microsoft.Extensions.FileProviders.Abstractions": "10.0.11"
}
},
+ "Microsoft.Extensions.Configuration.UserSecrets": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.11, )",
+ "resolved": "10.0.11",
+ "contentHash": "BRliLdUowglV8GS+J1G/QsSofCJYYFg3U8QZx0ACRn+a91az/Qnpy+h6PyHS94WgV2TSazX5D/cuuk6wnCJatw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.11",
+ "Microsoft.Extensions.Configuration.Json": "10.0.11",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.11",
+ "Microsoft.Extensions.FileProviders.Physical": "10.0.11"
+ }
+ },
"Microsoft.Extensions.DependencyInjection": {
"type": "CentralTransitive",
"requested": "[10.0.11, )",