diff --git a/.github/workflows/build-cs-steps.yml b/.github/workflows/build-cs-steps.yml
index a77b9d5..20d4886 100644
--- a/.github/workflows/build-cs-steps.yml
+++ b/.github/workflows/build-cs-steps.yml
@@ -30,23 +30,21 @@ jobs:
with:
clean: true
- # adapted from https://github.com/actions/setup-dotnet?tab=readme-ov-file#azure-artifacts
- # saves auth credentials to ../nuget.config
- name: Setup .NET 9 SDK
uses: actions/setup-dotnet@v5
with:
dotnet-version: '9.0.x'
- source-url: https://pkgs.dev.azure.com/microsoft/windows.ai.toolkit/_packaging/Neutron/nuget/v3/index.json
env:
NUGET_AUTH_TOKEN: ${{ secrets.AZURE_DEVOPS_PAT }}
+ # /p:FoundryLocalCoreVersion="*-*" to always use nightly version of Foundry Local Core
- name: Restore dependencies
run: |
- dotnet restore sdk_v2\cs\src\Microsoft.AI.Foundry.Local.csproj /p:UseWinML=${{ inputs.useWinML }} --configfile ../nuget.config
+ dotnet restore sdk_v2\cs\src\Microsoft.AI.Foundry.Local.csproj /p:UseWinML=${{ inputs.useWinML }} /p:FoundryLocalCoreVersion="*-*" --configfile sdk_v2\cs\NuGet.config
- name: Build solution
run: |
- dotnet build sdk_v2\cs\src\Microsoft.AI.Foundry.Local.csproj --configfile ../nuget.config --no-restore --configuration ${{ inputs.buildConfiguration }} /p:UseWinML=${{ inputs.useWinML }}
+ dotnet build sdk_v2\cs\src\Microsoft.AI.Foundry.Local.csproj --no-restore --configuration ${{ inputs.buildConfiguration }} /p:UseWinML=${{ inputs.useWinML }} /p:FoundryLocalCoreVersion="*-*"
# need to use direct git commands to clone from Azure DevOps instead of actions/checkout
- name: Checkout test-data-shared from Azure DevOps
@@ -80,7 +78,7 @@ jobs:
- name: Run Foundry Local Core tests
run: |
- dotnet test sdk_v2\cs\test\FoundryLocal.Tests\Microsoft.AI.Foundry.Local.Tests.csproj --verbosity normal /p:UseWinML=${{ inputs.useWinML }}
+ dotnet test sdk_v2\cs\test\FoundryLocal.Tests\Microsoft.AI.Foundry.Local.Tests.csproj --verbosity normal /p:UseWinML=${{ inputs.useWinML }} /p:FoundryLocalCoreVersion="*-*"
- name: Pack NuGet package
shell: pwsh
@@ -90,14 +88,21 @@ jobs:
$version = "${{ inputs.version }}"
$config = "${{ inputs.buildConfiguration }}"
$useWinML = "${{ inputs.useWinML }}"
+ # $coreVersion = "${{ env.FOUNDRY_CORE_VERSION }}"
+
+ # Always mark as prerelease since we use nightly core
+ if (-not $version.Contains("dev")) {
+ $version = "$version-dev"
+ }
Write-Host "Packing project: $projectPath"
Write-Host "Output directory: $outputDir"
Write-Host "Version: $version"
Write-Host "Configuration: $config"
Write-Host "UseWinML: $useWinML"
+ # Write-Host "FoundryLocalCoreVersion: $coreVersion"
- & dotnet pack $projectPath --no-build --configuration $config --output $outputDir /p:PackageVersion=$version /p:UseWinML=$useWinML /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg --verbosity normal
+ & dotnet pack $projectPath --no-build --configuration $config --output $outputDir /p:PackageVersion=$version /p:UseWinML=$useWinML /p:FoundryLocalCoreVersion="*-*" /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg --verbosity normal
if ($LASTEXITCODE -ne 0) {
Write-Error "dotnet pack failed with exit code $LASTEXITCODE"
diff --git a/.github/workflows/build-js-steps.yml b/.github/workflows/build-js-steps.yml
index 37c3e06..cafd7b5 100644
--- a/.github/workflows/build-js-steps.yml
+++ b/.github/workflows/build-js-steps.yml
@@ -34,7 +34,6 @@ jobs:
uses: actions/setup-dotnet@v5
with:
dotnet-version: '9.0.x'
- source-url: https://pkgs.dev.azure.com/microsoft/windows.ai.toolkit/_packaging/Neutron/nuget/v3/index.json
env:
NUGET_AUTH_TOKEN: ${{ secrets.AZURE_DEVOPS_PAT }}
@@ -89,7 +88,7 @@ jobs:
- name: npm install (Standard)
if: ${{ inputs.useWinML == false }}
working-directory: sdk_v2\js
- run: npm install
+ run: npm install --nightly
# Verify that installing new packages doesn't strip custom native binary folders
- name: npm install openai (verify persistence)
diff --git a/sdk_v2/cs/NuGet.config b/sdk_v2/cs/NuGet.config
new file mode 100644
index 0000000..cf09cc0
--- /dev/null
+++ b/sdk_v2/cs/NuGet.config
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/sdk_v2/cs/src/Microsoft.AI.Foundry.Local.csproj b/sdk_v2/cs/src/Microsoft.AI.Foundry.Local.csproj
index c292ef8..979994a 100644
--- a/sdk_v2/cs/src/Microsoft.AI.Foundry.Local.csproj
+++ b/sdk_v2/cs/src/Microsoft.AI.Foundry.Local.csproj
@@ -59,6 +59,7 @@
+
@@ -67,6 +68,13 @@
+
+
+
+
+
+
@@ -87,6 +95,12 @@
$(NoWarn);CsWinRT1028
+
+
+
+ 0.8.1.0
+
+
True
@@ -96,9 +110,9 @@
+ Include="Microsoft.AI.Foundry.Local.Core.WinML" Version="$(FoundryLocalCoreVersion)" />
+ Include="Microsoft.AI.Foundry.Local.Core" Version="$(FoundryLocalCoreVersion)" />
diff --git a/sdk_v2/js/script/install.cjs b/sdk_v2/js/script/install.cjs
index 2208161..d175798 100644
--- a/sdk_v2/js/script/install.cjs
+++ b/sdk_v2/js/script/install.cjs
@@ -39,28 +39,35 @@ const REQUIRED_FILES = [
// When you run npm install --winml, npm does not pass --winml as a command-line argument to your script.
// Instead, it sets an environment variable named npm_config_winml to 'true'.
const useWinML = process.env.npm_config_winml === 'true';
+const useNightly = process.env.npm_config_nightly === 'true';
console.log(`[foundry-local] WinML enabled: ${useWinML}`);
+console.log(`[foundry-local] Nightly enabled: ${useNightly}`);
const NUGET_FEED = 'https://api.nuget.org/v3/index.json';
const ORT_FEED = 'https://pkgs.dev.azure.com/aiinfra/PublicPackages/_packaging/ORT/nuget/v3/index.json';
+const ORT_NIGHTLY_FEED = 'https://pkgs.dev.azure.com/aiinfra/PublicPackages/_packaging/ORT-Nightly/nuget/v3/index.json';
+
+// If nightly is requested, pull Core/GenAI from the ORT-Nightly feed where nightly builds are published.
+// Otherwise use the standard NuGet.org feed.
+const CORE_FEED = useNightly ? ORT_NIGHTLY_FEED : NUGET_FEED;
const ARTIFACTS = [
{
name: useWinML ? 'Microsoft.AI.Foundry.Local.Core.WinML' : 'Microsoft.AI.Foundry.Local.Core',
- version: '0.8.2.2',
+ version: useNightly ? undefined : '0.8.2.2', // Set later using resolveLatestVersion if undefined
files: ['Microsoft.AI.Foundry.Local.Core'],
- feed: NUGET_FEED
+ feed: CORE_FEED
},
{
name: 'Microsoft.ML.OnnxRuntime.Foundry',
- version: '1.23.2',
+ version: '1.23.2.1', // Hardcoded stable version
files: ['onnxruntime'],
- feed: ORT_FEED
+ feed: ORT_NIGHTLY_FEED
},
{
name: useWinML ? 'Microsoft.ML.OnnxRuntimeGenAI.WinML' : 'Microsoft.ML.OnnxRuntimeGenAI.Foundry',
- version: '0.11.4',
+ version: '0.11.2', // Hardcoded stable version
files: ['onnxruntime-genai'],
feed: NUGET_FEED
}
@@ -68,8 +75,13 @@ const ARTIFACTS = [
// Check if already installed
if (fs.existsSync(BIN_DIR) && REQUIRED_FILES.every(f => fs.existsSync(path.join(BIN_DIR, f)))) {
- console.log(`[foundry-local] Native libraries already installed.`);
- process.exit(0);
+ if (useNightly) {
+ console.log(`[foundry-local] Nightly requested. Forcing reinstall...`);
+ fs.rmSync(BIN_DIR, { recursive: true, force: true });
+ } else {
+ console.log(`[foundry-local] Native libraries already installed.`);
+ process.exit(0);
+ }
}
console.log(`[foundry-local] Installing native libraries for ${RID}...`);
@@ -143,7 +155,7 @@ async function downloadFile(url, dest) {
// Map to cache service index resources
const serviceIndexCache = new Map();
-async function resolvePackageRawUrl(feedUrl, packageName, version) {
+async function getBaseAddress(feedUrl) {
// 1. Get Service Index
if (!serviceIndexCache.has(feedUrl)) {
const index = await downloadJson(feedUrl);
@@ -162,7 +174,36 @@ async function resolvePackageRawUrl(feedUrl, packageName, version) {
const baseAddress = baseAddressRes['@id'];
// Ensure trailing slash
- const properBase = baseAddress.endsWith('/') ? baseAddress : baseAddress + '/';
+ return baseAddress.endsWith('/') ? baseAddress : baseAddress + '/';
+}
+
+async function resolveLatestVersion(feedUrl, packageName) {
+ const baseAddress = await getBaseAddress(feedUrl);
+ const nameLower = packageName.toLowerCase();
+
+ // Fetch version list: {baseAddress}/{lower_id}/index.json
+ const versionsUrl = `${baseAddress}${nameLower}/index.json`;
+ try {
+ const versionData = await downloadJson(versionsUrl);
+ const versions = versionData.versions || [];
+
+ if (versions.length === 0) {
+ throw new Error('No versions found');
+ }
+
+ // Sort descending to prioritize latest date-based versions (e.g. 0.9.0-dev.YYYYMMDD...)
+ versions.sort((a, b) => b.localeCompare(a));
+
+ const latestVersion = versions[0];
+ console.log(`[foundry-local] Installing latest version of Foundry Local Core: ${latestVersion}`);
+ return latestVersion;
+ } catch (e) {
+ throw new Error(`Failed to fetch versions for ${packageName} from ${versionsUrl}: ${e.message}`);
+ }
+}
+
+async function resolvePackageRawUrl(feedUrl, packageName, version) {
+ const properBase = await getBaseAddress(feedUrl);
// 3. Construct .nupkg URL (lowercase is standard for V3)
const nameLower = packageName.toLowerCase();
@@ -173,9 +214,15 @@ async function resolvePackageRawUrl(feedUrl, packageName, version) {
async function installPackage(artifact, tempDir) {
const pkgName = artifact.name;
- const pkgVer = artifact.version;
const feedUrl = artifact.feed;
+ // Resolve version if not specified
+ let pkgVer = artifact.version;
+ if (!pkgVer) {
+ console.log(` Resolving latest version for ${pkgName}...`);
+ pkgVer = await resolveLatestVersion(feedUrl, pkgName);
+ }
+
console.log(` Resolving ${pkgName} ${pkgVer}...`);
const downloadUrl = await resolvePackageRawUrl(feedUrl, pkgName, pkgVer);