Skip to content

Commit 5343bb0

Browse files
committed
ToolApproval: remove specialized ctors
1 parent 422720b commit 5343bb0

6 files changed

Lines changed: 144 additions & 141 deletions

File tree

src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ToolApprovalRequestContent.cs

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5-
using System.ComponentModel;
65
using System.Text.Json.Serialization;
76
using Microsoft.Shared.Diagnostics;
87

@@ -16,49 +15,16 @@ public sealed class ToolApprovalRequestContent : InputRequestContent
1615
/// <summary>
1716
/// Initializes a new instance of the <see cref="ToolApprovalRequestContent"/> class.
1817
/// </summary>
19-
/// <param name="requestId">The unique identifier that correlates this request with its corresponding response. This may differ from the <see cref="ToolCallContent.CallId"/> of the specified <paramref name="functionCall"/>.</param>
20-
/// <param name="functionCall">The function call that requires approval before execution.</param>
21-
/// <exception cref="ArgumentNullException"><paramref name="requestId"/> is <see langword="null"/>.</exception>
22-
/// <exception cref="ArgumentException"><paramref name="requestId"/> is empty or composed entirely of whitespace.</exception>
23-
/// <exception cref="ArgumentNullException"><paramref name="functionCall"/> is <see langword="null"/>.</exception>
24-
public ToolApprovalRequestContent(string requestId, FunctionCallContent functionCall)
25-
: base(requestId)
26-
{
27-
ToolCall = Throw.IfNull(functionCall);
28-
}
29-
30-
/// <summary>
31-
/// Initializes a new instance of the <see cref="ToolApprovalRequestContent"/> class.
32-
/// </summary>
33-
/// <param name="requestId">The unique identifier that correlates this request with its corresponding response. This may differ from the <see cref="ToolCallContent.CallId"/> of the specified <paramref name="mcpServerToolCall"/>.</param>
34-
/// <param name="mcpServerToolCall">The MCP server tool call that requires approval before execution.</param>
35-
/// <exception cref="ArgumentNullException"><paramref name="requestId"/> is <see langword="null"/>.</exception>
36-
/// <exception cref="ArgumentException"><paramref name="requestId"/> is empty or composed entirely of whitespace.</exception>
37-
/// <exception cref="ArgumentNullException"><paramref name="mcpServerToolCall"/> is <see langword="null"/>.</exception>
38-
public ToolApprovalRequestContent(string requestId, McpServerToolCallContent mcpServerToolCall)
39-
: base(requestId)
40-
{
41-
ToolCall = Throw.IfNull(mcpServerToolCall);
42-
}
43-
44-
/// <summary>
45-
/// Initializes a new instance of the <see cref="ToolApprovalRequestContent"/> class for JSON deserialization.
46-
/// </summary>
4718
/// <param name="requestId">The unique identifier that correlates this request with its corresponding response.</param>
4819
/// <param name="toolCall">The tool call that requires approval before execution.</param>
20+
/// <exception cref="ArgumentNullException"><paramref name="requestId"/> is <see langword="null"/>.</exception>
21+
/// <exception cref="ArgumentException"><paramref name="requestId"/> is empty or composed entirely of whitespace.</exception>
22+
/// <exception cref="ArgumentNullException"><paramref name="toolCall"/> is <see langword="null"/>.</exception>
4923
[JsonConstructor]
50-
[EditorBrowsable(EditorBrowsableState.Never)]
5124
public ToolApprovalRequestContent(string requestId, ToolCallContent toolCall)
5225
: base(requestId)
5326
{
54-
_ = Throw.IfNull(toolCall);
55-
56-
if (toolCall is not FunctionCallContent and not McpServerToolCallContent)
57-
{
58-
Throw.ArgumentException(nameof(toolCall), $"Unsupported type '{toolCall.GetType().Name}'.");
59-
}
60-
61-
ToolCall = toolCall;
27+
ToolCall = Throw.IfNull(toolCall);
6228
}
6329

6430
/// <summary>
@@ -72,12 +38,6 @@ public ToolApprovalRequestContent(string requestId, ToolCallContent toolCall)
7238
/// <param name="approved"><see langword="true"/> if the tool call is approved; otherwise, <see langword="false"/>.</param>
7339
/// <param name="reason">An optional reason for the approval or rejection.</param>
7440
/// <returns>The <see cref="ToolApprovalResponseContent"/> correlated with this request.</returns>
75-
public ToolApprovalResponseContent CreateResponse(bool approved, string? reason = null) => ToolCall switch
76-
{
77-
FunctionCallContent fcc => new ToolApprovalResponseContent(RequestId, approved, fcc) { Reason = reason },
78-
McpServerToolCallContent mcp => new ToolApprovalResponseContent(RequestId, approved, mcp) { Reason = reason },
79-
80-
// This should never occur since the constructor enforces the allowed types.
81-
_ => throw new InvalidOperationException($"Unsupported ToolCallContent type '{ToolCall.GetType().Name}'."),
82-
};
41+
public ToolApprovalResponseContent CreateResponse(bool approved, string? reason = null) =>
42+
new ToolApprovalResponseContent(RequestId, approved, ToolCall) { Reason = reason };
8343
}

src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ToolApprovalResponseContent.cs

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5-
using System.ComponentModel;
65
using System.Text.Json.Serialization;
76
using Microsoft.Shared.Diagnostics;
87

@@ -18,53 +17,16 @@ public sealed class ToolApprovalResponseContent : InputResponseContent
1817
/// </summary>
1918
/// <param name="requestId">The unique identifier of the <see cref="ToolApprovalRequestContent"/> associated with this response.</param>
2019
/// <param name="approved"><see langword="true"/> if the tool call is approved; otherwise, <see langword="false"/>.</param>
21-
/// <param name="functionCall">The function call that was subject to approval.</param>
22-
/// <exception cref="ArgumentNullException"><paramref name="requestId"/> is <see langword="null"/>.</exception>
23-
/// <exception cref="ArgumentException"><paramref name="requestId"/> is empty or composed entirely of whitespace.</exception>
24-
/// <exception cref="ArgumentNullException"><paramref name="functionCall"/> is <see langword="null"/>.</exception>
25-
public ToolApprovalResponseContent(string requestId, bool approved, FunctionCallContent functionCall)
26-
: base(requestId)
27-
{
28-
Approved = approved;
29-
ToolCall = Throw.IfNull(functionCall);
30-
}
31-
32-
/// <summary>
33-
/// Initializes a new instance of the <see cref="ToolApprovalResponseContent"/> class.
34-
/// </summary>
35-
/// <param name="requestId">The unique identifier of the <see cref="ToolApprovalRequestContent"/> associated with this response.</param>
36-
/// <param name="approved"><see langword="true"/> if the tool call is approved; otherwise, <see langword="false"/>.</param>
37-
/// <param name="mcpServerToolCall">The MCP server tool call that was subject to approval.</param>
20+
/// <param name="toolCall">The tool call that was subject to approval.</param>
3821
/// <exception cref="ArgumentNullException"><paramref name="requestId"/> is <see langword="null"/>.</exception>
3922
/// <exception cref="ArgumentException"><paramref name="requestId"/> is empty or composed entirely of whitespace.</exception>
40-
/// <exception cref="ArgumentNullException"><paramref name="mcpServerToolCall"/> is <see langword="null"/>.</exception>
41-
public ToolApprovalResponseContent(string requestId, bool approved, McpServerToolCallContent mcpServerToolCall)
42-
: base(requestId)
43-
{
44-
Approved = approved;
45-
ToolCall = Throw.IfNull(mcpServerToolCall);
46-
}
47-
48-
/// <summary>
49-
/// Initializes a new instance of the <see cref="ToolApprovalResponseContent"/> class for JSON deserialization.
50-
/// </summary>
51-
/// <param name="requestId">The unique identifier of the <see cref="ToolApprovalRequestContent"/> associated with this response.</param>
52-
/// <param name="approved"><see langword="true"/> if the tool call is approved; otherwise, <see langword="false"/>.</param>
53-
/// <param name="toolCall">The tool call that was subject to approval.</param>
23+
/// <exception cref="ArgumentNullException"><paramref name="toolCall"/> is <see langword="null"/>.</exception>
5424
[JsonConstructor]
55-
[EditorBrowsable(EditorBrowsableState.Never)]
5625
public ToolApprovalResponseContent(string requestId, bool approved, ToolCallContent toolCall)
5726
: base(requestId)
5827
{
59-
_ = Throw.IfNull(toolCall);
60-
61-
if (toolCall is not FunctionCallContent and not McpServerToolCallContent)
62-
{
63-
Throw.ArgumentException(nameof(toolCall), $"Unsupported type '{toolCall.GetType().Name}'.");
64-
}
65-
6628
Approved = approved;
67-
ToolCall = toolCall;
29+
ToolCall = Throw.IfNull(toolCall);
6830
}
6931

7032
/// <summary>

src/Libraries/Microsoft.Extensions.AI.Abstractions/Microsoft.Extensions.AI.Abstractions.json

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3266,14 +3266,6 @@
32663266
"Type": "sealed class Microsoft.Extensions.AI.ToolApprovalRequestContent : Microsoft.Extensions.AI.InputRequestContent",
32673267
"Stage": "Stable",
32683268
"Methods": [
3269-
{
3270-
"Member": "Microsoft.Extensions.AI.ToolApprovalRequestContent.ToolApprovalRequestContent(string requestId, Microsoft.Extensions.AI.FunctionCallContent functionCall);",
3271-
"Stage": "Stable"
3272-
},
3273-
{
3274-
"Member": "Microsoft.Extensions.AI.ToolApprovalRequestContent.ToolApprovalRequestContent(string requestId, Microsoft.Extensions.AI.McpServerToolCallContent mcpServerToolCall);",
3275-
"Stage": "Stable"
3276-
},
32773269
{
32783270
"Member": "Microsoft.Extensions.AI.ToolApprovalRequestContent.ToolApprovalRequestContent(string requestId, Microsoft.Extensions.AI.ToolCallContent toolCall);",
32793271
"Stage": "Stable"
@@ -3294,14 +3286,6 @@
32943286
"Type": "sealed class Microsoft.Extensions.AI.ToolApprovalResponseContent : Microsoft.Extensions.AI.InputResponseContent",
32953287
"Stage": "Stable",
32963288
"Methods": [
3297-
{
3298-
"Member": "Microsoft.Extensions.AI.ToolApprovalResponseContent.ToolApprovalResponseContent(string requestId, bool approved, Microsoft.Extensions.AI.FunctionCallContent functionCall);",
3299-
"Stage": "Stable"
3300-
},
3301-
{
3302-
"Member": "Microsoft.Extensions.AI.ToolApprovalResponseContent.ToolApprovalResponseContent(string requestId, bool approved, Microsoft.Extensions.AI.McpServerToolCallContent mcpServerToolCall);",
3303-
"Stage": "Stable"
3304-
},
33053289
{
33063290
"Member": "Microsoft.Extensions.AI.ToolApprovalResponseContent.ToolApprovalResponseContent(string requestId, bool approved, Microsoft.Extensions.AI.ToolCallContent toolCall);",
33073291
"Stage": "Stable"

test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Contents/ToolApprovalRequestContentTests.cs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,18 @@ public class ToolApprovalRequestContentTests
1313
[Fact]
1414
public void Constructor_InvalidArguments_Throws()
1515
{
16-
FunctionCallContent functionCall = new("FCC1", "TestFunction");
17-
McpServerToolCallContent mcpCall = new("MCC1", "TestTool", "TestServer");
18-
19-
// FunctionCallContent overload
20-
Assert.Throws<ArgumentNullException>("requestId", () => new ToolApprovalRequestContent(null!, functionCall));
21-
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalRequestContent("", functionCall));
22-
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalRequestContent("\r\t\n ", functionCall));
23-
Assert.Throws<ArgumentNullException>("functionCall", () => new ToolApprovalRequestContent("id", (FunctionCallContent)null!));
24-
25-
// McpServerToolCallContent overload
26-
Assert.Throws<ArgumentNullException>("requestId", () => new ToolApprovalRequestContent(null!, mcpCall));
27-
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalRequestContent("", mcpCall));
28-
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalRequestContent("\r\t\n ", mcpCall));
29-
Assert.Throws<ArgumentNullException>("mcpServerToolCall", () => new ToolApprovalRequestContent("id", (McpServerToolCallContent)null!));
30-
31-
// ToolCallContent (JsonConstructor) overload
32-
Assert.Throws<ArgumentNullException>("toolCall", () => new ToolApprovalRequestContent("id", (ToolCallContent)null!));
33-
Assert.Throws<ArgumentException>("toolCall", () => new ToolApprovalRequestContent("id", new CodeInterpreterToolCallContent("call1")));
34-
Assert.Throws<ArgumentException>("toolCall", () => new ToolApprovalRequestContent("id", new ImageGenerationToolCallContent("call1")));
16+
Assert.Throws<ArgumentNullException>("requestId", () => new ToolApprovalRequestContent(null!, new FunctionCallContent("FCC1", "TestFunction")));
17+
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalRequestContent("", new FunctionCallContent("FCC1", "TestFunction")));
18+
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalRequestContent("\r\t\n ", new FunctionCallContent("FCC1", "TestFunction")));
19+
Assert.Throws<ArgumentNullException>("toolCall", () => new ToolApprovalRequestContent("id", null!));
3520
}
3621

3722
public static TheoryData<ToolCallContent> ToolCallContentInstances => new()
3823
{
3924
new FunctionCallContent("FCC1", "TestFunction", new Dictionary<string, object?> { { "param1", 123 } }),
4025
new McpServerToolCallContent("MCC1", "TestTool", "TestServer") { Arguments = new Dictionary<string, object?> { { "arg1", "value1" } } },
26+
new CodeInterpreterToolCallContent("CI1") { Inputs = [new DataContent("print('hello')"u8.ToArray(), "text/x-python")] },
27+
new ImageGenerationToolCallContent("IG1"),
4128
};
4229

4330
[Theory]

test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Contents/ToolApprovalResponseContentTests.cs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,18 @@ public class ToolApprovalResponseContentTests
1313
[Fact]
1414
public void Constructor_InvalidArguments_Throws()
1515
{
16-
FunctionCallContent functionCall = new("FCC1", "TestFunction");
17-
McpServerToolCallContent mcpCall = new("MCC1", "TestTool", "TestServer");
18-
19-
// FunctionCallContent overload
20-
Assert.Throws<ArgumentNullException>("requestId", () => new ToolApprovalResponseContent(null!, true, functionCall));
21-
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalResponseContent("", true, functionCall));
22-
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalResponseContent("\r\t\n ", true, functionCall));
23-
Assert.Throws<ArgumentNullException>("functionCall", () => new ToolApprovalResponseContent("id", true, (FunctionCallContent)null!));
24-
25-
// McpServerToolCallContent overload
26-
Assert.Throws<ArgumentNullException>("requestId", () => new ToolApprovalResponseContent(null!, true, mcpCall));
27-
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalResponseContent("", true, mcpCall));
28-
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalResponseContent("\r\t\n ", true, mcpCall));
29-
Assert.Throws<ArgumentNullException>("mcpServerToolCall", () => new ToolApprovalResponseContent("id", true, (McpServerToolCallContent)null!));
30-
31-
// ToolCallContent (JsonConstructor) overload
32-
Assert.Throws<ArgumentNullException>("toolCall", () => new ToolApprovalResponseContent("id", true, (ToolCallContent)null!));
33-
Assert.Throws<ArgumentException>("toolCall", () => new ToolApprovalResponseContent("id", true, new CodeInterpreterToolCallContent("call1")));
34-
Assert.Throws<ArgumentException>("toolCall", () => new ToolApprovalResponseContent("id", true, new ImageGenerationToolCallContent("call1")));
16+
Assert.Throws<ArgumentNullException>("requestId", () => new ToolApprovalResponseContent(null!, true, new FunctionCallContent("FCC1", "TestFunction")));
17+
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalResponseContent("", true, new FunctionCallContent("FCC1", "TestFunction")));
18+
Assert.Throws<ArgumentException>("requestId", () => new ToolApprovalResponseContent("\r\t\n ", true, new FunctionCallContent("FCC1", "TestFunction")));
19+
Assert.Throws<ArgumentNullException>("toolCall", () => new ToolApprovalResponseContent("id", true, null!));
3520
}
3621

3722
public static TheoryData<ToolCallContent> ToolCallContentInstances => new()
3823
{
3924
new FunctionCallContent("FCC1", "TestFunction", new Dictionary<string, object?> { { "param1", 123 } }),
4025
new McpServerToolCallContent("MCC1", "TestTool", "TestServer") { Arguments = new Dictionary<string, object?> { { "arg1", "value1" } } },
26+
new CodeInterpreterToolCallContent("CI1") { Inputs = [new DataContent("print('hello')"u8.ToArray(), "text/x-python")] },
27+
new ImageGenerationToolCallContent("IG1"),
4128
};
4229

4330
[Theory]

0 commit comments

Comments
 (0)