Add net10.0 assets and run some fixers (#875)
This commit is contained in:
parent
e7b403b820
commit
bfc0980ef5
46 changed files with 168 additions and 194 deletions
|
|
@ -1,9 +1,9 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
<System9Version>9.0.5</System9Version>
|
||||
<System10Version>10.0.0-preview.4.25258.110</System10Version>
|
||||
<MicrosoftExtensionsAIVersion>9.9.1</MicrosoftExtensionsAIVersion>
|
||||
<System9Version>9.0.10</System9Version>
|
||||
<System10Version>10.0.0-rc.2.25502.107</System10Version>
|
||||
<MicrosoftExtensionsAIVersion>9.10.0</MicrosoftExtensionsAIVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Product dependencies netstandard -->
|
||||
|
|
@ -28,19 +28,17 @@
|
|||
<!-- Product dependencies .NET 9 -->
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(System9Version)" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.9.0" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.14.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(System9Version)" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(System9Version)" />
|
||||
<PackageVersion Include="System.IO.Pipelines" Version="$(System9Version)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Product dependencies .NET 10 -->
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(System10Version)" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.9.0" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.14.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(System10Version)" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(System10Version)" />
|
||||
<PackageVersion Include="System.IO.Pipelines" Version="$(System10Version)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Product dependencies shared -->
|
||||
|
|
@ -56,19 +54,19 @@
|
|||
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
|
||||
|
||||
<!-- Testing dependencies -->
|
||||
<PackageVersion Include="Anthropic.SDK" Version="5.5.1" />
|
||||
<PackageVersion Include="Anthropic.SDK" Version="5.6.0" />
|
||||
<PackageVersion Include="coverlet.collector" Version="6.0.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageVersion>
|
||||
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="9.9.1-preview.1.25474.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="9.10.0-preview.1.25513.3" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="$(System9Version)" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="$(System9Version)" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="$(System9Version)" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="$(System9Version)" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options" Version="$(System9Version)" />
|
||||
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="9.5.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="9.10.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageVersion Include="Moq" Version="4.20.72" />
|
||||
<PackageVersion Include="OpenTelemetry" Version="1.12.0" />
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public sealed class InteractiveTools
|
|||
string? playerName = nameResponse.Content?["Name"].GetString();
|
||||
|
||||
// Generate a random number between 1 and 10
|
||||
Random random = new Random();
|
||||
Random random = new();
|
||||
int targetNumber = random.Next(1, 11); // 1 to 10 inclusive
|
||||
int attempts = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ builder.Services.AddMcpServer()
|
|||
{
|
||||
mcpOptions.Capabilities = new();
|
||||
mcpOptions.Capabilities.Tools = new();
|
||||
var toolCollection = mcpOptions.ToolCollection = new();
|
||||
var toolCollection = mcpOptions.ToolCollection = [];
|
||||
|
||||
foreach (var tool in tools)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ internal class CancellableStreamReader : TextReader
|
|||
CheckAsyncTaskInProgress();
|
||||
|
||||
// Call ReadBuffer, then pull data out of charBuffer.
|
||||
StringBuilder sb = new StringBuilder(_charLen - _charPos);
|
||||
StringBuilder sb = new(_charLen - _charPos);
|
||||
do
|
||||
{
|
||||
sb.Append(_charBuffer, _charPos, _charLen - _charPos);
|
||||
|
|
@ -953,7 +953,7 @@ internal class CancellableStreamReader : TextReader
|
|||
private async Task<string> ReadToEndAsyncInternal(CancellationToken cancellationToken)
|
||||
{
|
||||
// Call ReadBuffer, then pull data out of charBuffer.
|
||||
StringBuilder sb = new StringBuilder(_charLen - _charPos);
|
||||
StringBuilder sb = new(_charLen - _charPos);
|
||||
do
|
||||
{
|
||||
int tmpCharPos = _charPos;
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ public class McpAuthenticationOptions : AuthenticationSchemeOptions
|
|||
/// Gets or sets the events used to handle authentication events.
|
||||
/// </summary>
|
||||
public new McpAuthenticationEvents Events
|
||||
{
|
||||
get { return (McpAuthenticationEvents)base.Events!; }
|
||||
set { base.Events = value; }
|
||||
{
|
||||
get => (McpAuthenticationEvents)base.Events!;
|
||||
set => base.Events = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ internal sealed class AuthorizationFilterSetup(IAuthorizationPolicyProvider? pol
|
|||
});
|
||||
}
|
||||
|
||||
private void CheckListToolsFilter(McpServerOptions options)
|
||||
private static void CheckListToolsFilter(McpServerOptions options)
|
||||
{
|
||||
options.Filters.ListToolsFilters.Add(next => async (context, cancellationToken) =>
|
||||
{
|
||||
|
|
@ -87,7 +87,7 @@ internal sealed class AuthorizationFilterSetup(IAuthorizationPolicyProvider? pol
|
|||
});
|
||||
}
|
||||
|
||||
private void CheckCallToolFilter(McpServerOptions options)
|
||||
private static void CheckCallToolFilter(McpServerOptions options)
|
||||
{
|
||||
options.Filters.CallToolFilters.Add(next => async (context, cancellationToken) =>
|
||||
{
|
||||
|
|
@ -115,7 +115,7 @@ internal sealed class AuthorizationFilterSetup(IAuthorizationPolicyProvider? pol
|
|||
});
|
||||
}
|
||||
|
||||
private void CheckListResourcesFilter(McpServerOptions options)
|
||||
private static void CheckListResourcesFilter(McpServerOptions options)
|
||||
{
|
||||
options.Filters.ListResourcesFilters.Add(next => async (context, cancellationToken) =>
|
||||
{
|
||||
|
|
@ -145,7 +145,7 @@ internal sealed class AuthorizationFilterSetup(IAuthorizationPolicyProvider? pol
|
|||
});
|
||||
}
|
||||
|
||||
private void CheckListResourceTemplatesFilter(McpServerOptions options)
|
||||
private static void CheckListResourceTemplatesFilter(McpServerOptions options)
|
||||
{
|
||||
options.Filters.ListResourceTemplatesFilters.Add(next => async (context, cancellationToken) =>
|
||||
{
|
||||
|
|
@ -177,7 +177,7 @@ internal sealed class AuthorizationFilterSetup(IAuthorizationPolicyProvider? pol
|
|||
});
|
||||
}
|
||||
|
||||
private void CheckReadResourceFilter(McpServerOptions options)
|
||||
private static void CheckReadResourceFilter(McpServerOptions options)
|
||||
{
|
||||
options.Filters.ReadResourceFilters.Add(next => async (context, cancellationToken) =>
|
||||
{
|
||||
|
|
@ -205,7 +205,7 @@ internal sealed class AuthorizationFilterSetup(IAuthorizationPolicyProvider? pol
|
|||
});
|
||||
}
|
||||
|
||||
private void CheckListPromptsFilter(McpServerOptions options)
|
||||
private static void CheckListPromptsFilter(McpServerOptions options)
|
||||
{
|
||||
options.Filters.ListPromptsFilters.Add(next => async (context, cancellationToken) =>
|
||||
{
|
||||
|
|
@ -237,7 +237,7 @@ internal sealed class AuthorizationFilterSetup(IAuthorizationPolicyProvider? pol
|
|||
});
|
||||
}
|
||||
|
||||
private void CheckGetPromptFilter(McpServerOptions options)
|
||||
private static void CheckGetPromptFilter(McpServerOptions options)
|
||||
{
|
||||
options.Filters.GetPromptFilters.Add(next => async (context, cancellationToken) =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net9.0;net8.0</TargetFrameworks>
|
||||
<TargetFrameworks>net10.0;net9.0;net8.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
|
|
|
|||
|
|
@ -128,10 +128,7 @@ public static class AIContentExtensions
|
|||
_ => null,
|
||||
};
|
||||
|
||||
if (ac is not null)
|
||||
{
|
||||
ac.RawRepresentation = content;
|
||||
}
|
||||
ac?.RawRepresentation = content;
|
||||
|
||||
return ac;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
#if NET9_0_OR_GREATER
|
||||
using System.Buffers.Text;
|
||||
#endif
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Security.Cryptography;
|
||||
|
|
@ -238,14 +241,17 @@ internal sealed partial class ClientOAuthProvider
|
|||
LogOAuthAuthorizationCompleted();
|
||||
}
|
||||
|
||||
private static readonly string[] s_wellKnownPaths = [".well-known/openid-configuration", ".well-known/oauth-authorization-server"];
|
||||
|
||||
private async Task<AuthorizationServerMetadata> GetAuthServerMetadataAsync(Uri authServerUri, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!authServerUri.OriginalString.EndsWith("/"))
|
||||
if (authServerUri.OriginalString.Length == 0 ||
|
||||
authServerUri.OriginalString[authServerUri.OriginalString.Length - 1] != '/')
|
||||
{
|
||||
authServerUri = new Uri(authServerUri.OriginalString + "/");
|
||||
authServerUri = new Uri($"{authServerUri.OriginalString}/");
|
||||
}
|
||||
|
||||
foreach (var path in new[] { ".well-known/openid-configuration", ".well-known/oauth-authorization-server" })
|
||||
foreach (var path in s_wellKnownPaths)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -540,11 +546,7 @@ internal sealed partial class ClientOAuthProvider
|
|||
Port = -1 // Always remove port
|
||||
};
|
||||
|
||||
if (builder.Path == "/")
|
||||
{
|
||||
builder.Path = string.Empty;
|
||||
}
|
||||
else if (builder.Path.Length > 1 && builder.Path.EndsWith("/"))
|
||||
if (builder.Path.Length > 0 && builder.Path[builder.Path.Length - 1] == '/')
|
||||
{
|
||||
builder.Path = builder.Path.TrimEnd('/');
|
||||
}
|
||||
|
|
@ -633,18 +635,18 @@ internal sealed partial class ClientOAuthProvider
|
|||
continue;
|
||||
}
|
||||
|
||||
string key = trimmedPart.Substring(0, equalsIndex).Trim();
|
||||
ReadOnlySpan<char> key = trimmedPart.AsSpan().Slice(0, equalsIndex).Trim();
|
||||
|
||||
if (string.Equals(key, parameterName, StringComparison.OrdinalIgnoreCase))
|
||||
if (key.Equals(parameterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string value = trimmedPart.Substring(equalsIndex + 1).Trim();
|
||||
ReadOnlySpan<char> value = trimmedPart.AsSpan(equalsIndex + 1).Trim();
|
||||
|
||||
if (value.StartsWith("\"") && value.EndsWith("\""))
|
||||
if (value.Length > 0 && value[0] == '"' && value[value.Length - 1] == '"')
|
||||
{
|
||||
value = value.Substring(1, value.Length - 2);
|
||||
value = value.Slice(1, value.Length - 2);
|
||||
}
|
||||
|
||||
return value;
|
||||
return value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -664,12 +666,18 @@ internal sealed partial class ClientOAuthProvider
|
|||
|
||||
private static string GenerateCodeChallenge(string codeVerifier)
|
||||
{
|
||||
#if NET9_0_OR_GREATER
|
||||
Span<byte> hash = stackalloc byte[SHA256.HashSizeInBytes];
|
||||
SHA256.HashData(Encoding.UTF8.GetBytes(codeVerifier), hash);
|
||||
return Base64Url.EncodeToString(hash);
|
||||
#else
|
||||
using var sha256 = SHA256.Create();
|
||||
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
|
||||
return Convert.ToBase64String(challengeBytes)
|
||||
.TrimEnd('=')
|
||||
.Replace('+', '-')
|
||||
.Replace('/', '_');
|
||||
#endif
|
||||
}
|
||||
|
||||
private string GetClientIdOrThrow() => _clientId ?? throw new InvalidOperationException("Client ID is not available. This may indicate an issue with dynamic client registration.");
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ namespace ModelContextProtocol.Client;
|
|||
/// </remarks>
|
||||
public sealed class McpClientOptions
|
||||
{
|
||||
private McpClientHandlers? _handlers;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets information about this client implementation, including its name and version.
|
||||
/// </summary>
|
||||
|
|
@ -71,11 +69,11 @@ public sealed class McpClientOptions
|
|||
/// </summary>
|
||||
public McpClientHandlers Handlers
|
||||
{
|
||||
get => _handlers ??= new();
|
||||
get => field ??= new();
|
||||
set
|
||||
{
|
||||
Throw.IfNull(value);
|
||||
_handlers = value;
|
||||
field = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,21 +5,15 @@ using System.Diagnostics;
|
|||
namespace ModelContextProtocol.Client;
|
||||
|
||||
/// <summary>Provides the client side of a stdio-based session transport.</summary>
|
||||
internal sealed class StdioClientSessionTransport : StreamClientSessionTransport
|
||||
internal sealed class StdioClientSessionTransport(
|
||||
StdioClientTransportOptions options, Process process, string endpointName, Queue<string> stderrRollingLog, ILoggerFactory? loggerFactory) :
|
||||
StreamClientSessionTransport(process.StandardInput.BaseStream, process.StandardOutput.BaseStream, encoding: null, endpointName, loggerFactory)
|
||||
{
|
||||
private readonly StdioClientTransportOptions _options;
|
||||
private readonly Process _process;
|
||||
private readonly Queue<string> _stderrRollingLog;
|
||||
private readonly StdioClientTransportOptions _options = options;
|
||||
private readonly Process _process = process;
|
||||
private readonly Queue<string> _stderrRollingLog = stderrRollingLog;
|
||||
private int _cleanedUp = 0;
|
||||
|
||||
public StdioClientSessionTransport(StdioClientTransportOptions options, Process process, string endpointName, Queue<string> stderrRollingLog, ILoggerFactory? loggerFactory)
|
||||
: base(process.StandardInput.BaseStream, process.StandardOutput.BaseStream, encoding: null, endpointName, loggerFactory)
|
||||
{
|
||||
_process = process;
|
||||
_options = options;
|
||||
_stderrRollingLog = stderrRollingLog;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task SendMessageAsync(JsonRpcMessage message, CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
|
@ -56,7 +50,7 @@ internal sealed class StdioClientSessionTransport : StreamClientSessionTransport
|
|||
// Now terminate the server process.
|
||||
try
|
||||
{
|
||||
StdioClientTransport.DisposeProcess(_process, processRunning: true, _options.ShutdownTimeout, Name);
|
||||
StdioClientTransport.DisposeProcess(_process, processRunning: true, shutdownTimeout: _options.ShutdownTimeout);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ public sealed partial class StdioClientTransport : IClientTransport
|
|||
|
||||
_options = options;
|
||||
_loggerFactory = loggerFactory;
|
||||
Name = options.Name ?? $"stdio-{Regex.Replace(Path.GetFileName(options.Command), @"[\s\.]+", "-")}";
|
||||
Name = options.Name ?? $"stdio-{WhitespaceAndPeriods().Replace(Path.GetFileName(options.Command), "-")}";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -189,7 +189,7 @@ public sealed partial class StdioClientTransport : IClientTransport
|
|||
|
||||
try
|
||||
{
|
||||
DisposeProcess(process, processStarted, _options.ShutdownTimeout, endpointName);
|
||||
DisposeProcess(process, processStarted, _options.ShutdownTimeout);
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
|
|
@ -201,7 +201,7 @@ public sealed partial class StdioClientTransport : IClientTransport
|
|||
}
|
||||
|
||||
internal static void DisposeProcess(
|
||||
Process? process, bool processRunning, TimeSpan shutdownTimeout, string endpointName)
|
||||
Process? process, bool processRunning, TimeSpan shutdownTimeout)
|
||||
{
|
||||
if (process is not null)
|
||||
{
|
||||
|
|
@ -279,4 +279,12 @@ public sealed partial class StdioClientTransport : IClientTransport
|
|||
|
||||
[LoggerMessage(Level = LogLevel.Warning, Message = "{EndpointName} shutdown failed.")]
|
||||
private static partial void LogTransportShutdownFailed(ILogger logger, string endpointName, Exception exception);
|
||||
|
||||
#if NET
|
||||
[GeneratedRegex(@"[\s\.]+")]
|
||||
private static partial Regex WhitespaceAndPeriods();
|
||||
#else
|
||||
private static Regex WhitespaceAndPeriods() => s_whitespaceAndPeriods;
|
||||
private static readonly Regex s_whitespaceAndPeriods = new(@"[\s\.]+", RegexOptions.Compiled);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,9 +93,9 @@ internal static class Diagnostics
|
|||
{
|
||||
if (jsonObject["_meta"] is not JsonObject meta)
|
||||
{
|
||||
meta = new JsonObject();
|
||||
jsonObject["_meta"] = meta;
|
||||
jsonObject["_meta"] = meta = [];
|
||||
}
|
||||
|
||||
meta[key] = value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -405,7 +405,7 @@ internal sealed partial class McpSessionHandler : IAsyncDisposable
|
|||
|
||||
long? startingTimestamp = durationMetric.Enabled ? Stopwatch.GetTimestamp() : null;
|
||||
using Activity? activity = Diagnostics.ShouldInstrumentMessage(request) ?
|
||||
Diagnostics.ActivitySource.StartActivity(CreateActivityName(method), ActivityKind.Client) :
|
||||
Diagnostics.ActivitySource.StartActivity(McpSessionHandler.CreateActivityName(method), ActivityKind.Client) :
|
||||
null;
|
||||
|
||||
// Set request ID
|
||||
|
|
@ -501,7 +501,7 @@ internal sealed partial class McpSessionHandler : IAsyncDisposable
|
|||
|
||||
long? startingTimestamp = durationMetric.Enabled ? Stopwatch.GetTimestamp() : null;
|
||||
using Activity? activity = Diagnostics.ShouldInstrumentMessage(message) ?
|
||||
Diagnostics.ActivitySource.StartActivity(CreateActivityName(method), ActivityKind.Client) :
|
||||
Diagnostics.ActivitySource.StartActivity(McpSessionHandler.CreateActivityName(method), ActivityKind.Client) :
|
||||
null;
|
||||
|
||||
TagList tags = default;
|
||||
|
|
@ -567,7 +567,7 @@ internal sealed partial class McpSessionHandler : IAsyncDisposable
|
|||
}
|
||||
}
|
||||
|
||||
private string CreateActivityName(string method) => method;
|
||||
private static string CreateActivityName(string method) => method;
|
||||
|
||||
private static string GetMethodName(JsonRpcMessage message) =>
|
||||
message switch
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net9.0;net8.0;netstandard2.0</TargetFrameworks>
|
||||
<TargetFrameworks>net10.0;net9.0;net8.0;netstandard2.0</TargetFrameworks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>ModelContextProtocol.Core</PackageId>
|
||||
|
|
@ -27,16 +27,20 @@
|
|||
<PackageReference Include="System.Threading.Channels" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Dependencies only needed by netstandard2.0 or net8.0 -->
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'net8.0'">
|
||||
<!-- Dependencies only needed by pre-net9.0 -->
|
||||
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net9.0'))">
|
||||
<PackageReference Include="System.IO.Pipelines" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Dependencies only needed pre-net10.0 -->
|
||||
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net10.0'))">
|
||||
<PackageReference Include="System.Net.ServerSentEvents" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Dependencies needed by all -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||
<PackageReference Include="System.Net.ServerSentEvents" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -240,14 +240,8 @@ internal sealed class NotificationHandlers
|
|||
// to point past this one. Importantly, we do not modify this node's Next or Prev.
|
||||
// We want to ensure that an enumeration through all of the registrations can still
|
||||
// progress through this one.
|
||||
if (Prev is not null)
|
||||
{
|
||||
Prev.Next = Next;
|
||||
}
|
||||
if (Next is not null)
|
||||
{
|
||||
Next.Prev = Prev;
|
||||
}
|
||||
Prev?.Next = Next;
|
||||
Next?.Prev = Prev;
|
||||
|
||||
// Decrement the ref count. In the common case, there's no in-flight invocation for
|
||||
// this handler. However, in the uncommon case that there is, we need to wait for
|
||||
|
|
|
|||
|
|
@ -11,15 +11,12 @@ namespace ModelContextProtocol.Protocol;
|
|||
[JsonConverter(typeof(Converter))]
|
||||
public readonly struct ProgressToken : IEquatable<ProgressToken>
|
||||
{
|
||||
/// <summary>The token, either a string or a boxed long or null.</summary>
|
||||
private readonly object? _token;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="ProgressToken"/> with a specified value.</summary>
|
||||
/// <param name="value">The required ID value.</param>
|
||||
public ProgressToken(string value)
|
||||
{
|
||||
Throw.IfNull(value);
|
||||
_token = value;
|
||||
Token = value;
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="ProgressToken"/> with a specified value.</summary>
|
||||
|
|
@ -27,27 +24,27 @@ public readonly struct ProgressToken : IEquatable<ProgressToken>
|
|||
public ProgressToken(long value)
|
||||
{
|
||||
// Box the long. Progress tokens are almost always strings in practice, so this should be rare.
|
||||
_token = value;
|
||||
Token = value;
|
||||
}
|
||||
|
||||
/// <summary>Gets the underlying object for this token.</summary>
|
||||
/// <remarks>This will either be a <see cref="string"/>, a boxed <see cref="long"/>, or <see langword="null"/>.</remarks>
|
||||
public object? Token => _token;
|
||||
public object? Token { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string? ToString() =>
|
||||
_token is string stringValue ? stringValue :
|
||||
_token is long longValue ? longValue.ToString(CultureInfo.InvariantCulture) :
|
||||
Token is string stringValue ? stringValue :
|
||||
Token is long longValue ? longValue.ToString(CultureInfo.InvariantCulture) :
|
||||
null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(ProgressToken other) => Equals(_token, other._token);
|
||||
public bool Equals(ProgressToken other) => Equals(Token, other.Token);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object? obj) => obj is ProgressToken other && Equals(other);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode() => _token?.GetHashCode() ?? 0;
|
||||
public override int GetHashCode() => Token?.GetHashCode() ?? 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public static bool operator ==(ProgressToken left, ProgressToken right) => left.Equals(right);
|
||||
|
|
@ -77,7 +74,7 @@ public readonly struct ProgressToken : IEquatable<ProgressToken>
|
|||
{
|
||||
Throw.IfNull(writer);
|
||||
|
||||
switch (value._token)
|
||||
switch (value.Token)
|
||||
{
|
||||
case string str:
|
||||
writer.WriteStringValue(str);
|
||||
|
|
|
|||
|
|
@ -11,15 +11,12 @@ namespace ModelContextProtocol.Protocol;
|
|||
[JsonConverter(typeof(Converter))]
|
||||
public readonly struct RequestId : IEquatable<RequestId>
|
||||
{
|
||||
/// <summary>The id, either a string or a boxed long or null.</summary>
|
||||
private readonly object? _id;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="RequestId"/> with a specified value.</summary>
|
||||
/// <param name="value">The required ID value.</param>
|
||||
public RequestId(string value)
|
||||
{
|
||||
Throw.IfNull(value);
|
||||
_id = value;
|
||||
Id = value;
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="RequestId"/> with a specified value.</summary>
|
||||
|
|
@ -27,27 +24,27 @@ public readonly struct RequestId : IEquatable<RequestId>
|
|||
public RequestId(long value)
|
||||
{
|
||||
// Box the long. Request IDs are almost always strings in practice, so this should be rare.
|
||||
_id = value;
|
||||
Id = value;
|
||||
}
|
||||
|
||||
/// <summary>Gets the underlying object for this id.</summary>
|
||||
/// <remarks>This will either be a <see cref="string"/>, a boxed <see cref="long"/>, or <see langword="null"/>.</remarks>
|
||||
public object? Id => _id;
|
||||
public object? Id { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString() =>
|
||||
_id is string stringValue ? stringValue :
|
||||
_id is long longValue ? longValue.ToString(CultureInfo.InvariantCulture) :
|
||||
Id is string stringValue ? stringValue :
|
||||
Id is long longValue ? longValue.ToString(CultureInfo.InvariantCulture) :
|
||||
string.Empty;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(RequestId other) => Equals(_id, other._id);
|
||||
public bool Equals(RequestId other) => Equals(Id, other.Id);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object? obj) => obj is RequestId other && Equals(other);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode() => _id?.GetHashCode() ?? 0;
|
||||
public override int GetHashCode() => Id?.GetHashCode() ?? 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public static bool operator ==(RequestId left, RequestId right) => left.Equals(right);
|
||||
|
|
@ -77,7 +74,7 @@ public readonly struct RequestId : IEquatable<RequestId>
|
|||
{
|
||||
Throw.IfNull(writer);
|
||||
|
||||
switch (value._id)
|
||||
switch (value.Id)
|
||||
{
|
||||
case string str:
|
||||
writer.WriteStringValue(str);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ internal sealed class AIFunctionMcpServerPrompt : McpServerPrompt
|
|||
return Create(
|
||||
AIFunctionFactory.Create(method, args =>
|
||||
{
|
||||
Debug.Assert(args.Services is RequestServiceProvider<GetPromptRequestParams>, $"The service provider should be a {nameof(RequestServiceProvider<GetPromptRequestParams>)} for this method to work correctly.");
|
||||
Debug.Assert(args.Services is RequestServiceProvider<GetPromptRequestParams>, $"The service provider should be a {nameof(RequestServiceProvider<>)} for this method to work correctly.");
|
||||
return createTargetFunc(((RequestServiceProvider<GetPromptRequestParams>)args.Services!).Request);
|
||||
}, CreateAIFunctionFactoryOptions(method, options)),
|
||||
options);
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ internal sealed class AIFunctionMcpServerResource : McpServerResource
|
|||
return Create(
|
||||
AIFunctionFactory.Create(method, args =>
|
||||
{
|
||||
Debug.Assert(args.Services is RequestServiceProvider<ReadResourceRequestParams>, $"The service provider should be a {nameof(RequestServiceProvider<ReadResourceRequestParams>)} for this method to work correctly.");
|
||||
Debug.Assert(args.Services is RequestServiceProvider<ReadResourceRequestParams>, $"The service provider should be a {nameof(RequestServiceProvider<>)} for this method to work correctly.");
|
||||
return createTargetFunc(((RequestServiceProvider<ReadResourceRequestParams>)args.Services!).Request);
|
||||
}, CreateAIFunctionFactoryOptions(method, options)),
|
||||
options);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue