From 4ef9c35bb9829f089e4c425582fe95d52c6d3e20 Mon Sep 17 00:00:00 2001 From: Tamir Dresher Date: Wed, 10 Jun 2026 18:44:01 +0300 Subject: [PATCH 1/2] .NET: Make GitHub.Copilot.SDK build targets reach transitive consumers (#6455) Microsoft.Agents.AI.GitHub.Copilot now ships a buildTransitive/ bridge so consumers who only reference this package (the normal use case) get the GitHub.Copilot.SDK's CLI binary-download MSBuild targets executed at build time. Without this, the SDK shipped its targets under build/ which NuGet only auto-imports for projects with a direct PackageReference to the SDK, so consumers of the adapter package got only the managed .dll, no copilot.exe in their output, and a runtime InvalidOperationException on the first RunAsync. The bridge consists of two files under buildTransitive/: * Microsoft.Agents.AI.GitHub.Copilot.props is generated at this package's pack time and pins the SDK version (from PackageVersion items in Directory.Packages.props) into _MicrosoftAgentsAICopilotSdkVersion. * Microsoft.Agents.AI.GitHub.Copilot.targets is static and imports the SDK's own build/GitHub.Copilot.SDK.targets from the NuGet cache using the pinned version. The version-pin condition no-ops gracefully if the resolved SDK differs from what was baked in (e.g. consumer overrides the SDK version directly), so this is purely additive. Verified by packing locally, restoring from a flat local feed, and building a transitive-only consumer (PackageReference to MAF only, no direct SDK ref). copilot.exe lands at bin/{cfg}/{tfm}/runtimes/{rid}/ native/copilot.exe as expected, matching the path the SDK's runtime CopilotClient looks at. Fixes #6455 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Microsoft.Agents.AI.GitHub.Copilot.csproj | 46 +++++++++++++++++++ .../buildTransitive/.gitignore | 3 ++ ...Microsoft.Agents.AI.GitHub.Copilot.targets | 31 +++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/.gitignore create mode 100644 dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/Microsoft.Agents.AI.GitHub.Copilot.targets diff --git a/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/Microsoft.Agents.AI.GitHub.Copilot.csproj b/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/Microsoft.Agents.AI.GitHub.Copilot.csproj index 8b868b5f77..da4b73aedc 100644 --- a/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/Microsoft.Agents.AI.GitHub.Copilot.csproj +++ b/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/Microsoft.Agents.AI.GitHub.Copilot.csproj @@ -32,4 +32,50 @@ Provides Microsoft Agent Framework support for GitHub Copilot SDK. + + + + <_CopilotSdkPackageVersion Include="@(PackageVersion)" Condition="'%(Identity)' == 'GitHub.Copilot.SDK'" /> + + + <_CopilotSdkResolvedVersion>@(_CopilotSdkPackageVersion->'%(Version)') + + + + <_BuildTransitivePropsContent> +<Project> + <PropertyGroup> + <_MicrosoftAgentsAICopilotSdkVersion Condition="'%24(_MicrosoftAgentsAICopilotSdkVersion)' == ''">$(_CopilotSdkResolvedVersion)</_MicrosoftAgentsAICopilotSdkVersion> + </PropertyGroup> +</Project> + + + + + + + + + + + + diff --git a/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/.gitignore b/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/.gitignore new file mode 100644 index 0000000000..87bc8ad53e --- /dev/null +++ b/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/.gitignore @@ -0,0 +1,3 @@ +# Auto-generated at pack time by _GenerateBuildTransitiveProps in the csproj. +Microsoft.Agents.AI.GitHub.Copilot.props + diff --git a/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/Microsoft.Agents.AI.GitHub.Copilot.targets b/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/Microsoft.Agents.AI.GitHub.Copilot.targets new file mode 100644 index 0000000000..9ea8d5b260 --- /dev/null +++ b/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/Microsoft.Agents.AI.GitHub.Copilot.targets @@ -0,0 +1,31 @@ + + + + <_MicrosoftAgentsAICopilotSdkBuildDir Condition="'$(_MicrosoftAgentsAICopilotSdkVersion)' != ''">$([System.IO.Path]::Combine('$(NuGetPackageRoot)', 'github.copilot.sdk', '$(_MicrosoftAgentsAICopilotSdkVersion)', 'build')) + + + + From 4e60b321544bbcc411fdc57d789baab693cf97ff Mon Sep 17 00:00:00 2001 From: Tamir Dresher Date: Wed, 10 Jun 2026 18:55:52 +0300 Subject: [PATCH 2/2] Address Copilot review feedback (#6457) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - buildTransitive/.targets: compute the full SDK targets path with a single Path.Combine call into one property (_MicrosoftAgentsAICopilotSdkTargetsPath), used in both Project= and Exists() — no more split between Path.Combine for the directory and inline / separator for the file name. - Split the version-defaulting Condition between the two files: the generated .props now just bakes the packaged SDK version into a dedicated property (_MicrosoftAgentsAICopilotSdkPackagedVersion), and the static .targets file is the single place that defaults _MicrosoftAgentsAICopilotSdkVersion to it. Removes the need for any MSBuild escape gymnastics in the pack-time string construction, and keeps the consumer override path the same. - _GenerateBuildTransitiveProps now hangs off public BeforeTargets (Build, Pack) in addition to _GetPackageFiles, so the file is generated even without a full pack, and we're not solely dependent on an underscore-prefixed internal target. The items live in a top-level ItemGroup so they are collected at evaluation time instead of being added from inside the Target. End-to-end retested with a transitive-only consumer (PackageReference to MAF only, no direct GitHub.Copilot.SDK ref): copilot.exe lands at bin/Debug/net10.0/runtimes/win-x64/native/copilot.exe (141.8 MB) as before. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Microsoft.Agents.AI.GitHub.Copilot.csproj | 36 ++++++++++--------- ...Microsoft.Agents.AI.GitHub.Copilot.targets | 17 +++++---- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/Microsoft.Agents.AI.GitHub.Copilot.csproj b/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/Microsoft.Agents.AI.GitHub.Copilot.csproj index da4b73aedc..34d1ed8130 100644 --- a/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/Microsoft.Agents.AI.GitHub.Copilot.csproj +++ b/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/Microsoft.Agents.AI.GitHub.Copilot.csproj @@ -42,12 +42,21 @@ adapter .dll, no copilot.exe in their output, and a runtime failure at the first RunAsync call. - The targets file in buildTransitive/ is static; the .props file is generated - here at pack time so the SDK version we were built against is baked in and - consumers don't have to discover it from the nuspec. See the targets file - for the full design rationale. + The targets file in buildTransitive/ is static and contains all of the + Condition / Import logic. The .props file generated here just bakes the + SDK version this package was built against into a dedicated property + ($(_MicrosoftAgentsAICopilotSdkPackagedVersion)) — no Condition or + inner $(...) reference in the generated file, so we avoid any MSBuild + escape gymnastics during string construction. The static targets file + then defaults $(_MicrosoftAgentsAICopilotSdkVersion) to the packaged + version unless the consumer overrides it. --> - + + + + + + <_CopilotSdkPackageVersion Include="@(PackageVersion)" Condition="'%(Identity)' == 'GitHub.Copilot.SDK'" /> @@ -58,24 +67,17 @@ Text="Could not resolve GitHub.Copilot.SDK version from PackageVersion items. Ensure the central package version is declared in Directory.Packages.props." /> <_BuildTransitivePropsContent> -<Project> - <PropertyGroup> - <_MicrosoftAgentsAICopilotSdkVersion Condition="'%24(_MicrosoftAgentsAICopilotSdkVersion)' == ''">$(_CopilotSdkResolvedVersion)</_MicrosoftAgentsAICopilotSdkVersion> - </PropertyGroup> -</Project> + + + <_MicrosoftAgentsAICopilotSdkPackagedVersion>$(_CopilotSdkResolvedVersion) + +]]> - - - - - - - diff --git a/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/Microsoft.Agents.AI.GitHub.Copilot.targets b/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/Microsoft.Agents.AI.GitHub.Copilot.targets index 9ea8d5b260..04a777550f 100644 --- a/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/Microsoft.Agents.AI.GitHub.Copilot.targets +++ b/dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/buildTransitive/Microsoft.Agents.AI.GitHub.Copilot.targets @@ -17,15 +17,18 @@ consumer's output as expected. The companion .props file is generated at this package's pack time and sets - $(_MicrosoftAgentsAICopilotSdkVersion) to the SDK version this package was - built against. Consumers may opt out via $(CopilotSkipCliDownload)=true (also - honored by the SDK's own targets) or override the SDK version path by - setting $(_MicrosoftAgentsAICopilotSdkVersion) before this file is imported. + $(_MicrosoftAgentsAICopilotSdkPackagedVersion) to the SDK version this + package was built against. The Condition below uses that as the default for + $(_MicrosoftAgentsAICopilotSdkVersion), so consumers may override the SDK + version path by setting $(_MicrosoftAgentsAICopilotSdkVersion) before this + file is imported. Consumers may also opt out of the binary download via the + SDK's own $(CopilotSkipCliDownload)=true, which the SDK targets honor. --> - <_MicrosoftAgentsAICopilotSdkBuildDir Condition="'$(_MicrosoftAgentsAICopilotSdkVersion)' != ''">$([System.IO.Path]::Combine('$(NuGetPackageRoot)', 'github.copilot.sdk', '$(_MicrosoftAgentsAICopilotSdkVersion)', 'build')) + <_MicrosoftAgentsAICopilotSdkVersion Condition="'$(_MicrosoftAgentsAICopilotSdkVersion)' == ''">$(_MicrosoftAgentsAICopilotSdkPackagedVersion) + <_MicrosoftAgentsAICopilotSdkTargetsPath Condition="'$(_MicrosoftAgentsAICopilotSdkVersion)' != ''">$([System.IO.Path]::Combine('$(NuGetPackageRoot)', 'github.copilot.sdk', '$(_MicrosoftAgentsAICopilotSdkVersion)', 'build', 'GitHub.Copilot.SDK.targets')) - +