Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
05fe7a5
Merged PR 54952: Getting ready for the 10.0 stable release. Flowing .…
joperezr Nov 6, 2025
de9fc03
[MEDI] start producing NuGet packages (#7016)
adamsitnik Nov 5, 2025
a7f5cbc
Update version numbers in AI changelogs (#7008)
stephentoub Nov 6, 2025
2279548
[MEDI] Don't stop document processing on enricher error (#7005)
adamsitnik Nov 6, 2025
90846d8
[MEDI] add PackageTags (#7022)
adamsitnik Nov 6, 2025
1d693bc
Add MarkItDownMcpReader for MCP server support (#7025)
Copilot Nov 7, 2025
9cd3cf4
Image generation tool (#6749)
ericstj Nov 7, 2025
d6f343c
Make MEAI packages use 10.0 runtime packages (#7028)
ericstj Nov 8, 2025
ea69fde
Merged PR 55051: Backport MEAI libraries updates into release/10.0
jeffhandley Nov 8, 2025
0e1d148
When using latest .NET packages, force System.Numerics.Tensors to 10.…
jeffhandley Nov 9, 2025
fbd3936
Merged PR 55054: When using latest .NET packages, force System.Numeri…
jeffhandley Nov 10, 2025
e3beb46
Add a new Microsoft.Agents.AI.Templates package with an aiagents-weba…
jeffhandley Nov 7, 2025
8917d58
Use `Microsoft.Extensions.DataIngestion` in AI Chat Web template (#7023)
MackinnonBuck Nov 10, 2025
243be68
Add Agent Framework DevUI into the aiagent-webapi template (#7026)
jeffhandley Nov 11, 2025
886cdd8
Fix display of target frameworks in agents template. Hide the chat mo…
jeffhandley Nov 11, 2025
b093829
Port project template updates into the 10.0 release branch
jeffhandley Nov 11, 2025
e9e1d3e
Merging changes from internal branch
joperezr Nov 11, 2025
2b6ecc1
Merge changes from internal (#7038)
joperezr Nov 14, 2025
8dc19dd
Merge changes from release/10.0 into main
joperezr Nov 14, 2025
fe1de92
Resolve merge conflicts
jeffhandley Nov 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 100 additions & 100 deletions eng/Version.Details.xml

Large diffs are not rendered by default.

228 changes: 114 additions & 114 deletions eng/Versions.props

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,19 @@
yield return CreateUpdate(GetImageGenerationResult(streamingImageGenUpdate, options));
break;

case StreamingResponseImageGenerationCallInProgressUpdate imageGenInProgress:

Check failure on line 469 in src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs

View check run for this annotation

Azure Pipelines / extensions-ci (Build Ubuntu)

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs#L469

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs(469,22): error CS8120: (NETCORE_ENGINEERING_TELEMETRY=Build) The switch case is unreachable. It has already been handled by a previous case or it is impossible to match.

Check failure on line 469 in src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs

View check run for this annotation

Azure Pipelines / extensions-ci (Build Ubuntu)

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs#L469

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs(469,22): error CS8120: (NETCORE_ENGINEERING_TELEMETRY=Build) The switch case is unreachable. It has already been handled by a previous case or it is impossible to match.

Check failure on line 469 in src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs

View check run for this annotation

Azure Pipelines / extensions-ci (Build Ubuntu)

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs#L469

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs(469,22): error CS8120: (NETCORE_ENGINEERING_TELEMETRY=Build) The switch case is unreachable. It has already been handled by a previous case or it is impossible to match.

Check failure on line 469 in src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs

View check run for this annotation

Azure Pipelines / extensions-ci

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs#L469

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs(469,22): error CS8120: (NETCORE_ENGINEERING_TELEMETRY=Build) The switch case is unreachable. It has already been handled by a previous case or it is impossible to match.

Check failure on line 469 in src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs

View check run for this annotation

Azure Pipelines / extensions-ci

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs#L469

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs(469,22): error CS8120: (NETCORE_ENGINEERING_TELEMETRY=Build) The switch case is unreachable. It has already been handled by a previous case or it is impossible to match.
yield return CreateUpdate(new ImageGenerationToolCallContent
{
ImageId = imageGenInProgress.ItemId,
RawRepresentation = imageGenInProgress,

});
goto default;

case StreamingResponseImageGenerationCallPartialImageUpdate streamingImageGenUpdate:

Check failure on line 478 in src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs

View check run for this annotation

Azure Pipelines / extensions-ci (Build Ubuntu)

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs#L478

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs(478,22): error CS8120: (NETCORE_ENGINEERING_TELEMETRY=Build) The switch case is unreachable. It has already been handled by a previous case or it is impossible to match.

Check failure on line 478 in src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs

View check run for this annotation

Azure Pipelines / extensions-ci (Build Ubuntu)

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs#L478

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs(478,22): error CS8120: (NETCORE_ENGINEERING_TELEMETRY=Build) The switch case is unreachable. It has already been handled by a previous case or it is impossible to match.

Check failure on line 478 in src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs

View check run for this annotation

Azure Pipelines / extensions-ci

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs#L478

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs(478,22): error CS8120: (NETCORE_ENGINEERING_TELEMETRY=Build) The switch case is unreachable. It has already been handled by a previous case or it is impossible to match.

Check failure on line 478 in src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs

View check run for this annotation

Azure Pipelines / extensions-ci

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs#L478

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs(478,22): error CS8120: (NETCORE_ENGINEERING_TELEMETRY=Build) The switch case is unreachable. It has already been handled by a previous case or it is impossible to match.
yield return CreateUpdate(GetImageGenerationResult(streamingImageGenUpdate, options));
break;

default:
yield return CreateUpdate();
break;
Expand Down Expand Up @@ -1295,13 +1308,26 @@
var imageGenTool = options?.Tools.OfType<ImageGenerationTool>().FirstOrDefault();
var outputType = imageGenTool?.OutputFileFormat?.ToString() ?? "png";

var bytes = update.PartialImageBytes;

if (bytes is null || bytes.Length == 0)
{
// workaround https://github.com/openai/openai-dotnet/issues/809
if (update.Patch.TryGetJson("$.partial_image_b64"u8, out var jsonBytes))
{
Utf8JsonReader reader = new(jsonBytes.Span);
_ = reader.Read();
bytes = BinaryData.FromBytes(reader.GetBytesFromBase64());
}
}

return new ImageGenerationToolResultContent
{
ImageId = update.ItemId,
RawRepresentation = update,
Outputs = new List<AIContent>
{
new DataContent(update.PartialImageBytes, $"image/{outputType}")
new DataContent(bytes, $"image/{outputType}")
{
AdditionalProperties = new()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,21 @@ public override async Task<IngestionDocument> ReadAsync(FileInfo source, string
throw new FileNotFoundException("The specified file does not exist.", source.FullName);
}

// Read file content and create DataContent
// Read file content as base64 data URI
#if NET
ReadOnlyMemory<byte> fileBytes = await File.ReadAllBytesAsync(source.FullName, cancellationToken).ConfigureAwait(false);
byte[] fileBytes = await File.ReadAllBytesAsync(source.FullName, cancellationToken).ConfigureAwait(false);
#else
ReadOnlyMemory<byte> fileBytes;
byte[] fileBytes;
using (FileStream fs = new(source.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 1, FileOptions.Asynchronous))
{
using MemoryStream ms = new((int)Math.Min(int.MaxValue, fs.Length));
using MemoryStream ms = new();
await fs.CopyToAsync(ms).ConfigureAwait(false);
fileBytes = ms.GetBuffer().AsMemory(0, (int)ms.Length);
fileBytes = ms.ToArray();
}
#endif
DataContent dataContent = new(
fileBytes,
string.IsNullOrEmpty(mediaType) ? "application/octet-stream" : mediaType!);
string dataUri = CreateDataUri(fileBytes, mediaType);

string markdown = await ConvertToMarkdownAsync(dataContent, cancellationToken).ConfigureAwait(false);
string markdown = await ConvertToMarkdownAsync(dataUri, cancellationToken).ConfigureAwait(false);

return MarkdownParser.Parse(markdown, identifier);
}
Expand All @@ -70,23 +68,31 @@ public override async Task<IngestionDocument> ReadAsync(Stream source, string id
_ = Throw.IfNull(source);
_ = Throw.IfNullOrEmpty(identifier);

// Read stream content and create DataContent
using MemoryStream ms = source.CanSeek ? new((int)Math.Min(int.MaxValue, source.Length)) : new();
// Read stream content as base64 data URI
using MemoryStream ms = new();
#if NET
await source.CopyToAsync(ms, cancellationToken).ConfigureAwait(false);
#else
await source.CopyToAsync(ms).ConfigureAwait(false);
#endif
DataContent dataContent = new(
ms.GetBuffer().AsMemory(0, (int)ms.Length),
string.IsNullOrEmpty(mediaType) ? "application/octet-stream" : mediaType);
byte[] fileBytes = ms.ToArray();
string dataUri = CreateDataUri(fileBytes, mediaType);

string markdown = await ConvertToMarkdownAsync(dataContent, cancellationToken).ConfigureAwait(false);
string markdown = await ConvertToMarkdownAsync(dataUri, cancellationToken).ConfigureAwait(false);

return MarkdownParser.Parse(markdown, identifier);
}

private async Task<string> ConvertToMarkdownAsync(DataContent dataContent, CancellationToken cancellationToken)
#pragma warning disable S3995 // URI return values should not be strings
private static string CreateDataUri(byte[] fileBytes, string? mediaType)
#pragma warning restore S3995 // URI return values should not be strings
{
string base64Content = Convert.ToBase64String(fileBytes);
string mimeType = string.IsNullOrEmpty(mediaType) ? "application/octet-stream" : mediaType!;
return $"data:{mimeType};base64,{base64Content}";
}

private async Task<string> ConvertToMarkdownAsync(string dataUri, CancellationToken cancellationToken)
{
// Create HTTP client transport for MCP
HttpClientTransport transport = new(new HttpClientTransportOptions
Expand All @@ -104,7 +110,7 @@ private async Task<string> ConvertToMarkdownAsync(DataContent dataContent, Cance
// Build parameters for convert_to_markdown tool
Dictionary<string, object?> parameters = new()
{
["uri"] = dataContent.Uri
["uri"] = dataUri
};

// Call the convert_to_markdown tool
Expand Down
38 changes: 38 additions & 0 deletions src/Libraries/Microsoft.Extensions.DataIngestion/Utils/Batching.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

using System;
using System.Collections.Generic;
#if NET10_0_OR_GREATER
using System.Linq;
#endif
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -67,4 +69,40 @@ internal static async IAsyncEnumerable<IngestionChunk<string>> ProcessAsync<TMet
}
}
}

#if !NET10_0_OR_GREATER
#pragma warning disable VSTHRD200 // Use "Async" suffix for async methods
private static IAsyncEnumerable<TSource[]> Chunk<TSource>(this IAsyncEnumerable<TSource> source, int count)
#pragma warning restore VSTHRD200 // Use "Async" suffix for async methods
{
_ = Throw.IfNull(source);
_ = Throw.IfLessThanOrEqual(count, 0);

return CoreAsync(source, count);

static async IAsyncEnumerable<TSource[]> CoreAsync(IAsyncEnumerable<TSource> source, int count,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var buffer = new TSource[count];
int index = 0;

await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
{
buffer[index++] = item;

if (index == count)
{
index = 0;
yield return buffer;
}
}

if (index > 0)
{
Array.Resize(ref buffer, index);
yield return buffer;
}
}
}
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
{
"id": "ChatModel",
"isVisible": true
"isVisible": false
},
{
"id": "UseManagedIdentity",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@
"choices": [
{
"choice": "net10.0",
"description": "Target net10.0"
"description": ".NET 10"
},
{
"choice": "net9.0",
"description": "Target net9.0"
"description": ".NET 9"
},
{
"choice": "net8.0",
"description": "Target net8.0"
"description": ".NET 8"
}
],
"replaces": "net10.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<PackageReference Include="Microsoft.ML.Tokenizers.Data.Cl100kBase" Version="${TemplatePackageVersion_MicrosoftMLTokenizers}" />
<PackageReference Include="Microsoft.ML.Tokenizers.Data.O200kBase" Version="${TemplatePackageVersion_MicrosoftMLTokenizers}" />
<!--#if (IsNET9) -->
<PackageReference Include="System.Linq.AsyncEnumerable" Version="${TemplatePackageVersion_SystemLinqAsyncEnumerable}" />
<PackageReference Include="System.Linq.Async" Version="${TemplatePackageVersion_SystemLinqAsync}" />
<!--#endif -->
<!--#if (IsAzureAISearch && IsAspire)
<PackageReference Include="Aspire.Azure.Search.Documents" Version="${TemplatePackageVersion_Aspire}" />
Expand Down
Loading