Skip to content

Commit e30c4c0

Browse files
authored
Expose ctors for setting AdditionalProperties on Hosted tools (#7120)
* Expose ctors for setting AdditionalProperties on Hosted tools * Address feedback
1 parent 32f5695 commit e30c4c0

File tree

18 files changed

+429
-46
lines changed

18 files changed

+429
-46
lines changed

src/Libraries/Microsoft.Extensions.AI.Abstractions/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Microsoft.Extensions.AI.Abstractions Release History
22

3+
## 10.1.1 (NOT YET RELEASED)
4+
5+
- Added `InputCachedTokenCount` and `ReasoningTokenCount` to `UsageDetails`.
6+
- Added constructors to `HostedCodeInterpreterTool`, `HostedFileSearchTool`, `HostedImageGeneratorTool`, `HostedMcpServerTool`,
7+
and `HostedWebSearchTool` that accept a dictionary for `AdditionalProperties`.
8+
39
## 10.1.0
410

511
- Fixed package references for net10.0 asset.

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,9 +1918,17 @@
19181918
{
19191919
"Member": "Microsoft.Extensions.AI.HostedCodeInterpreterTool.HostedCodeInterpreterTool();",
19201920
"Stage": "Stable"
1921+
},
1922+
{
1923+
"Member": "Microsoft.Extensions.AI.HostedCodeInterpreterTool.HostedCodeInterpreterTool(System.Collections.Generic.IReadOnlyDictionary<string, object?>? additionalProperties);",
1924+
"Stage": "Stable"
19211925
}
19221926
],
19231927
"Properties": [
1928+
{
1929+
"Member": "override System.Collections.Generic.IReadOnlyDictionary<string, object?> Microsoft.Extensions.AI.HostedCodeInterpreterTool.AdditionalProperties { get; }",
1930+
"Stage": "Stable"
1931+
},
19241932
{
19251933
"Member": "System.Collections.Generic.IList<Microsoft.Extensions.AI.AIContent>? Microsoft.Extensions.AI.HostedCodeInterpreterTool.Inputs { get; set; }",
19261934
"Stage": "Stable"
@@ -1938,9 +1946,17 @@
19381946
{
19391947
"Member": "Microsoft.Extensions.AI.HostedFileSearchTool.HostedFileSearchTool();",
19401948
"Stage": "Stable"
1949+
},
1950+
{
1951+
"Member": "Microsoft.Extensions.AI.HostedFileSearchTool.HostedFileSearchTool(System.Collections.Generic.IReadOnlyDictionary<string, object?>? additionalProperties);",
1952+
"Stage": "Stable"
19411953
}
19421954
],
19431955
"Properties": [
1956+
{
1957+
"Member": "override System.Collections.Generic.IReadOnlyDictionary<string, object?> Microsoft.Extensions.AI.HostedFileSearchTool.AdditionalProperties { get; }",
1958+
"Stage": "Stable"
1959+
},
19441960
{
19451961
"Member": "System.Collections.Generic.IList<Microsoft.Extensions.AI.AIContent>? Microsoft.Extensions.AI.HostedFileSearchTool.Inputs { get; set; }",
19461962
"Stage": "Stable"
@@ -1962,9 +1978,17 @@
19621978
{
19631979
"Member": "Microsoft.Extensions.AI.HostedWebSearchTool.HostedWebSearchTool();",
19641980
"Stage": "Stable"
1981+
},
1982+
{
1983+
"Member": "Microsoft.Extensions.AI.HostedWebSearchTool.HostedWebSearchTool(System.Collections.Generic.IReadOnlyDictionary<string, object?>? additionalProperties);",
1984+
"Stage": "Stable"
19651985
}
19661986
],
19671987
"Properties": [
1988+
{
1989+
"Member": "override System.Collections.Generic.IReadOnlyDictionary<string, object?> Microsoft.Extensions.AI.HostedWebSearchTool.AdditionalProperties { get; }",
1990+
"Stage": "Stable"
1991+
},
19681992
{
19691993
"Member": "override string Microsoft.Extensions.AI.HostedWebSearchTool.Name { get; }",
19701994
"Stage": "Stable"

src/Libraries/Microsoft.Extensions.AI.Abstractions/Tools/HostedCodeInterpreterTool.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,27 @@ namespace Microsoft.Extensions.AI;
1212
/// </remarks>
1313
public class HostedCodeInterpreterTool : AITool
1414
{
15+
/// <summary>Any additional properties associated with the tool.</summary>
16+
private IReadOnlyDictionary<string, object?>? _additionalProperties;
17+
1518
/// <summary>Initializes a new instance of the <see cref="HostedCodeInterpreterTool"/> class.</summary>
1619
public HostedCodeInterpreterTool()
1720
{
1821
}
1922

23+
/// <summary>Initializes a new instance of the <see cref="HostedCodeInterpreterTool"/> class.</summary>
24+
/// <param name="additionalProperties">Any additional properties associated with the tool.</param>
25+
public HostedCodeInterpreterTool(IReadOnlyDictionary<string, object?>? additionalProperties)
26+
{
27+
_additionalProperties = additionalProperties;
28+
}
29+
2030
/// <inheritdoc />
2131
public override string Name => "code_interpreter";
2232

33+
/// <inheritdoc />
34+
public override IReadOnlyDictionary<string, object?> AdditionalProperties => _additionalProperties ?? base.AdditionalProperties;
35+
2336
/// <summary>Gets or sets a collection of <see cref="AIContent"/> to be used as input to the code interpreter tool.</summary>
2437
/// <remarks>
2538
/// Services support different varied kinds of inputs. Most support the IDs of files that are hosted by the service,

src/Libraries/Microsoft.Extensions.AI.Abstractions/Tools/HostedFileSearchTool.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,27 @@ namespace Microsoft.Extensions.AI;
1212
/// </remarks>
1313
public class HostedFileSearchTool : AITool
1414
{
15+
/// <summary>Any additional properties associated with the tool.</summary>
16+
private IReadOnlyDictionary<string, object?>? _additionalProperties;
17+
1518
/// <summary>Initializes a new instance of the <see cref="HostedFileSearchTool"/> class.</summary>
1619
public HostedFileSearchTool()
1720
{
1821
}
1922

23+
/// <summary>Initializes a new instance of the <see cref="HostedFileSearchTool"/> class.</summary>
24+
/// <param name="additionalProperties">Any additional properties associated with the tool.</param>
25+
public HostedFileSearchTool(IReadOnlyDictionary<string, object?>? additionalProperties)
26+
{
27+
_additionalProperties = additionalProperties;
28+
}
29+
2030
/// <inheritdoc />
2131
public override string Name => "file_search";
2232

33+
/// <inheritdoc />
34+
public override IReadOnlyDictionary<string, object?> AdditionalProperties => _additionalProperties ?? base.AdditionalProperties;
35+
2336
/// <summary>Gets or sets a collection of <see cref="AIContent"/> to be used as input to the file search tool.</summary>
2437
/// <remarks>
2538
/// If no explicit inputs are provided, the service determines what inputs should be searched. Different services

src/Libraries/Microsoft.Extensions.AI.Abstractions/Tools/HostedImageGenerationTool.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Collections.Generic;
45
using System.Diagnostics.CodeAnalysis;
56

67
namespace Microsoft.Extensions.AI;
@@ -13,13 +14,29 @@ namespace Microsoft.Extensions.AI;
1314
[Experimental("MEAI001")]
1415
public class HostedImageGenerationTool : AITool
1516
{
17+
/// <summary>Any additional properties associated with the tool.</summary>
18+
private IReadOnlyDictionary<string, object?>? _additionalProperties;
19+
1620
/// <summary>
1721
/// Initializes a new instance of the <see cref="HostedImageGenerationTool"/> class with the specified options.
1822
/// </summary>
1923
public HostedImageGenerationTool()
2024
{
2125
}
2226

27+
/// <summary>Initializes a new instance of the <see cref="HostedImageGenerationTool"/> class.</summary>
28+
/// <param name="additionalProperties">Any additional properties associated with the tool.</param>
29+
public HostedImageGenerationTool(IReadOnlyDictionary<string, object?>? additionalProperties)
30+
{
31+
_additionalProperties = additionalProperties;
32+
}
33+
34+
/// <inheritdoc />
35+
public override string Name => "image_generation";
36+
37+
/// <inheritdoc />
38+
public override IReadOnlyDictionary<string, object?> AdditionalProperties => _additionalProperties ?? base.AdditionalProperties;
39+
2340
/// <summary>
2441
/// Gets or sets the options used to configure image generation.
2542
/// </summary>

src/Libraries/Microsoft.Extensions.AI.Abstractions/Tools/HostedMcpServerTool.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ namespace Microsoft.Extensions.AI;
1414
[Experimental("MEAI001")]
1515
public class HostedMcpServerTool : AITool
1616
{
17+
/// <summary>Any additional properties associated with the tool.</summary>
18+
private IReadOnlyDictionary<string, object?>? _additionalProperties;
19+
1720
/// <summary>
1821
/// Initializes a new instance of the <see cref="HostedMcpServerTool"/> class.
1922
/// </summary>
@@ -27,6 +30,20 @@ public HostedMcpServerTool(string serverName, string serverAddress)
2730
ServerAddress = Throw.IfNullOrWhitespace(serverAddress);
2831
}
2932

33+
/// <summary>
34+
/// Initializes a new instance of the <see cref="HostedMcpServerTool"/> class.
35+
/// </summary>
36+
/// <param name="serverName">The name of the remote MCP server.</param>
37+
/// <param name="serverAddress">The address of the remote MCP server. This may be a URL, or in the case of a service providing built-in MCP servers with known names, it can be such a name.</param>
38+
/// <param name="additionalProperties">Any additional properties associated with the tool.</param>
39+
/// <exception cref="ArgumentNullException"><paramref name="serverName"/> or <paramref name="serverAddress"/> is <see langword="null"/>.</exception>
40+
/// <exception cref="ArgumentException"><paramref name="serverName"/> or <paramref name="serverAddress"/> is empty or composed entirely of whitespace.</exception>
41+
public HostedMcpServerTool(string serverName, string serverAddress, IReadOnlyDictionary<string, object?>? additionalProperties)
42+
: this(serverName, serverAddress)
43+
{
44+
_additionalProperties = additionalProperties;
45+
}
46+
3047
/// <summary>
3148
/// Initializes a new instance of the <see cref="HostedMcpServerTool"/> class.
3249
/// </summary>
@@ -40,6 +57,21 @@ public HostedMcpServerTool(string serverName, Uri serverUrl)
4057
{
4158
}
4259

60+
/// <summary>
61+
/// Initializes a new instance of the <see cref="HostedMcpServerTool"/> class.
62+
/// </summary>
63+
/// <param name="serverName">The name of the remote MCP server.</param>
64+
/// <param name="serverUrl">The URL of the remote MCP server.</param>
65+
/// <param name="additionalProperties">Any additional properties associated with the tool.</param>
66+
/// <exception cref="ArgumentNullException"><paramref name="serverName"/> or <paramref name="serverUrl"/> is <see langword="null"/>.</exception>
67+
/// <exception cref="ArgumentException"><paramref name="serverName"/> is empty or composed entirely of whitespace.</exception>
68+
/// <exception cref="ArgumentException"><paramref name="serverUrl"/> is not an absolute URL.</exception>
69+
public HostedMcpServerTool(string serverName, Uri serverUrl, IReadOnlyDictionary<string, object?>? additionalProperties)
70+
: this(serverName, ValidateUrl(serverUrl))
71+
{
72+
_additionalProperties = additionalProperties;
73+
}
74+
4375
private static string ValidateUrl(Uri serverUrl)
4476
{
4577
_ = Throw.IfNull(serverUrl);
@@ -55,6 +87,9 @@ private static string ValidateUrl(Uri serverUrl)
5587
/// <inheritdoc />
5688
public override string Name => "mcp";
5789

90+
/// <inheritdoc />
91+
public override IReadOnlyDictionary<string, object?> AdditionalProperties => _additionalProperties ?? base.AdditionalProperties;
92+
5893
/// <summary>
5994
/// Gets the name of the remote MCP server that is used to identify it.
6095
/// </summary>

src/Libraries/Microsoft.Extensions.AI.Abstractions/Tools/HostedWebSearchTool.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Collections.Generic;
5+
46
namespace Microsoft.Extensions.AI;
57

68
/// <summary>Represents a hosted tool that can be specified to an AI service to enable it to perform web searches.</summary>
@@ -10,11 +12,24 @@ namespace Microsoft.Extensions.AI;
1012
/// </remarks>
1113
public class HostedWebSearchTool : AITool
1214
{
15+
/// <summary>Any additional properties associated with the tool.</summary>
16+
private IReadOnlyDictionary<string, object?>? _additionalProperties;
17+
1318
/// <summary>Initializes a new instance of the <see cref="HostedWebSearchTool"/> class.</summary>
1419
public HostedWebSearchTool()
1520
{
1621
}
1722

23+
/// <summary>Initializes a new instance of the <see cref="HostedWebSearchTool"/> class.</summary>
24+
/// <param name="additionalProperties">Any additional properties associated with the tool.</param>
25+
public HostedWebSearchTool(IReadOnlyDictionary<string, object?>? additionalProperties)
26+
{
27+
_additionalProperties = additionalProperties;
28+
}
29+
1830
/// <inheritdoc />
1931
public override string Name => "web_search";
32+
33+
/// <inheritdoc />
34+
public override IReadOnlyDictionary<string, object?> AdditionalProperties => _additionalProperties ?? base.AdditionalProperties;
2035
}

src/Libraries/Microsoft.Extensions.AI.OpenAI/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Microsoft.Extensions.AI.OpenAI Release History
22

3+
## 10.1.1-preview.1.? (NOT YET RELEASED)
4+
5+
- Updated to accommodate the additions in `Microsoft.Extensions.AI.Abstractions`.
6+
- Updated the OpenAI Responses and Chat Completion `IChatClient`s to populate `UsageDetails`'s `InputCachedTokenCount` and `ReasoningTokenCount`.
7+
- Updated handling of `HostedWebSearchTool`, `HostedFileSearchTool`, and `HostedImageGenerationTool` to pull OpenAI-specific
8+
options from `AdditionalProperties`.
9+
310
## 10.1.0-preview.1.25608.1
411

512
- Fixed package references for net10.0 asset.

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIAssistantsChatClient.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,10 @@ internal static FunctionToolDefinition ToOpenAIAssistantsFunctionToolDefinition(
409409
break;
410410

411411
case HostedFileSearchTool fileSearchTool:
412-
_ = toolsOverride.Add(ToolDefinition.CreateFileSearch(fileSearchTool.MaximumResultCount));
412+
var fst = ToolDefinition.CreateFileSearch(fileSearchTool.MaximumResultCount);
413+
fst.RankingOptions = fileSearchTool.GetProperty<FileSearchRankingOptions>(nameof(FileSearchToolDefinition.RankingOptions));
414+
_ = toolsOverride.Add(fst);
415+
413416
if (fileSearchTool.Inputs is { Count: > 0 } fileSearchInputs)
414417
{
415418
foreach (var input in fileSearchInputs)

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIClientExtensions.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ internal static void PatchModelIfNotSet(ref JsonPatch patch, string? modelId)
242242
}
243243
}
244244

245+
/// <summary>Gets the typed property of the specified name from the tool's <see cref="AITool.AdditionalProperties"/>.</summary>
246+
internal static T? GetProperty<T>(this AITool tool, string name) =>
247+
tool.AdditionalProperties?.TryGetValue(name, out object? value) is true && value is T tValue ? tValue : default;
248+
245249
/// <summary>Used to create the JSON payload for an OpenAI tool description.</summary>
246250
internal sealed class ToolJson
247251
{

0 commit comments

Comments
 (0)