Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
73e5515
impl
Apr 5, 2026
2dbfc48
github actions bug fixes
Apr 5, 2026
6769477
rust fix
Apr 5, 2026
e632ac4
rust fix v2
Apr 5, 2026
59e9a84
rust fix v3
Apr 5, 2026
d2c9ebf
merge deps versions
Apr 5, 2026
c35ce35
checkout none
Apr 6, 2026
f76a2a8
Merge remote-tracking branch 'origin' into prathikrao/unify-flc-versi…
Apr 6, 2026
14ab58d
rust fmt fix
Apr 6, 2026
1be045b
bug fixes
Apr 6, 2026
20bb8ee
standard genai
Apr 6, 2026
bbf0f4b
bug fixes
Apr 6, 2026
ea7add0
Merge remote-tracking branch 'origin' into prathikrao/unify-flc-versi…
Apr 7, 2026
8b9b6d1
bug fix
Apr 7, 2026
d8f6f98
Merge remote-tracking branch 'origin' into prathikrao/unify-flc-versi…
Apr 7, 2026
68dfe94
separate deps
Apr 7, 2026
9a18540
combine sdk build & test stages
Apr 7, 2026
e045e23
bug fixes
Apr 7, 2026
5eb2b34
stage naming
Apr 7, 2026
1a67cff
rust fix
Apr 7, 2026
b7fee62
rustic fix
Apr 7, 2026
6bf4f1f
Merge remote-tracking branch 'origin' into prathikrao/unify-flc-versi…
Apr 7, 2026
cc289f6
copilot feedback
Apr 7, 2026
8370e3e
js fixes
Apr 7, 2026
1e4bc43
even less stages
Apr 7, 2026
c96365f
copilot feedback
Apr 7, 2026
4c84e17
Merge remote-tracking branch 'origin' into prathikrao/unify-flc-versi…
Apr 7, 2026
8cb8d33
js & rust fixes
Apr 8, 2026
36d485a
Merge remote-tracking branch 'origin' into prathikrao/unify-flc-versi…
Apr 8, 2026
a2da0fd
js fix
Apr 8, 2026
73a14ed
Merge remote-tracking branch 'origin' into prathikrao/unify-flc-versi…
Apr 8, 2026
1252b44
Merge remote-tracking branch 'origin' into prathikrao/unify-flc-versi…
Apr 13, 2026
bd5edae
baiju
Apr 13, 2026
f66b14d
net8.0
Apr 14, 2026
c2aeeda
use net 8
Apr 14, 2026
6976866
more net8.0
Apr 14, 2026
d210e48
revert
Apr 14, 2026
d1709f7
Revert "more net8.0"
Apr 14, 2026
66ea6d2
revert
Apr 14, 2026
53baa2f
Merge remote-tracking branch 'origin' into prathikrao/net8-support
Apr 14, 2026
64d236c
sdk 8.0
Apr 14, 2026
c6fabcf
bug
Apr 14, 2026
7dec015
net8.0 for tests
Apr 14, 2026
0058c7b
netstandard2.0
Apr 14, 2026
9e5a4e1
winml
Apr 14, 2026
28f5219
rmv trimmable
Apr 14, 2026
1b13fb1
Merge remote-tracking branch 'origin' into prathikrao/net8-support
Apr 15, 2026
2683b0b
more support
Apr 15, 2026
8e7cc03
maximum targets
Apr 15, 2026
745b2dd
bug fixes
Apr 16, 2026
9b9ebc4
missing package ref
Apr 16, 2026
1b4169b
add polysharp
Apr 16, 2026
1f540d9
<net7.0 support fixes
Apr 16, 2026
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
8 changes: 5 additions & 3 deletions .pipelines/templates/build-cs-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ steps:
Write-Host "##vso[task.setvariable variable=repoRoot]$repoRoot"
Write-Host "##vso[task.setvariable variable=testDataDir]$testDataDir"

# Using the latest SDK does not prevent us from targeting other platforms.
# It ensures that we've got the latest tooling, fixes, and performance enhancements.
- task: UseDotNet@2
displayName: 'Use .NET 9 SDK'
displayName: 'Use .NET 10 SDK'
inputs:
packageType: sdk
version: '9.0.x'
version: '10.0.x'

# Read version from the version-info artifact produced by compute_version stage.
- task: PowerShell@2
Expand Down Expand Up @@ -127,7 +129,7 @@ steps:
targetType: inline
script: |
$base = "$(repoRoot)/sdk/cs/src/bin/Release"
# The SDK targets net9.0 (standard) or net9.0-windows10.0.26100.0 (WinML).
# The SDK targets netstandard2.0 and any compatible runtime.
# Find whichever TFM directory was produced by the build.
$tfmDir = Get-ChildItem $base -Directory | Select-Object -First 1
if (-not $tfmDir) { throw "No target framework directory found under $base" }
Expand Down
40 changes: 40 additions & 0 deletions sdk/cs/src/Detail/CoreInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
// need to load ORT first as the winml GenAI library redirects and tries to load a winml onnxruntime.dll,
// which will not have the EPs we expect/require. if/when we don't bundle our own onnxruntime.dll we need to
// revisit this.
var loadedOrt = NativeLibrary.TryLoad(ortPath, out ortLibHandle);

Check failure on line 45 in sdk/cs/src/Detail/CoreInterop.cs

View workflow job for this annotation

GitHub Actions / build-cs-macos / build

The name 'NativeLibrary' does not exist in the current context
var loadedGenAI = NativeLibrary.TryLoad(genaiPath, out genaiLibHandle);

Check failure on line 46 in sdk/cs/src/Detail/CoreInterop.cs

View workflow job for this annotation

GitHub Actions / build-cs-macos / build

The name 'NativeLibrary' does not exist in the current context

#if DEBUG
Console.WriteLine($"Loaded ORT:{loadedOrt} handle={ortLibHandle}");
Expand All @@ -53,7 +53,7 @@

static CoreInterop()
{
NativeLibrary.SetDllImportResolver(typeof(CoreInterop).Assembly, (libraryName, assembly, searchPath) =>

Check failure on line 56 in sdk/cs/src/Detail/CoreInterop.cs

View workflow job for this annotation

GitHub Actions / build-cs-macos / build

The name 'NativeLibrary' does not exist in the current context
{
if (libraryName == LibraryName)
{
Expand Down Expand Up @@ -156,41 +156,81 @@
private unsafe delegate void ExecuteCommandDelegate(RequestBuffer* req, ResponseBuffer* resp);

// Import the function from the AOT-compiled library
#if NET7_0_OR_GREATER
[LibraryImport(LibraryName, EntryPoint = "execute_command")]
[UnmanagedCallConv(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
private static unsafe partial void CoreExecuteCommand(RequestBuffer* request, ResponseBuffer* response);
#else
[DllImport(LibraryName, EntryPoint = "execute_command", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern void CoreExecuteCommand(RequestBuffer* request, ResponseBuffer* response);
#endif

#if NET7_0_OR_GREATER
[LibraryImport(LibraryName, EntryPoint = "execute_command_with_callback")]
[UnmanagedCallConv(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
private static unsafe partial void CoreExecuteCommandWithCallback(RequestBuffer* nativeRequest,
ResponseBuffer* nativeResponse,
nint callbackPtr, // NativeCallbackFn pointer
nint userData);
#else
[DllImport(LibraryName, EntryPoint = "execute_command_with_callback", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern void CoreExecuteCommandWithCallback(RequestBuffer* nativeRequest,
ResponseBuffer* nativeResponse,
nint callbackPtr,
nint userData);
#endif

#if NET7_0_OR_GREATER
[LibraryImport(LibraryName, EntryPoint = "execute_command_with_binary")]
[UnmanagedCallConv(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
private static unsafe partial void CoreExecuteCommandWithBinary(StreamingRequestBuffer* nativeRequest,
ResponseBuffer* nativeResponse);
#else
[DllImport(LibraryName, EntryPoint = "execute_command_with_binary", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern void CoreExecuteCommandWithBinary(StreamingRequestBuffer* nativeRequest,
ResponseBuffer* nativeResponse);
#endif

// --- Audio streaming P/Invoke imports (kept for future dedicated entry points) ---

#if NET7_0_OR_GREATER
[LibraryImport(LibraryName, EntryPoint = "audio_stream_start")]
[UnmanagedCallConv(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
private static unsafe partial void CoreAudioStreamStart(
RequestBuffer* request,
ResponseBuffer* response);
#else
[DllImport(LibraryName, EntryPoint = "audio_stream_start", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern void CoreAudioStreamStart(
RequestBuffer* request,
ResponseBuffer* response);
#endif

#if NET7_0_OR_GREATER
[LibraryImport(LibraryName, EntryPoint = "audio_stream_push")]
[UnmanagedCallConv(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
private static unsafe partial void CoreAudioStreamPush(
StreamingRequestBuffer* request,
ResponseBuffer* response);
#else
[DllImport(LibraryName, EntryPoint = "audio_stream_push", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern void CoreAudioStreamPush(
StreamingRequestBuffer* request,
ResponseBuffer* response);
#endif

#if NET7_0_OR_GREATER
[LibraryImport(LibraryName, EntryPoint = "audio_stream_stop")]
[UnmanagedCallConv(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
private static unsafe partial void CoreAudioStreamStop(
RequestBuffer* request,
ResponseBuffer* response);
#else
[DllImport(LibraryName, EntryPoint = "audio_stream_stop", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern void CoreAudioStreamStop(
RequestBuffer* request,
ResponseBuffer* response);
#endif

// helper to capture exceptions in callbacks
internal class CallbackHelper
Expand Down Expand Up @@ -323,7 +363,7 @@

if (response.Error != IntPtr.Zero && response.ErrorLength > 0)
{
result.Error = Marshal.PtrToStringUTF8(response.Error, response.ErrorLength)!;

Check failure on line 366 in sdk/cs/src/Detail/CoreInterop.cs

View workflow job for this annotation

GitHub Actions / build-cs-macos / build

'Marshal' does not contain a definition for 'PtrToStringUTF8'
_logger.LogDebug($"Input:{commandInput ?? "null"}");
_logger.LogDebug($"Command: {commandName} Error: {result.Error}");
}
Expand Down
8 changes: 4 additions & 4 deletions sdk/cs/src/Detail/ICoreInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal record Response
public delegate void CallbackFn(string callbackData);

[StructLayout(LayoutKind.Sequential)]
protected unsafe struct RequestBuffer
public unsafe struct RequestBuffer
{
public nint Command;
public int CommandLength;
Expand All @@ -31,7 +31,7 @@ protected unsafe struct RequestBuffer
}

[StructLayout(LayoutKind.Sequential)]
protected unsafe struct ResponseBuffer
public unsafe struct ResponseBuffer
{
public nint Data;
public int DataLength;
Expand All @@ -42,7 +42,7 @@ protected unsafe struct ResponseBuffer
// native callback function signature
// Return: 0 = continue, 1 = cancel
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
protected unsafe delegate int NativeCallbackFn(nint data, int length, nint userData);
public unsafe delegate int NativeCallbackFn(nint data, int length, nint userData);

Response ExecuteCommand(string commandName, CoreInteropRequest? commandInput = null);
Response ExecuteCommandWithCallback(string commandName, CoreInteropRequest? commandInput, CallbackFn callback);
Expand All @@ -56,7 +56,7 @@ Task<Response> ExecuteCommandWithCallbackAsync(string commandName, CoreInteropRe
// --- Audio streaming session support ---

[StructLayout(LayoutKind.Sequential)]
protected unsafe struct StreamingRequestBuffer
public unsafe struct StreamingRequestBuffer
{
public nint Command;
public int CommandLength;
Expand Down
11 changes: 6 additions & 5 deletions sdk/cs/src/Microsoft.AI.Foundry.Local.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,15 @@
<RepositoryUrl>https://github.com/microsoft/Foundry-Local</RepositoryUrl>
<RepositoryType>git</RepositoryType>

<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<RuntimeIdentifiers>win-x64;win-arm64;linux-x64;linux-arm64;osx-arm64</RuntimeIdentifiers>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why you need to explicitly state the RuntimeIdentifiers in the general case? Do you have a native dependency bound to these?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we have a Foundry Local Core dependency which is a native AOT c# application.


<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<ImplicitUsings>enable</ImplicitUsings>
<IsAotCompatible>True</IsAotCompatible>
<IsTrimmable>True</IsTrimmable>
<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">True</IsAotCompatible>
<Nullable>enable</Nullable>
<WarningsAsErrors />
<LangVersion>latest</LangVersion>

<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
Expand Down Expand Up @@ -88,7 +87,7 @@
<PackageId>Microsoft.AI.Foundry.Local.WinML</PackageId>
<AssemblyName>Microsoft.AI.Foundry.Local.WinML</AssemblyName>
<DefineConstants>$(DefineConstants);IS_WINML</DefineConstants>
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework> <!-- override -->
<TargetFrameworks>net8.0-windows10.0.26100.0</TargetFrameworks>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<!-- TODO: Should we define this here to make it explicit? What minimnum is actually supported? -->
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
Expand Down Expand Up @@ -128,6 +127,8 @@

<PackageReference Include="Betalgo.Ranul.OpenAI" Version="9.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.9" />
<PackageReference Include="PolySharp" Version="1.15.0" PrivateAssets="all" />
<PackageReference Include="System.Threading.Channels" Version="8.0.0" />
<!-- specify PrivateAssets to exclude from nuget dependencies -->
<PackageReference Include="IDisposableAnalyzers" Version="4.0.8" PrivateAssets="all"/>
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net462;net8.0;</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
Expand All @@ -19,7 +19,7 @@
</PropertyGroup>

<PropertyGroup Condition="'$(UseWinML)'=='true'">
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework>
<TargetFrameworks>net8.0-windows10.0.26100.0;</TargetFrameworks>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<WindowsPackageType>None</WindowsPackageType>
</PropertyGroup>
Expand Down
Loading