Repository navigation
Expand file tree
/
Copy pathGitHub.Copilot.SDK.targets
More file actions
267 lines (251 loc) · 24.3 KB
/
Copy pathGitHub.Copilot.SDK.targets
File metadata and controls
267 lines (251 loc) · 24.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
<Project>
<!-- These targets run in consuming projects when they build -->
<!-- CopilotCliVersion is imported from GitHub.Copilot.SDK.props (generated at SDK build time, packaged alongside) -->
<Import Project="$(MSBuildThisFileDirectory)GitHub.Copilot.SDK.props" Condition="'$(CopilotCliVersion)' == '' And Exists('$(MSBuildThisFileDirectory)GitHub.Copilot.SDK.props')" />
<!-- Resolve portable RID from explicit RuntimeIdentifier or build host -->
<PropertyGroup>
<!-- Determine OS: from RID prefix if set, otherwise from build host -->
<_CopilotOs Condition="'$(RuntimeIdentifier)' != '' And $(RuntimeIdentifier.StartsWith('win'))">win</_CopilotOs>
<_CopilotOs Condition="'$(_CopilotOs)' == '' And '$(RuntimeIdentifier)' != '' And $(RuntimeIdentifier.StartsWith('osx'))">osx</_CopilotOs>
<_CopilotOs Condition="'$(_CopilotOs)' == '' And '$(RuntimeIdentifier)' != '' And $(RuntimeIdentifier.StartsWith('maccatalyst'))">osx</_CopilotOs>
<_CopilotOs Condition="'$(_CopilotOs)' == '' And '$(RuntimeIdentifier)' != '' And $(RuntimeIdentifier.StartsWith('linux-musl'))">linux-musl</_CopilotOs>
<_CopilotOs Condition="'$(_CopilotOs)' == '' And '$(RuntimeIdentifier)' != ''">linux</_CopilotOs>
<!-- Determine arch: from RID suffix if set, otherwise from build host -->
<_CopilotArch Condition="'$(RuntimeIdentifier)' != '' And $(RuntimeIdentifier.EndsWith('-x64'))">x64</_CopilotArch>
<_CopilotArch Condition="'$(_CopilotArch)' == '' And '$(RuntimeIdentifier)' != '' And $(RuntimeIdentifier.EndsWith('-arm64'))">arm64</_CopilotArch>
<!-- When no RuntimeIdentifier is set, use the SDK's portable RID for the build host -->
<_CopilotRid Condition="'$(_CopilotOs)' != '' And '$(_CopilotArch)' != ''">$(_CopilotOs)-$(_CopilotArch)</_CopilotRid>
<_CopilotRid Condition="'$(_CopilotRid)' == '' And '$(RuntimeIdentifier)' == ''">$(NETCoreSdkPortableRuntimeIdentifier)</_CopilotRid>
</PropertyGroup>
<!-- Fail if we couldn't determine a portable RID from the given RuntimeIdentifier -->
<Target Name="_ValidateCopilotRid" BeforeTargets="BeforeBuild" Condition="'$(RuntimeIdentifier)' != '' And '$(_CopilotRid)' == ''">
<Error Text="Could not determine a supported portable RID from RuntimeIdentifier '$(RuntimeIdentifier)'. Supported RIDs: win-x64, win-arm64, linux-x64, linux-arm64, linux-musl-x64, linux-musl-arm64, osx-x64, osx-arm64." />
</Target>
<!-- Map RID to the platform suffix used by Copilot CLI release assets -->
<PropertyGroup>
<_CopilotPlatform Condition="'$(_CopilotRid)' == 'win-x64'">win32-x64</_CopilotPlatform>
<_CopilotPlatform Condition="'$(_CopilotRid)' == 'win-arm64'">win32-arm64</_CopilotPlatform>
<_CopilotPlatform Condition="'$(_CopilotRid)' == 'linux-x64'">linux-x64</_CopilotPlatform>
<_CopilotPlatform Condition="'$(_CopilotRid)' == 'linux-arm64'">linux-arm64</_CopilotPlatform>
<_CopilotPlatform Condition="'$(_CopilotRid)' == 'linux-musl-x64'">linuxmusl-x64</_CopilotPlatform>
<_CopilotPlatform Condition="'$(_CopilotRid)' == 'linux-musl-arm64'">linuxmusl-arm64</_CopilotPlatform>
<_CopilotPlatform Condition="'$(_CopilotRid)' == 'osx-x64'">darwin-x64</_CopilotPlatform>
<_CopilotPlatform Condition="'$(_CopilotRid)' == 'osx-arm64'">darwin-arm64</_CopilotPlatform>
<_CopilotBinary Condition="$(_CopilotRid.StartsWith('win-'))">copilot.exe</_CopilotBinary>
<_CopilotBinary Condition="'$(_CopilotBinary)' == ''">copilot</_CopilotBinary>
<_CopilotRuntimeWrapper Condition="$(_CopilotRid.StartsWith('win-'))">copilot-runtime.exe</_CopilotRuntimeWrapper>
<_CopilotRuntimeWrapper Condition="'$(_CopilotRuntimeWrapper)' == ''">copilot-runtime</_CopilotRuntimeWrapper>
<!-- FFI in-process hosting cdylib, renamed from the tarball's napi-style
prebuilds/<platform>/runtime.node to the natural platform shared-library
name (what the Rust cdylib would be called if napi didn't rename it to
.node). The .NET host loads it by absolute path, so the name is ours. -->
<_CopilotRuntimeLib Condition="$(_CopilotRid.StartsWith('win-'))">copilot_runtime.dll</_CopilotRuntimeLib>
<_CopilotRuntimeLib Condition="$(_CopilotRid.StartsWith('osx-'))">libcopilot_runtime.dylib</_CopilotRuntimeLib>
<_CopilotRuntimeLib Condition="'$(_CopilotRuntimeLib)' == ''">libcopilot_runtime.so</_CopilotRuntimeLib>
</PropertyGroup>
<!-- Allow customization of the Copilot CLI GitHub release download base URL.
This is primarily for organizations using private or mirrored release assets.
Set CopilotCliReleaseBaseUrl in your .csproj or Directory.Build.props, for example:
<PropertyGroup>
<CopilotCliReleaseBaseUrl>https://your-mirror.example.com/copilot-cli/releases/download</CopilotCliReleaseBaseUrl>
</PropertyGroup>
COPILOT_CLI_DOWNLOAD_BASE_URL is also honored. -->
<PropertyGroup>
<CopilotCliReleaseBaseUrl Condition="'$(CopilotCliReleaseBaseUrl)' == '' And '$(COPILOT_CLI_DOWNLOAD_BASE_URL)' != ''">$(COPILOT_CLI_DOWNLOAD_BASE_URL)</CopilotCliReleaseBaseUrl>
<CopilotCliReleaseBaseUrl Condition="'$(CopilotCliReleaseBaseUrl)' == ''">https://github.com/github/copilot-cli/releases/download</CopilotCliReleaseBaseUrl>
</PropertyGroup>
<!-- Timeout in seconds for downloading the Copilot CLI tarball.
Override CopilotCliDownloadTimeout in your .csproj or Directory.Build.props if needed.
Default is 600 seconds (10 minutes) to handle slow or unreliable network conditions. -->
<PropertyGroup>
<CopilotCliDownloadTimeout Condition="'$(CopilotCliDownloadTimeout)' == ''">600</CopilotCliDownloadTimeout>
</PropertyGroup>
<!-- Allow consumers to point the targets at a pre-downloaded Copilot CLI binary
(for example, fetched separately from an authenticated release mirror, since
MSBuild's DownloadFile task does not support credentials).
When CopilotCliBinaryPath is set:
- The built-in download target is skipped automatically; no need to also set
CopilotSkipCliDownload=true.
- The copy and register targets still place that binary into the build output
and propagate it to referencing projects.
Example:
<PropertyGroup>
<CopilotCliBinaryPath>$(MSBuildProjectDirectory)\copilot-cli\copilot.exe</CopilotCliBinaryPath>
</PropertyGroup>
-->
<PropertyGroup>
<_CopilotCliBinaryPath Condition="'$(CopilotCliBinaryPath)' != ''">$(CopilotCliBinaryPath)</_CopilotCliBinaryPath>
</PropertyGroup>
<!-- Download and extract the CLI runtime bundle.
Skipped when CopilotCliBinaryPath is set (consumer supplied the binary)
or when CopilotSkipCliDownload=true (consumer opted out entirely). -->
<Target Name="_DownloadCopilotCli" DependsOnTargets="$(_CopilotCliVersionTarget)" BeforeTargets="BeforeBuild" Condition="'$(TargetFramework)' != '' And '$(CopilotCliBinaryPath)' == '' And '$(CopilotSkipCliDownload)' != 'true' And '$(_CopilotPlatform)' != ''">
<Error Condition="'$(CopilotCliVersion)' == ''" Text="CopilotCliVersion is not set. The GitHub.Copilot.SDK.props file may be missing from the NuGet package." />
<!-- Compute paths using version (now available) -->
<PropertyGroup>
<_CopilotCacheDir>$(IntermediateOutputPath)copilot-cli\$(CopilotCliVersion)\$(_CopilotPlatform)</_CopilotCacheDir>
<!-- Release archives do not contain package/copilot[.exe]. Use the runtime
wrapper as the cached compatibility entrypoint and completion marker. -->
<_CopilotCliBinaryPath Condition="'$(_CopilotCliBinaryPath)' == ''">$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\$(_CopilotRuntimeWrapper)</_CopilotCliBinaryPath>
<_CopilotRuntimeNodePath>$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\runtime.node</_CopilotRuntimeNodePath>
<_CopilotRuntimeBundleCompleteMarker>$(_CopilotCacheDir)\.copilot-runtime-complete</_CopilotRuntimeBundleCompleteMarker>
<_CopilotArchivePath>$(_CopilotCacheDir)\copilot.tgz</_CopilotArchivePath>
<_CopilotChecksumPath>$(_CopilotCacheDir)\SHA256SUMS.txt</_CopilotChecksumPath>
<_CopilotAssetName>github-copilot-$(CopilotCliVersion)-$(_CopilotPlatform).tgz</_CopilotAssetName>
<_CopilotAssetNameRegex>$([System.Text.RegularExpressions.Regex]::Escape('$(_CopilotAssetName)'))</_CopilotAssetNameRegex>
<_CopilotNormalizedReleaseBaseUrl>$([System.String]::Copy('$(CopilotCliReleaseBaseUrl)').TrimEnd('/'))</_CopilotNormalizedReleaseBaseUrl>
<_CopilotReleaseUrl>$(_CopilotNormalizedReleaseBaseUrl)/v$(CopilotCliVersion)</_CopilotReleaseUrl>
<_CopilotDownloadUrl>$(_CopilotReleaseUrl)/$(_CopilotAssetName)</_CopilotDownloadUrl>
<_CopilotChecksumsUrl>$(_CopilotReleaseUrl)/SHA256SUMS.txt</_CopilotChecksumsUrl>
<_CopilotRuntimeBundleMissing Condition="!Exists('$(_CopilotCliBinaryPath)') Or !Exists('$(_CopilotRuntimeNodePath)') Or !Exists('$(_CopilotRuntimeBundleCompleteMarker)')">true</_CopilotRuntimeBundleMissing>
<!-- DownloadFile Timeout is in milliseconds; convert from user-facing seconds -->
<_CopilotCliDownloadTimeoutMs>$([System.Convert]::ToInt32($([MSBuild]::Multiply($(CopilotCliDownloadTimeout), 1000))))</_CopilotCliDownloadTimeoutMs>
</PropertyGroup>
<!-- Reacquire incomplete bundles into an empty cache so stale files cannot survive extraction. -->
<RemoveDir Directories="$(_CopilotCacheDir)" Condition="'$(_CopilotRuntimeBundleMissing)' == 'true'" />
<!-- Download if not cached -->
<MakeDir Directories="$(_CopilotCacheDir)" Condition="'$(_CopilotRuntimeBundleMissing)' == 'true'" />
<Message Importance="high" Text="Downloading Copilot CLI $(CopilotCliVersion) for $(_CopilotPlatform)..." Condition="'$(_CopilotRuntimeBundleMissing)' == 'true'" />
<DownloadFile SourceUrl="$(_CopilotChecksumsUrl)" DestinationFolder="$(_CopilotCacheDir)" DestinationFileName="SHA256SUMS.txt"
Timeout="$(_CopilotCliDownloadTimeoutMs)"
Condition="'$(_CopilotRuntimeBundleMissing)' == 'true'" />
<ReadLinesFromFile File="$(_CopilotChecksumPath)" Condition="'$(_CopilotRuntimeBundleMissing)' == 'true'">
<Output TaskParameter="Lines" ItemName="_CopilotChecksumLine" />
</ReadLinesFromFile>
<ItemGroup Condition="'$(_CopilotRuntimeBundleMissing)' == 'true'">
<_CopilotChecksumMatch Include="@(_CopilotChecksumLine)"
Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(Identity)', '^[0-9a-fA-F]{64}[\t ]+\*?$(_CopilotAssetNameRegex)[\t ]*$'))" />
</ItemGroup>
<Error Condition="'$(_CopilotRuntimeBundleMissing)' == 'true' And '@(_CopilotChecksumMatch->Count())' != '1'"
Text="SHA256SUMS.txt from '$(_CopilotChecksumsUrl)' must contain exactly one checksum for $(_CopilotAssetName)." />
<DownloadFile SourceUrl="$(_CopilotDownloadUrl)" DestinationFolder="$(_CopilotCacheDir)" DestinationFileName="copilot.tgz"
Timeout="$(_CopilotCliDownloadTimeoutMs)"
Condition="'$(_CopilotRuntimeBundleMissing)' == 'true'" />
<GetFileHash Files="$(_CopilotArchivePath)" Algorithm="SHA256" Condition="'$(_CopilotRuntimeBundleMissing)' == 'true'">
<Output TaskParameter="Items" ItemName="_CopilotArchiveHash" />
</GetFileHash>
<PropertyGroup Condition="'$(_CopilotRuntimeBundleMissing)' == 'true'">
<_CopilotChecksumLineValue>@(_CopilotChecksumMatch)</_CopilotChecksumLineValue>
<_CopilotArchiveHashValue>@(_CopilotArchiveHash->'%(FileHash)')</_CopilotArchiveHashValue>
<_CopilotExpectedChecksum>$([System.String]::Copy('$(_CopilotChecksumLineValue)').Substring(0, 64).ToUpperInvariant())</_CopilotExpectedChecksum>
<_CopilotActualChecksum>$([System.String]::Copy('$(_CopilotArchiveHashValue)').ToUpperInvariant())</_CopilotActualChecksum>
<_CopilotChecksumMismatch Condition="'$(_CopilotExpectedChecksum)' != '$(_CopilotActualChecksum)'">true</_CopilotChecksumMismatch>
</PropertyGroup>
<Delete Files="$(_CopilotArchivePath)" Condition="'$(_CopilotChecksumMismatch)' == 'true'" />
<Error Condition="'$(_CopilotChecksumMismatch)' == 'true'"
Text="Checksum mismatch for $(_CopilotAssetName): expected $(_CopilotExpectedChecksum), got $(_CopilotActualChecksum)." />
<!-- Extract using tar (use Windows system tar explicitly to avoid Git bash tar issues) -->
<PropertyGroup>
<_TarCommand Condition="$([MSBuild]::IsOSPlatform('Windows'))">$(SystemRoot)\System32\tar.exe</_TarCommand>
<_TarCommand Condition="'$(_TarCommand)' == ''">tar</_TarCommand>
</PropertyGroup>
<Exec Command=""$(_TarCommand)" -xzf "$(_CopilotArchivePath)" --strip-components=1 -C "$(_CopilotCacheDir)""
Condition="'$(_CopilotRuntimeBundleMissing)' == 'true'" />
<Error Condition="!Exists('$(_CopilotCliBinaryPath)')" Text="Failed to extract Copilot runtime wrapper to $(_CopilotCliBinaryPath)" />
<Error Condition="!Exists('$(_CopilotRuntimeNodePath)')" Text="Copilot runtime wrapper at '$(_CopilotCliBinaryPath)' is missing its adjacent runtime.node at '$(_CopilotRuntimeNodePath)'." />
<WriteLinesToFile File="$(_CopilotRuntimeBundleCompleteMarker)" Lines="$(CopilotCliVersion)" Overwrite="true"
Condition="'$(_CopilotRuntimeBundleMissing)' == 'true'" />
</Target>
<!-- Copy the compatibility CLI entrypoint to output and register it for transitive
copy. Release bundles use copilot-runtime[.exe] as the source and retain the
copilot[.exe] output alias; explicit CopilotCliBinaryPath values are unchanged.
Skipped only when CopilotSkipCliDownload=true and no path was supplied. -->
<Target Name="_CopyCopilotCliToOutput" AfterTargets="Build" DependsOnTargets="_DownloadCopilotCli" Condition="'$(TargetFramework)' != '' And ('$(CopilotCliBinaryPath)' != '' Or '$(CopilotSkipCliDownload)' != 'true') And '$(_CopilotPlatform)' != ''">
<PropertyGroup>
<_CopilotCacheDir Condition="'$(_CopilotCacheDir)' == ''">$(IntermediateOutputPath)copilot-cli\$(CopilotCliVersion)\$(_CopilotPlatform)</_CopilotCacheDir>
<_CopilotCliBinaryPath Condition="'$(_CopilotCliBinaryPath)' == ''">$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\$(_CopilotRuntimeWrapper)</_CopilotCliBinaryPath>
<_CopilotOutputDir>$(OutDir)runtimes\$(_CopilotRid)\native</_CopilotOutputDir>
<!-- FFI in-process hosting cdylib. Loaded by the SDK in-proc (not needed
for stdio), so only emitted when the tarball ships it. Copied from the
tarball's prebuilds/<platform>/runtime.node to a flat, natural
shared-library name next to the CLI binary. -->
<_CopilotRuntimeNodePath>$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\runtime.node</_CopilotRuntimeNodePath>
<_CopilotRuntimeWrapperPath Condition="'$(_CopilotRuntimeWrapperPath)' == ''">$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\$(_CopilotRuntimeWrapper)</_CopilotRuntimeWrapperPath>
<_CopilotRuntimeAssetManifest>$(_CopilotOutputDir)\.copilot-runtime-assets</_CopilotRuntimeAssetManifest>
<_CopilotExplicitCliMarker>$(_CopilotOutputDir)\.copilot-explicit-cli</_CopilotExplicitCliMarker>
</PropertyGroup>
<Error Condition="!Exists('$(_CopilotCliBinaryPath)')" Text="Copilot CLI binary not found at '$(_CopilotCliBinaryPath)'. Set CopilotCliBinaryPath to an existing CLI binary for the current RID, or remove CopilotSkipCliDownload=true to let the SDK download it." />
<Error Condition="Exists('$(_CopilotRuntimeWrapperPath)') != Exists('$(_CopilotRuntimeNodePath)')" Text="Incomplete Copilot runtime bundle in '$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)': $(_CopilotRuntimeWrapper) and runtime.node are both required." />
<ReadLinesFromFile File="$(_CopilotRuntimeAssetManifest)" Condition="Exists('$(_CopilotRuntimeAssetManifest)')">
<Output TaskParameter="Lines" ItemName="_CopilotPreviousRuntimeAsset" />
</ReadLinesFromFile>
<ItemGroup>
<_CopilotSafePreviousRuntimeAsset Include="@(_CopilotPreviousRuntimeAsset)"
Condition="!$([System.IO.Path]::IsPathRooted('%(Identity)')) And !$([System.String]::Copy('%(Identity)').Contains('..'))" />
</ItemGroup>
<Delete Files="@(_CopilotSafePreviousRuntimeAsset->'$(_CopilotOutputDir)\%(Identity)')" />
<Delete Files="$(_CopilotRuntimeAssetManifest)" />
<ItemGroup Condition="Exists('$(_CopilotRuntimeWrapperPath)') And Exists('$(_CopilotRuntimeNodePath)')">
<_CopilotRuntimeRootAsset Include="$(_CopilotCacheDir)\**\*"
Exclude="$(_CopilotCacheDir)\.copilot-runtime-complete;$(_CopilotCacheDir)\app.js;$(_CopilotCacheDir)\assets\**\*;$(_CopilotCacheDir)\changelog.json;$(_CopilotCacheDir)\copilot;$(_CopilotCacheDir)\copilot.exe;$(_CopilotCacheDir)\copilot.tgz;$(_CopilotCacheDir)\foundry-local-sdk\**\*;$(_CopilotCacheDir)\index.js;$(_CopilotCacheDir)\LICENSE.md;$(_CopilotCacheDir)\napi-oop-runtime\**\*;$(_CopilotCacheDir)\npm-loader.js;$(_CopilotCacheDir)\package.json;$(_CopilotCacheDir)\prebuilds\**\*;$(_CopilotCacheDir)\pvrecorder\**\*;$(_CopilotCacheDir)\queries\**\*;$(_CopilotCacheDir)\README.md;$(_CopilotCacheDir)\sea-loader.js;$(_CopilotCacheDir)\SHA256SUMS.txt;$(_CopilotCacheDir)\tree-sitter*.wasm;$(_CopilotCacheDir)\voice-*.js;$(_CopilotCacheDir)\webview\**\*" />
<_CopilotRuntimePrebuildAsset Include="$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\**\*"
Exclude="$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\cli-native.node;$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\mediaremote-adapter\**\*;$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\copilot-runtime-bin*" />
</ItemGroup>
<MakeDir Directories="$(_CopilotOutputDir)" />
<WriteLinesToFile File="$(_CopilotExplicitCliMarker)" Lines="explicit" Overwrite="true"
Condition="'$(CopilotCliBinaryPath)' != ''" />
<Delete Files="$(_CopilotExplicitCliMarker)" Condition="'$(CopilotCliBinaryPath)' == ''" />
<Copy SourceFiles="$(_CopilotCliBinaryPath)" DestinationFiles="$(_CopilotOutputDir)\$(_CopilotBinary)" SkipUnchangedFiles="true" />
<Copy SourceFiles="$(_CopilotRuntimeNodePath)" DestinationFiles="$(_CopilotOutputDir)\$(_CopilotRuntimeLib)" SkipUnchangedFiles="true" Condition="Exists('$(_CopilotRuntimeNodePath)')" />
<Copy SourceFiles="@(_CopilotRuntimeRootAsset)"
DestinationFiles="@(_CopilotRuntimeRootAsset->'$(_CopilotOutputDir)\%(RecursiveDir)%(Filename)%(Extension)')"
SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_CopilotRuntimePrebuildAsset)"
DestinationFiles="@(_CopilotRuntimePrebuildAsset->'$(_CopilotOutputDir)\%(RecursiveDir)%(Filename)%(Extension)')"
SkipUnchangedFiles="true" />
<WriteLinesToFile File="$(_CopilotRuntimeAssetManifest)"
Lines="@(_CopilotRuntimeRootAsset->'%(RecursiveDir)%(Filename)%(Extension)');@(_CopilotRuntimePrebuildAsset->'%(RecursiveDir)%(Filename)%(Extension)')"
Overwrite="true"
Condition="'@(_CopilotRuntimeRootAsset)' != '' Or '@(_CopilotRuntimePrebuildAsset)' != ''" />
<Delete Files="$(_CopilotOutputDir)\$(_CopilotRuntimeLib)" Condition="!Exists('$(_CopilotRuntimeNodePath)')" />
</Target>
<!-- Register the compatibility entrypoint as content so it flows through project references
and publish output. Tool packages (PackAsTool) are built from the publish layout, so the
runtime assets must be registered for publish as well as build output.
Same gating semantics as _CopyCopilotCliToOutput. -->
<Target Name="_RegisterCopilotCliForCopy" BeforeTargets="GetCopyToOutputDirectoryItems;GetCopyToPublishDirectoryItems" DependsOnTargets="_DownloadCopilotCli" Condition="'$(TargetFramework)' != '' And ('$(CopilotCliBinaryPath)' != '' Or '$(CopilotSkipCliDownload)' != 'true') And '$(_CopilotPlatform)' != ''">
<PropertyGroup>
<_CopilotCacheDir Condition="'$(_CopilotCacheDir)' == ''">$(IntermediateOutputPath)copilot-cli\$(CopilotCliVersion)\$(_CopilotPlatform)</_CopilotCacheDir>
<_CopilotCliBinaryPath Condition="'$(_CopilotCliBinaryPath)' == ''">$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\$(_CopilotRuntimeWrapper)</_CopilotCliBinaryPath>
<_CopilotRuntimeNodePath>$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\runtime.node</_CopilotRuntimeNodePath>
<_CopilotRuntimeWrapperPath Condition="'$(_CopilotRuntimeWrapperPath)' == ''">$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\$(_CopilotRuntimeWrapper)</_CopilotRuntimeWrapperPath>
<_CopilotExplicitCliMarker>$(_CopilotCacheDir)\.copilot-explicit-cli</_CopilotExplicitCliMarker>
</PropertyGroup>
<Error Condition="!Exists('$(_CopilotCliBinaryPath)')" Text="Copilot CLI binary not found at '$(_CopilotCliBinaryPath)'. Set CopilotCliBinaryPath to an existing CLI binary for the current RID, or remove CopilotSkipCliDownload=true to let the SDK download it." />
<Error Condition="Exists('$(_CopilotRuntimeWrapperPath)') != Exists('$(_CopilotRuntimeNodePath)')" Text="Incomplete Copilot runtime bundle in '$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)': $(_CopilotRuntimeWrapper) and runtime.node are both required." />
<MakeDir Directories="$(_CopilotCacheDir)" Condition="'$(CopilotCliBinaryPath)' != ''" />
<WriteLinesToFile File="$(_CopilotExplicitCliMarker)" Lines="explicit" Overwrite="true"
Condition="'$(CopilotCliBinaryPath)' != ''" />
<ItemGroup>
<_CopilotRuntimeRootAsset Include="$(_CopilotCacheDir)\**\*"
Exclude="$(_CopilotCacheDir)\.copilot-runtime-complete;$(_CopilotCacheDir)\app.js;$(_CopilotCacheDir)\assets\**\*;$(_CopilotCacheDir)\changelog.json;$(_CopilotCacheDir)\copilot;$(_CopilotCacheDir)\copilot.exe;$(_CopilotCacheDir)\copilot.tgz;$(_CopilotCacheDir)\foundry-local-sdk\**\*;$(_CopilotCacheDir)\index.js;$(_CopilotCacheDir)\LICENSE.md;$(_CopilotCacheDir)\napi-oop-runtime\**\*;$(_CopilotCacheDir)\npm-loader.js;$(_CopilotCacheDir)\package.json;$(_CopilotCacheDir)\prebuilds\**\*;$(_CopilotCacheDir)\pvrecorder\**\*;$(_CopilotCacheDir)\queries\**\*;$(_CopilotCacheDir)\README.md;$(_CopilotCacheDir)\sea-loader.js;$(_CopilotCacheDir)\SHA256SUMS.txt;$(_CopilotCacheDir)\tree-sitter*.wasm;$(_CopilotCacheDir)\voice-*.js;$(_CopilotCacheDir)\webview\**\*"
Condition="Exists('$(_CopilotRuntimeWrapperPath)') And Exists('$(_CopilotRuntimeNodePath)')" />
<_CopilotRuntimePrebuildAsset Include="$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\**\*"
Exclude="$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\cli-native.node;$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\mediaremote-adapter\**\*;$(_CopilotCacheDir)\prebuilds\$(_CopilotPlatform)\copilot-runtime-bin*"
Condition="Exists('$(_CopilotRuntimeWrapperPath)') And Exists('$(_CopilotRuntimeNodePath)')" />
<ContentWithTargetPath Include="$(_CopilotCliBinaryPath)"
TargetPath="runtimes\$(_CopilotRid)\native\$(_CopilotBinary)"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest" />
<ContentWithTargetPath Include="$(_CopilotExplicitCliMarker)"
TargetPath="runtimes\$(_CopilotRid)\native\.copilot-explicit-cli"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest"
Condition="'$(CopilotCliBinaryPath)' != ''" />
<!-- FFI cdylib (only when the tarball ships it); see _CopyCopilotCliToOutput. -->
<ContentWithTargetPath Include="$(_CopilotRuntimeNodePath)"
TargetPath="runtimes\$(_CopilotRid)\native\$(_CopilotRuntimeLib)"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest"
Condition="Exists('$(_CopilotRuntimeNodePath)')" />
<ContentWithTargetPath Include="@(_CopilotRuntimeRootAsset)"
TargetPath="runtimes\$(_CopilotRid)\native\%(RecursiveDir)%(Filename)%(Extension)"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest" />
<ContentWithTargetPath Include="@(_CopilotRuntimePrebuildAsset)"
TargetPath="runtimes\$(_CopilotRid)\native\%(RecursiveDir)%(Filename)%(Extension)"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest" />
</ItemGroup>
</Target>
</Project>