Skip to content

Commit b279a78

Browse files
authored
Agents v2 (branch-to-branch): OpenAI 2.7.0 / SCM 1.8.1 (#54001)
* incorporate SCM 1.8.1 via OpenAI 2.7.0 rev * (tiny) normalize slashes in csproj
1 parent 1ba8ce4 commit b279a78

14 files changed

+153
-191
lines changed

eng/Packages.Data.props

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,10 @@
208208
<PackageReference Update="OpenAI" Version="[2.6.0,3.0)" />
209209
</ItemGroup>
210210

211-
<ItemGroup Condition="$(MSBuildProjectName.StartsWith('Azure.AI.Projects.OpenAI'))">
212-
<PackageReference Update="OpenAI" Version="[2.6.0,3.0)" />
211+
<ItemGroup Condition="$(MSBuildProjectName.StartsWith('Azure.AI.Projects'))">
212+
<PackageReference Update="OpenAI" Version="[2.7.0,3.0)" />
213+
<!-- Foundry libs depend on OpenAI; float SCM with upstream version -->
214+
<PackageReference Update="System.ClientModel" Version="*" />
213215
</ItemGroup>
214216

215217
<ItemGroup Condition="$(MSBuildProjectName.StartsWith('Azure.AI.AgentServer'))">

sdk/ai/Azure.AI.Projects.OpenAI/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
## 1.0.0-beta.4 (Unreleased)
44

5+
This change updates the baseline `OpenAI` dependency to the latest `2.7.0` official version. For inherited details, please see the [OpenAI .NET changelog](https://github.com/openai/openai-dotnet/tree/main/CHANGELOG.md).
6+
7+
### Breaking Changes (beta)
8+
9+
**Transitive from upgrade to System.ClientModel 1.8.1**:
10+
11+
- The extension `StructuredInputs` on `ResponseCreationOptions` will now correctly return a `BinaryData` instance with enclosing quotes included when retrieving an encoded string value
12+
513
## 1.0.0-beta.3 (2025-11-15)
614

715
### Bugs Fixed

sdk/ai/Azure.AI.Projects.OpenAI/src/Azure.AI.Projects.OpenAI.csproj

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,25 @@
1111
<Version>1.0.0-beta.4</Version>
1212
<PackageTags>Azure.AI.Projects.OpenAI</PackageTags>
1313
<TargetFrameworks>$(RequiredTargetFrameworks)</TargetFrameworks>
14-
<NoWarn>$(NoWarn);OPENAI001;CS1591;AZC0007;AZC0012;AZC0015;AZC0030;AZC0031;AZC0034;SA1649;SA1402;AZC0035</NoWarn>
15-
<!-- C# 14 extension property features; unnecessary once C# 14 releases -->
14+
</PropertyGroup>
15+
16+
<PropertyGroup>
17+
<!-- Acknowledge experimental OpenAI features -->
18+
<NoWarn>$(NoWarn);OPENAI001</NoWarn>
19+
<!-- Temporary suppression of XML doc requirement -->
20+
<NoWarn>$(NoWarn);CS1591</NoWarn>
21+
<!-- Ignore Azure-Core-specific constructor rule -->
22+
<NoWarn>$(NoWarn);AZC0007</NoWarn>
23+
<!-- Ignore Azure-Core-specific pageable rule -->
24+
<NoWarn>$(NoWarn);AZC0015</NoWarn>
25+
<!-- Ignore ModelFactory error (applied to externally originating types) -->
26+
<NoWarn>$(NoWarn);AZC0035</NoWarn>
27+
</PropertyGroup>
28+
29+
<PropertyGroup>
30+
<!-- For C# 14 extension property support, pending full toolchain integration -->
1631
<LangVersion>preview</LangVersion>
32+
<EnablePreviewFeatures>true</EnablePreviewFeatures>
1733
</PropertyGroup>
1834

1935
<ItemGroup>

sdk/ai/Azure.AI.Projects.OpenAI/src/Custom/OpenAI/ExtraDataDictionary.cs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -96,17 +96,12 @@ public bool Remove(string key)
9696

9797
public bool TryGetValue(ReadOnlySpan<byte> key, out BinaryData value)
9898
{
99-
// Try/catch: temporary SCM 1.8.0 workaround for TryGetJson
100-
try
99+
if (_parentOptions.Patch.TryGetJson(GetPathBytes(key), out ReadOnlyMemory<byte> jsonValueBytes)
100+
&& !jsonValueBytes.IsEmpty)
101101
{
102-
if (_parentOptions.Patch.TryGetJson(GetPathBytes(key), out ReadOnlyMemory<byte> jsonValueBytes)
103-
&& !jsonValueBytes.IsEmpty)
104-
{
105-
value = BinaryData.FromBytes(jsonValueBytes);
106-
return true;
107-
}
102+
value = BinaryData.FromBytes(jsonValueBytes);
103+
return true;
108104
}
109-
catch { }
110105
value = null;
111106
return false;
112107
}
@@ -128,19 +123,14 @@ private Dictionary<string, BinaryData> GetFullParsedDictionary()
128123
&& _parentOptions.Patch.TryGetJson(rootPathBytes, out ReadOnlyMemory<byte> jsonValueBytes)
129124
&& !jsonValueBytes.IsEmpty)
130125
{
131-
try
126+
using JsonDocument document = JsonDocument.Parse(jsonValueBytes);
127+
if (document.RootElement.ValueKind == JsonValueKind.Object)
132128
{
133-
using JsonDocument document = JsonDocument.Parse(jsonValueBytes);
134-
if (document.RootElement.ValueKind == JsonValueKind.Object)
129+
foreach (JsonProperty property in document.RootElement.EnumerateObject())
135130
{
136-
foreach (JsonProperty property in document.RootElement.EnumerateObject())
137-
{
138-
result.Add(property.Name, BinaryData.FromString(property.Value.GetRawText()));
139-
}
131+
result.Add(property.Name, BinaryData.FromString(property.Value.GetRawText()));
140132
}
141133
}
142-
catch (JsonException)
143-
{ }
144134
}
145135
return result;
146136
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#nullable enable
5+
6+
using System;
7+
using System.ClientModel.Primitives;
8+
9+
#pragma warning disable SCME0001
10+
11+
namespace Azure.AI.Projects.OpenAI;
12+
13+
internal static partial class JsonPatchExtensions
14+
{
15+
public static string? GetStringEx(this ref JsonPatch patch, ReadOnlySpan<byte> jsonPath)
16+
=> patch.IsRemoved(jsonPath)
17+
|| !patch.TryGetJson(jsonPath, out ReadOnlyMemory<byte> jsonBytes)
18+
|| jsonBytes.IsEmpty
19+
? null
20+
: patch.GetString(jsonPath);
21+
22+
public static T? GetJsonModelEx<T>(this ref JsonPatch patch, ReadOnlySpan<byte> jsonPath, ModelReaderWriterContext? readerContext = null)
23+
where T : class, IJsonModel<T>
24+
{
25+
if (patch.IsRemoved(jsonPath) || !patch.TryGetJson(jsonPath, out ReadOnlyMemory<byte> jsonBytes) || jsonBytes.IsEmpty)
26+
{
27+
return null;
28+
}
29+
readerContext ??= AzureAIProjectsOpenAIContext.Default;
30+
return ModelReaderWriter.Read<T>(BinaryData.FromBytes(jsonBytes), ModelSerializationExtensions.WireOptions, readerContext);
31+
}
32+
33+
public static void SetOrClearEx(this ref JsonPatch patch, ReadOnlySpan<byte> jsonPath, ReadOnlySpan<byte> jsonRemovalPath, string? value)
34+
{
35+
if (value is null)
36+
{
37+
patch.Remove(jsonRemovalPath);
38+
}
39+
else
40+
{
41+
patch.Set(jsonPath, value);
42+
}
43+
}
44+
45+
public static void SetOrClearEx<T>(
46+
this ref JsonPatch patch,
47+
ReadOnlySpan<byte> jsonPath,
48+
ReadOnlySpan<byte> jsonRemovalPath,
49+
T? value,
50+
ModelReaderWriterContext? writerContext = null)
51+
where T : IJsonModel<T>
52+
{
53+
if (value is null)
54+
{
55+
patch.Remove(jsonRemovalPath);
56+
}
57+
else
58+
{
59+
writerContext ??= AzureAIProjectsOpenAIContext.Default;
60+
patch.Set(jsonPath, ModelReaderWriter.Write(value, ModelSerializationExtensions.WireOptions, writerContext));
61+
}
62+
}
63+
}

sdk/ai/Azure.AI.Projects.OpenAI/src/Custom/OpenAI/OpenAIResponseExtensions.cs

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,7 @@
55

66
using System;
77
using System.ClientModel.Primitives;
8-
using System.Collections;
9-
using System.Collections.Generic;
10-
using System.IO;
11-
using System.Text;
12-
using System.Text.Json.Nodes;
13-
using Azure.AI.Projects.OpenAI;
8+
using System.Text.Json;
149
using OpenAI.Responses;
1510

1611
#pragma warning disable OPENAI001
@@ -22,45 +17,8 @@ public static partial class OpenAIResponseExtensions
2217
{
2318
extension(OpenAIResponse response)
2419
{
25-
public AgentReference Agent
26-
{
27-
get
28-
{
29-
// try/catch: SCM 1.8.0 workaround (fixed in 1.8.1)
30-
try
31-
{
32-
if (response.Patch.Contains("$.agent"u8)
33-
&& !response.Patch.IsRemoved("$.agent"u8)
34-
&& response.Patch.TryGetJson("$.agent"u8, out ReadOnlyMemory<byte> agentBytes)
35-
&& !agentBytes.IsEmpty)
36-
{
37-
AgentReference retrievedReference = ModelReaderWriter.Read<AgentReference>(BinaryData.FromBytes(agentBytes), ModelSerializationExtensions.WireOptions, AzureAIProjectsOpenAIContext.Default);
38-
return retrievedReference;
39-
}
40-
}
41-
catch (InvalidOperationException) { }
42-
return null;
43-
}
44-
}
20+
public AgentReference Agent => response.Patch.GetJsonModelEx<AgentReference>("$.agent"u8);
4521

46-
public string AgentConversationId
47-
{
48-
get
49-
{
50-
// try/catch: SCM 1.8.0 workaround (fixed in 1.8.1)
51-
try
52-
{
53-
if (response.Patch.Contains("$.conversation"u8)
54-
&& !response.Patch.IsRemoved("$.conversation"u8)
55-
&& response.Patch.TryGetJson("$.conversation.id"u8, out ReadOnlyMemory<byte> jsonPathValue)
56-
&& !jsonPathValue.IsEmpty)
57-
{
58-
return BinaryData.FromBytes(jsonPathValue).ToString();
59-
}
60-
}
61-
catch (InvalidOperationException) { }
62-
return null;
63-
}
64-
}
22+
public string AgentConversationId => response.Patch.GetStringEx("$.conversation.id"u8);
6523
}
6624
}

sdk/ai/Azure.AI.Projects.OpenAI/src/Custom/OpenAI/ResponseCreationOptionsExtensions.cs

Lines changed: 6 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -24,94 +24,20 @@ public static partial class ResponseCreationOptionsExtensions
2424
{
2525
public string Model
2626
{
27-
get
28-
{
29-
try
30-
{
31-
if (options.Patch.Contains("$.model"u8)
32-
&& !options.Patch.IsRemoved("$.model"u8)
33-
&& options.Patch.TryGetJson("$.model"u8, out ReadOnlyMemory<byte> agentBytes)
34-
&& !agentBytes.IsEmpty)
35-
{
36-
return BinaryData.FromBytes(agentBytes).ToString();
37-
}
38-
}
39-
catch (InvalidOperationException) { }
40-
return null;
41-
}
42-
set
43-
{
44-
if (value is not null)
45-
{
46-
options.Patch.Set("$.model"u8, value);
47-
}
48-
else
49-
{
50-
options.Patch.Remove("$.model"u8);
51-
}
52-
}
27+
get => options.Patch.GetStringEx("$.model"u8);
28+
set => options.Patch.SetOrClearEx("$.model"u8, "$.model"u8, value);
5329
}
5430

5531
public AgentReference Agent
5632
{
57-
get
58-
{
59-
try
60-
{
61-
if (options.Patch.Contains("$.agent"u8)
62-
&& !options.Patch.IsRemoved("$.agent"u8)
63-
&& options.Patch.TryGetJson("$.agent"u8, out ReadOnlyMemory<byte> agentBytes)
64-
&& !agentBytes.IsEmpty)
65-
{
66-
AgentReference retrievedReference = ModelReaderWriter.Read<AgentReference>(BinaryData.FromBytes(agentBytes), ModelSerializationExtensions.WireOptions, AzureAIProjectsOpenAIContext.Default);
67-
return retrievedReference;
68-
}
69-
}
70-
catch (InvalidOperationException) { }
71-
return null;
72-
}
73-
set
74-
{
75-
if (value is not null)
76-
{
77-
options.Patch.Set("$.agent"u8, ModelReaderWriter.Write(value, ModelSerializationExtensions.WireOptions, AzureAIProjectsOpenAIContext.Default));
78-
}
79-
else
80-
{
81-
options.Patch.Remove("$.agent"u8);
82-
}
83-
}
33+
get => options.Patch.GetJsonModelEx<AgentReference>("$.agent"u8);
34+
set => options.Patch.SetOrClearEx("$.agent"u8, "$.agent"u8, value);
8435
}
8536

8637
public string AgentConversationId
8738
{
88-
get
89-
{
90-
// try/catch: SCM 1.8.0 workaround (fixed in 1.8.1)
91-
try
92-
{
93-
if (options.Patch.Contains("$.conversation"u8)
94-
&& !options.Patch.IsRemoved("$.conversation"u8)
95-
&& options.Patch.TryGetJson("$.conversation.id"u8, out ReadOnlyMemory<byte> jsonPathValue)
96-
&& !jsonPathValue.IsEmpty)
97-
{
98-
return BinaryData.FromBytes(jsonPathValue).ToString();
99-
}
100-
}
101-
catch (InvalidOperationException) { }
102-
return null;
103-
}
104-
set
105-
{
106-
if (value is not null)
107-
{
108-
options.Patch.Set("$.conversation.id"u8, value);
109-
}
110-
else
111-
{
112-
options.Patch.Remove("$.conversation"u8);
113-
}
114-
}
39+
get => options.Patch.GetStringEx("$.conversation.id"u8);
40+
set => options.Patch.SetOrClearEx("$.conversation.id"u8, "$.conversation"u8, value);
11541
}
11642

11743
public ExtraDataDictionary StructuredInputs => new ExtraDataDictionary(options, "$.structured_inputs"u8);

sdk/ai/Azure.AI.Projects.OpenAI/tests/Azure.AI.Projects.OpenAI.Tests.csproj

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<TargetFrameworks>$(RequiredTargetFrameworks)</TargetFrameworks>
4-
54
<!--Ignore XML doc comments on test types and members-->
65
<NoWarn>$(NoWarn);CS1591</NoWarn>
7-
8-
<!-- Package downgrade (BCL) -->
9-
<NoWarn>$(NoWarn);NU1605</NoWarn>
10-
11-
<!-- Temporary fix to include latest changes from Projects. -->
12-
<NoWarn>$(NoWarn);NU1105</NoWarn>
13-
146
<!-- OPENAI001 - Ignore experimental warnings-->
157
<NoWarn>$(NoWarn);OPENAI001;SCME0001;</NoWarn>
8+
</PropertyGroup>
169

10+
<PropertyGroup>
11+
<!-- For C# 14 extension property support, pending full toolchain integration -->
1712
<LangVersion>preview</LangVersion>
13+
<EnablePreviewFeatures>true</EnablePreviewFeatures>
1814
</PropertyGroup>
15+
1916
<ItemGroup>
2017
<ProjectReference Include="..\..\Azure.AI.Projects\src\Azure.AI.Projects.csproj" />
2118
</ItemGroup>
@@ -29,10 +26,6 @@
2926
<PackageReference Include="System.Linq.Async" />
3027
<PackageReference Include="Microsoft.ClientModel.TestFramework" />
3128
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" />
32-
</ItemGroup>
33-
34-
<ItemGroup>
35-
3629
</ItemGroup>
3730

3831
<ItemGroup>

0 commit comments

Comments
 (0)