From a5e8f9b43230675c86dcb7c3ff5021914537f8be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 08:56:01 +0100 Subject: [PATCH 01/33] .Net: Bump form-data from 4.0.5 to 4.0.6 in /dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend (#14082) Bumps [form-data](https://github.com/form-data/form-data) from 4.0.5 to 4.0.6.
Changelog

Sourced from form-data's changelog.

v4.0.6 - 2026-06-12

Commits

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=form-data&package-manager=npm_and_yarn&previous-version=4.0.5&new-version=4.0.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/semantic-kernel/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../package-lock.json | 38 +++++-------------- .../yarn.lock | 21 ++++++---- 2 files changed, 24 insertions(+), 35 deletions(-) diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json index 0db75aee57aa..2509b92cd78d 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json @@ -80,7 +80,6 @@ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -971,7 +970,6 @@ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", "license": "MIT", - "peer": true, "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.9" @@ -1316,7 +1314,6 @@ "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.72.7.tgz", "integrity": "sha512-tuC8ZMBQicF4p+f9MJv9cVYZUSktQVreAGJq/YJxQ0Ts1mO2rnAuIBkBFlgjnjyebDiAO1FoAAz/wW99hrIh6A==", "license": "MIT", - "peer": true, "dependencies": { "@fluentui/react-accordion": "^9.8.14", "@fluentui/react-alert": "9.0.0-beta.129", @@ -1506,7 +1503,6 @@ "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.315.tgz", "integrity": "sha512-IITWAQGgU7I32eHPDHi+TUCUF6malP27wZLUV3bqjGVF/x/lfxvTIx8yqv/cxuwF3+ITGFDpl+278ZYJtOI7ww==", "license": "MIT", - "peer": true, "dependencies": { "@griffel/react": "^1.0.0", "tslib": "^2.1.0" @@ -3236,7 +3232,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -3246,7 +3241,6 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -3293,7 +3287,6 @@ "integrity": "sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.29.1", "@typescript-eslint/types": "8.29.1", @@ -3521,7 +3514,6 @@ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3657,7 +3649,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -3952,8 +3943,7 @@ "version": "8.6.0", "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/embla-carousel-autoplay": { "version": "8.6.0", @@ -4088,7 +4078,6 @@ "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -4451,16 +4440,16 @@ } }, "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -4620,9 +4609,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -5917,7 +5906,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -5927,7 +5915,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -6135,8 +6122,7 @@ "version": "0.27.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", @@ -6315,7 +6301,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6415,7 +6400,6 @@ "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6650,7 +6634,6 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -6744,7 +6727,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock index 2b3d7c38ff51..924eeb75abd4 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock @@ -2457,15 +2457,15 @@ follow-redirects@^1.15.6: integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== form-data@^4.0.4: - version "4.0.5" - resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz" - integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w== + version "4.0.6" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.6.tgz#28e864e1b786dbebb68db1f452f9635278665827" + integrity sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" es-set-tostringtag "^2.1.0" - hasown "^2.0.2" - mime-types "^2.1.12" + hasown "^2.0.4" + mime-types "^2.1.35" fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" @@ -2569,6 +2569,13 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" +hasown@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.4.tgz#8c62d8cb90beb2aad5d0a5b67581ad9854c3f003" + integrity sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A== + dependencies: + function-bind "^1.1.2" + hast-util-to-jsx-runtime@^2.0.0: version "2.3.6" resolved "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz" @@ -3078,9 +3085,9 @@ mime-db@1.52.0: resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12: +mime-types@^2.1.35: version "2.1.35" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" From 56422ada8aa95702aab5c969805c3395dd2f5022 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 08:58:56 +0100 Subject: [PATCH 02/33] .Net: Bump follow-redirects from 1.15.11 to 1.16.0 in /dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend (#13877) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.11 to 1.16.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=follow-redirects&package-manager=npm_and_yarn&previous-version=1.15.11&new-version=1.16.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/semantic-kernel/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../package-lock.json | 6 +++--- .../ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json index 2509b92cd78d..a2c8a6da6e7b 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json @@ -4420,9 +4420,9 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock index 924eeb75abd4..c5946becc005 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock @@ -2452,9 +2452,9 @@ flatted@^3.2.9: integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== follow-redirects@^1.15.6: - version "1.15.11" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz" - integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== + version "1.16.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" + integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== form-data@^4.0.4: version "4.0.6" From 1ad0b7501bd9c8f8dfbafb7c1aa69fab1ba4cd28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 09:07:56 +0100 Subject: [PATCH 03/33] Bump Aspire.Hosting.AppHost from 13.0.0 to 13.3.0 (#13995) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated [Aspire.Hosting.AppHost](https://github.com/microsoft/aspire) from 13.0.0 to 13.3.0.
Release notes _Sourced from [Aspire.Hosting.AppHost's releases](https://github.com/microsoft/aspire/releases)._ ## 13.3.0 # Aspire 13.3.0 Aspire 13.3 is here! 🚀 This release is packed with new ways to deploy, debug, and build distributed apps — including `aspire destroy`, browser telemetry in the dashboard, Kubernetes deployment, first-class JavaScript publishing, and major TypeScript AppHost parity improvements. ## Highlights - 🧹 **Clean teardown** — New **`aspire destroy`** tears down Azure, Kubernetes, and Docker Compose deployments, and pipeline summaries make deploy/publish/destroy runs easier to follow. - 🔍 **Frontend telemetry** — **Aspire.Hosting.Browsers** captures browser console logs, network requests, and screenshots right in the Aspire dashboard. - ☸️ **Kubernetes deploy preview** — **`aspire deploy`** can now generate Helm-based Kubernetes deployments, with first-class Ingress and Gateway API routing. - 🟨 **JavaScript publishing** — New **`PublishAs*`** methods support static sites, Node servers, npm-script apps, Next.js, Vite, Bun, Yarn, and pnpm. - 🌐 **TypeScript AppHost parity** — Unified `withEnvironment`, Docker Compose hooks, endpoint expressions, Azure Container Apps domains, and more close the gap with C# AppHosts. - 🛠️ **CLI upgrades** — Run the standalone dashboard with **`aspire dashboard run`**, install the CLI as a NativeAOT `dotnet tool`, and search API docs from the terminal. - ☁️ **Azure goodness** — New Azure Front Door, Network Security Perimeter, AKS, private endpoint, and Foundry Prompt Agent support. - 🐳 **Better containers** — The Aspire container tunnel is now enabled by default for consistent host connectivity across Docker Desktop, Docker Engine, and Podman. ## ⚠️ Breaking changes Notable breaking changes include `--log-level` becoming `--pipeline-log-level`, the dashboard MCP server being replaced by `aspire agent init`, `dotnet new aspire-py-starter` moving to `aspire new aspire-py-starter`, and several API shape updates across AKS, Foundry, JavaScript diagnostics, and TypeScript AppHost helpers. See the full list in the [Aspire 13.3 breaking changes](https://aspire.dev/whats-new/aspire-13-3/#%EF%B8%8F-breaking-changes). ## 📖 Learn more For the full details, examples, migration guidance, and everything new in this release, check out [What's new in Aspire 13.3](https://aspire.dev/whats-new/aspire-13-3/). Thank you to all the community contributors who helped make Aspire 13.3 possible! 💜 ## 13.2.4 # Aspire 13.2.4 ## What's New in Aspire 13.2.4 Patch release addressing a security advisory in OpenTelemetry dependencies. ### 🐛 Fixes - 🔒 Bumped OpenTelemetry dependencies to address CVE-2026-40894 (#​16420) ### 🏷️ Housekeeping - 🚀 Bumped branding to 13.2.4 (#​16436) ## 13.2.3 # What's New in Aspire 13.2.3 Patch release focused on CLI packaging, signing, and reliability fixes. ## 🐛 Fixes - 🛑 aspire stop now properly cleans up application containers on Windows (#​16123) - 🔐 Fixed macOS signing, permissions, and certificate trust with improved CI verification (#​16053) - ✍️ Fixed signing for the aspire-managed bundle payload (#​16211) - 🎭 Fixed Playwright CLI provenance verification for the new tag format (#​16134) - 🧭 Updated service discovery environment variables (#​16223) ## 🔧 Improvements - 📊 Removed telemetry API data limits and refactored URL builders (#​16023) - ⏱️ Increased native build + sign timeout to 60 minutes for reliability (#​16212) ## 🏷️ Housekeeping - 🔖 Bumped branding to 13.2.3 (#​16181) - 🧪 Temporarily disabled Verify CLI archive step on Windows while investigating (#​16276, #​16285) ## 13.2.2 This is a servicing release focused on bug fixes and platform improvements. 🐛 Bug Fixes - Fix SqlClient runtime asset layout on Unix — Resolved an issue where Microsoft.Data.SqlClient failed to load correctly on macOS and Linux due to incorrect NuGet asset layout (#​15709) - Fix IDE execution regressions for Azure Functions and class library projects — Backported fixes for 13.2 regressions impacting IDE-based execution (#​15714) - Fix NpmRunner multi-version output parsing — npm view returning multiple versions no longer breaks version resolution; also bumps @​playwright/cli to >=0.1.3 (#​15746) - Skip name validation for internal resources — ProjectRebuilderResource, installer, and venv creator resources no longer fail the 64-char name limit since they're never deployed (#​15726, fixes #​15693) 🔒 Security & Certificates - Use ASP.NET Core dev cert for DCP — Avoids ephemeral certificate trust issues by using the standard ASP.NET Core developer certificate (#​15718) - Cache PFX dev certs on Windows and Linux — Prevents binary-level changes between runs for persistent container scenarios (#​15774) 🏗️ Infrastructure & Platform - ARM64 CLI support — Added win-arm64 and linux-arm64 to the native CLI archive build matrix (#​15599) - Update DCP to 0.22.11 (#​15713) 💻 CLI Improvements - Show anonymous dashboard URLs in aspire ps — The dashboard URL is now displayed even when running without authentication (#​15731 ## 13.2.1 🐛 Bug Fixes - 🖥️ CLI bundles for ARM & musl — win-arm64, linux-arm64, and linux-musl-x64 bundles now correctly include DCP instead of silently producing broken installs (#​15529) - ⚡ aspire new in VS Code — Fixed a race where the workspace switch severed the CLI terminal before the agent init prompt could complete (#​15553) - 🔗 Dashboard resource URLs — The describe command no longer produces broken dashboard links with a stray /login?t=... in the path (#​15495) - 🌍 Guest AppHost env vars — Launch profile environment variables are now correctly forwarded to guest AppHosts (#​15637) - 📦 Legacy settings migration — .aspire/settings.json → aspire.config.json migration was silently skipped in some scenarios; now works reliably (#​15526) - 🔧 TypeScript AppHost restore — Fixed config resolution during TS AppHost restore (#​15625) - 🎭 Playwright CLI on Windows — aspire agent init now correctly installs playwright-cli on Windows (#​15559) - 📌 Emulator stability — Pinned Kusto emulator image and improved Cosmos DB emulator reliability (#​15504) ✨ Improvements - 🏗️ Brownfield TypeScript aspire init — Running aspire init in existing JS/TS projects now smartly merges package.json — scripts, dependencies, and engines — with semver-aware conflict handling (#​15123) - 🎯 Endpoint filtering — New ExcludeReferenceEndpoint property lets you filter specific endpoints from WithReference (#​15586) - 🌐 More polyglot ATS APIs — Exported additional hosting APIs for TypeScript and Go AppHost authoring (#​15557) - 🔍 Short trace ID support — The dashboard now resolves short trace IDs in addition to full-length ones (#​15613) - ⚠️ Aspire.Hosting.NodeJs deprecated — Use Aspire.Hosting.JavaScript instead; the old package no longer appears in aspire add (#​15686) ## 13.2.0 # Aspire 13.2 Aspire 13.2 brings major CLI enhancements, a new TypeScript AppHost (preview), dashboard data export/import, Microsoft Foundry integration, and multi-language improvements — all focused on making local development more streamlined for developers and AI coding agents alike. ## Highlights - 🛠️ CLI overhaul — New commands including **aspire start/stop/ps** for detached mode, **aspire describe** for resource monitoring, **aspire doctor** for environment diagnostics, **aspire secret** for managing user secrets, **aspire docs** for browsing documentation from the terminal, and **aspire agent** (renamed from **aspire mcp**) for AI agent integration. - 🌐 TypeScript AppHost (preview) — Write your apphost in TypeScript with **createBuilder()**, using the same app model concepts as C#. Full VS Code extension support included. - 🧩 VS Code extension — Dedicated Aspire Activity Bar panel with live resource state, inline CodeLens with health status and actions, gutter decorations, and a new Getting Started walkthrough. - 📊 Dashboard improvements — Bulk telemetry export/import, export environment variables as **.env** files, a new telemetry HTTP API, set parameters directly from the dashboard, and improved resource graph layout. - 🤖 Microsoft Foundry — Replaces Azure AI Foundry integration with broader **Aspire.Hosting.Foundry** support including hosted agents and model deployments. - 🔒 Azure Virtual Network & Private Endpoints — New **Aspire.Hosting.Azure.Network** integration for defining VNets, subnets, NAT gateways, NSGs, and private endpoints directly in your apphost. - 🐳 Docker Compose publishing — Generate docker-compose.yaml from your app model with **AddDockerComposeEnvironment.** - 📦 New integrations — Azure Data Lake Storage, MongoDB EF Core (**Aspire.MongoDB.EntityFrameworkCore**), Bun support for JS resources, and Certbot for automated SSL certificates. - ⚡ App model — **WithMcpServer** for declaring MCP endpoints, **rebuild** command for project resources, contextual endpoint resolution, and improved secret/certificate handling. ## ⚠️ Breaking changes Notable breaking changes include service discovery env vars now using endpoint scheme instead of name, aspire.config.json replacing split config files, AIFoundry → Foundry rename, WithSecretBuildArg → WithBuildSecret, and updated default Azure credential behavior. [See the full list of breaking changes](https://aspire.dev/whats-new/aspire-13-2/#%EF%B8%8F-breaking-changes). ## 📖 Learn more For the full details on everything in this release, check out the [What's new in Aspire 13.2](https://aspire.dev/whats-new/aspire-13-2/) documentation. Thank you to all the community contributors who helped make this release happen! 💜 ## 13.1.3 ## What's Changed * [release/13.1] Add installer publishing updates for 13.1.3 by @​radical in https://github.com/dotnet/aspire/pull/15158 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.1.2...v13.1.3 ## 13.1.2 ## What's Changed * Bump patch version from 13.1.1 to 13.1.2 by @​Copilot in https://github.com/dotnet/aspire/pull/14699 * [release/13.1] Fix template version parsing for .NET 10.0 SDK separator change by @​JamesNK in https://github.com/dotnet/aspire/pull/14698 * Update pipeline images to non-deprecated pools by @​joperezr in https://github.com/dotnet/aspire/pull/14707 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.1.1...v13.1.2 ## 13.1.1 ## What's Changed * [release/13.1] Ensure WithHostHttpsPort works when chained inline by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13678 * [release/13.1] Escape backslashes in path string to discovered vite config by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13822 * [release/13.1] [Testing] Fixing bugs for sticky slot app settings by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13810 * [release/13.1] Fix AzureBicepResource file-not-found error when using templateFile with AzurePublishingContext by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/14018 * [release/13.1] Filter dev certs without X509SubjectKeyIdentifierExtension when any cert has it by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13676 * [release/13.1] Fix Aspire.ProjectTemplates build failure from command line length limits by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/14009 * [release/13.1] Update Azure.Identity package version to 1.17.1 by @​eerhardt in https://github.com/dotnet/aspire/pull/14251 * Bump patch version from 13.1.0 to 13.1.1 by @​Copilot in https://github.com/dotnet/aspire/pull/14329 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.1.0...v13.1.1 ## 13.1.0 We are excited to share that our 13.1.0 release of Aspire has shipped! All of the packages are available in NuGet.org now. Head over to https://aspire.dev/whats-new/aspire-13-1/ to find what's new in 13.1.0! ## What's Changed * Target net10.0 in client integrations by @​eerhardt in https://github.com/dotnet/aspire/pull/12500 * Fix DockerComposeEnvironment duplicating image names in .env file by @​Copilot in https://github.com/dotnet/aspire/pull/12310 * Replace apt-get with npm for Azure Functions Core Tools installation by @​Copilot in https://github.com/dotnet/aspire/pull/12537 * Improve flaky dashboard integration test by @​JamesNK in https://github.com/dotnet/aspire/pull/12534 * Add README.md for the Aspire.Hosting.Azure.AppService package by @​ShilpiRach in https://github.com/dotnet/aspire/pull/12528 * Add support to enable automatic scaling for App Service Environment by @​ShilpiRach in https://github.com/dotnet/aspire/pull/12305 * Update to FluentUI 4.13.1 by @​JamesNK in https://github.com/dotnet/aspire/pull/12532 * Skip playground projects in build-packages workflow by @​Copilot in https://github.com/dotnet/aspire/pull/12547 * Allow HostUrl to remap both address and port by @​danegsta in https://github.com/dotnet/aspire/pull/12521 * Refactor NodeJs Integration by @​eerhardt in https://github.com/dotnet/aspire/pull/12530 * Fix MCP endpoint with redirect HTTPS by @​JamesNK in https://github.com/dotnet/aspire/pull/12556 * [main] Update dependencies from microsoft/usvc-apiserver by @​dotnet-maestro[bot] in https://github.com/dotnet/aspire/pull/12540 * Refactor AddNodeApp by @​eerhardt in https://github.com/dotnet/aspire/pull/12538 * Update Aspire branding from 13.0 to 13.1 by @​Copilot in https://github.com/dotnet/aspire/pull/12527 * Add annotation to specify custom base images for generated Dockerfiles by @​Copilot in https://github.com/dotnet/aspire/pull/12566 * Fix generating random MCP endpoint URL in templates by @​JamesNK in https://github.com/dotnet/aspire/pull/12558 * [CI] Add new Agent for disabling or quarantining tests by @​radical in https://github.com/dotnet/aspire/pull/12570 * Add `ExcludeFromMcp()` resource extension by @​JamesNK in https://github.com/dotnet/aspire/pull/12515 * Localized file check-in by OneLocBuild Task: Build definition ID 1309: Build ID 2828818 by @​dotnet-bot in https://github.com/dotnet/aspire/pull/12546 * Register IPipelineOutputService in DI for pipeline output directory management by @​Copilot in https://github.com/dotnet/aspire/pull/12563 * Add deploy support for Docker Compose by @​captainsafia in https://github.com/dotnet/aspire/pull/12548 * Quarantine flaky test: AzureServiceBusEmulatorResourceGeneratesConfigJsonWithCustomizations by @​Copilot in https://github.com/dotnet/aspire/pull/12578 * Update connection properties for non-Azure resources by @​sebastienros in https://github.com/dotnet/aspire/pull/12583 * Filter to highest package version per channel in aspire add command by @​Copilot in https://github.com/dotnet/aspire/pull/12553 * Log DCP messages at Debug/Trace level in AppHost by @​Copilot in https://github.com/dotnet/aspire/pull/12533 * Add CLI self-update prompts to `aspire update` command by @​Copilot in https://github.com/dotnet/aspire/pull/12395 * Fix golang and alpine images. by @​mitchdenny in https://github.com/dotnet/aspire/pull/12592 * Replace ContainerTargetPlatform.AllLinux with LinuxAmd64 by @​Copilot in https://github.com/dotnet/aspire/pull/12596 * [main] Update dependencies from microsoft/usvc-apiserver by @​dotnet-maestro[bot] in https://github.com/dotnet/aspire/pull/12610 * Make IReportingStep and IReportingTask completion idempotent by @​Copilot in https://github.com/dotnet/aspire/pull/12602 * Show --log-level debug hint when pipeline fails by @​Copilot in https://github.com/dotnet/aspire/pull/12603 * [main] Update dependencies from dotnet/arcade by @​dotnet-maestro[bot] in https://github.com/dotnet/aspire/pull/12622 * Rename app.py to main.py in template by @​eerhardt in https://github.com/dotnet/aspire/pull/12628 * bump extension version by @​adamint in https://github.com/dotnet/aspire/pull/12623 * don't build apphost in cli when running in extension by @​adamint in https://github.com/dotnet/aspire/pull/12621 * Detect which version of yarn is being used by @​eerhardt in https://github.com/dotnet/aspire/pull/12633 * Fix duplicate key exception when using WithExplicitStart() on resources with environment callbacks by @​Copilot in https://github.com/dotnet/aspire/pull/12604 * Support AddCSharpApp, fix some rough edges around project resources by @​adamint in https://github.com/dotnet/aspire/pull/12568 * Add missing namespace to `CertificateAuthorityCollectionResource` by @​danegsta in https://github.com/dotnet/aspire/pull/12639 * Add ModelContextProtocol assemblies to signing list by @​joperezr in https://github.com/dotnet/aspire/pull/12637 * Generate fallback Dockerfile for Python apps without UV by @​Copilot in https://github.com/dotnet/aspire/pull/12627 * Update/bump container image tags for hosting components by @​joperezr in https://github.com/dotnet/aspire/pull/12459 * Mark IDeveloperCertificateService experimental by @​danegsta in https://github.com/dotnet/aspire/pull/12648 * Wait with exponential backoff for expected Executables by @​karolz-ms in https://github.com/dotnet/aspire/pull/12647 * Make ProcessCertificateTrustConfigAsync internal by @​danegsta in https://github.com/dotnet/aspire/pull/12649 * Add test cases and ensure container cert override paths work by @​danegsta in https://github.com/dotnet/aspire/pull/12654 * Python hosting: Support .venv lookup by walking up parent directories by @​Copilot in https://github.com/dotnet/aspire/pull/12616 ... (truncated) ## 13.0.2 This patch is updating our Project Templates for our Python starter app to ensure we depend on the latest version of React. This is out of an abundance of caution, as we don't depend on any of the react packages that were flagged as vulnerable in https://github.com/advisories/GHSA-fv66-9v8q-g76r. ## What's Changed * Bump patch version from 13.0.1 to 13.0.2 by @​Copilot in https://github.com/dotnet/aspire/pull/13324 * Update React and ReactDOM to version 19.2.1 across all projects by @​joperezr in https://github.com/dotnet/aspire/pull/13325 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.0.1...v13.0.2 ## 13.0.1 ## What's Changed * Merge internal changes by @​joperezr in https://github.com/dotnet/aspire/pull/12896 * [release/13.0] Fix Azure roles resources always redeploying by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/12903 * [release/13.0] Remove .py and .js files from being signed (#​13005) by @​eerhardt in https://github.com/dotnet/aspire/pull/13032 * [release/13.0] Fix subscription ID not being disabled on Azure provisioning dialog by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/12913 * [release/13.0] Default OpenAISettings.EnableSensitiveTelemetryData to TelemetryHelpers.EnableSensitiveDataDefault by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13017 * Bump patch version from 13.0.0 to 13.0.1 by @​Copilot in https://github.com/dotnet/aspire/pull/13167 * [release/13.0] EndpointReference evaluation should wait on missing AllocatedEndpoint (#​13074) by @​karolz-ms in https://github.com/dotnet/aspire/pull/13076 * [release/13.0] Update to Npgsql 10 by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13166 * [release/13.0] Update dependencies from microsoft/usvc-apiserver by @​danegsta in https://github.com/dotnet/aspire/pull/13187 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.0.0...v13.0.1 Commits viewable in [compare view](https://github.com/microsoft/aspire/compare/v13.0.0...v13.3.0).
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- dotnet/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index d9dd609c34e9..f1b61aaaa97f 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -7,7 +7,7 @@ - + From 614db62500c96b1a798d0833d242ac239a8269db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:28:43 +0100 Subject: [PATCH 04/33] Python: Bump tornado from 6.5.5 to 6.5.7 in /python (#14090) Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.5.5 to 6.5.7.
Changelog

Sourced from tornado's changelog.

Release notes

.. toctree:: :maxdepth: 2

releases/v6.5.7 releases/v6.5.6 releases/v6.5.5 releases/v6.5.4 releases/v6.5.3 releases/v6.5.2 releases/v6.5.1 releases/v6.5.0 releases/v6.4.2 releases/v6.4.1 releases/v6.4.0 releases/v6.3.3 releases/v6.3.2 releases/v6.3.1 releases/v6.3.0 releases/v6.2.0 releases/v6.1.0 releases/v6.0.4 releases/v6.0.3 releases/v6.0.2 releases/v6.0.1 releases/v6.0.0 releases/v5.1.1 releases/v5.1.0 releases/v5.0.2 releases/v5.0.1 releases/v5.0.0 releases/v4.5.3 releases/v4.5.2 releases/v4.5.1 releases/v4.5.0 releases/v4.4.3 releases/v4.4.2 releases/v4.4.1 releases/v4.4.0 releases/v4.3.0 releases/v4.2.1 releases/v4.2.0 releases/v4.1.0 releases/v4.0.2 releases/v4.0.1 releases/v4.0.0 releases/v3.2.2 releases/v3.2.1

... (truncated)

Commits
  • 48fc2d4 Merge pull request #3633 from bdarnell/curl-reset-65
  • 4ae1ddd Release notes and version bump for 6.5.7
  • 3154caa curl_httpclient: Reset the curl object before putting it on the freelist
  • 7d869c0 Merge pull request #3631 from bdarnell/cve-links
  • 288241f docs: Use the correct link syntax
  • 8da981c docs: Add CVE links to 6.5.6 release notes
  • aba2569 Merge pull request #3626 from bdarnell/fixes-656
  • a24b260 httpclient_test: Accept an additional error message variant
  • a74240a Release notes and version bump for 6.5.6.
  • e8fc7ed simple_httpclient: Strip auth headers on cross-origin redirects
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tornado&package-manager=uv&previous-version=6.5.5&new-version=6.5.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/semantic-kernel/network/alerts).
--------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- python/pyproject.toml | 2 +- python/uv.lock | 54 ++++++++++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index 8a0deef93a72..b93a9083d533 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -164,7 +164,7 @@ dev = [ "pytest ~= 8.2", "pytest-xdist[psutil] ~= 3.6", "pytest-cov >= 5.0", - "pytest-asyncio ~= 0.24", + "pytest-asyncio ~= 1.0", "pytest-timeout>=2.3.1", "snoop ~= 0.4", "mypy >= 1.10", diff --git a/python/uv.lock b/python/uv.lock index 44c249e89981..2a0ef5016559 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -1,4 +1,5 @@ version = 1 +revision = 3 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '4' and sys_platform == 'darwin'", @@ -553,6 +554,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/df/73/b6e24bd22e6720ca8ee9a85a0c4a2971af8497d8f3193fa05390cbd46e09/backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8", size = 15148, upload-time = "2022-10-05T19:19:30.546Z" }, ] +[[package]] +name = "backports-asyncio-runner" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/ff/70dca7d7cb1cbc0edb2c6cc0c38b65cba36cccc491eca64cabd5fe7f8670/backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162", size = 69893, upload-time = "2025-07-02T02:27:15.685Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/59/76ab57e3fe74484f48a53f8e337171b4a2349e506eabe136d7e01d059086/backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5", size = 12313, upload-time = "2025-07-02T02:27:14.263Z" }, +] + [[package]] name = "bcrypt" version = "5.0.0" @@ -5341,14 +5351,16 @@ wheels = [ [[package]] name = "pytest-asyncio" -version = "0.26.0" +version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "backports-asyncio-runner", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, { name = "pytest", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(python_full_version < '3.13' and sys_platform == 'darwin') or (python_full_version < '3.13' and sys_platform == 'linux') or (python_full_version < '3.13' and sys_platform == 'win32')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/c4/453c52c659521066969523e87d85d54139bbd17b78f09532fb8eb8cdb58e/pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f", size = 54156, upload-time = "2025-03-25T06:22:28.883Z" } +sdist = { url = "https://files.pythonhosted.org/packages/43/7c/d36d04db312ecf4298932ef77e6e4a9e8ad017906e24e34f0b0c361a2473/pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42", size = 58514, upload-time = "2026-05-26T09:56:04.083Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/7f/338843f449ace853647ace35870874f69a764d251872ed1b4de9f234822c/pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0", size = 19694, upload-time = "2025-03-25T06:22:27.807Z" }, + { url = "https://files.pythonhosted.org/packages/03/e2/08a497ef684b88559c9cc5f4ad53a37e7b99e727094a86d6ea32536d5d3c/pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1", size = 16930, upload-time = "2026-05-26T09:56:02.576Z" }, ] [[package]] @@ -6480,13 +6492,13 @@ requires-dist = [ { name = "azure-cosmos", marker = "extra == 'azure'", specifier = "~=4.7" }, { name = "azure-identity", specifier = ">=1.13" }, { name = "azure-search-documents", marker = "extra == 'azure'", specifier = ">=11.6.0b4,<12.0.0" }, - { name = "boto3", marker = "extra == 'aws'", specifier = ">=1.36.4,<1.41.0" }, + { name = "boto3", marker = "extra == 'aws'", specifier = ">=1.36.4,<1.43.0" }, { name = "chromadb", marker = "extra == 'chroma'", specifier = ">=0.5,<1.4" }, { name = "cloudevents", specifier = "~=1.0" }, { name = "defusedxml", specifier = "~=0.7" }, { name = "faiss-cpu", marker = "extra == 'faiss'", specifier = ">=1.10.0" }, { name = "google-cloud-aiplatform", marker = "extra == 'google'", specifier = ">=1.114,<1.134" }, - { name = "google-genai", marker = "extra == 'google'", specifier = "~=1.51.0" }, + { name = "google-genai", marker = "extra == 'google'", specifier = ">=1.51,<1.75" }, { name = "ipykernel", marker = "extra == 'notebooks'", specifier = ">=6.29,<8.0" }, { name = "jinja2", specifier = "~=3.1" }, { name = "mcp", specifier = ">=1.26.0" }, @@ -6494,7 +6506,7 @@ requires-dist = [ { name = "microsoft-agents-activity", marker = "extra == 'copilotstudio'", specifier = ">=0.3.1" }, { name = "microsoft-agents-copilotstudio-client", marker = "extra == 'copilotstudio'", specifier = ">=0.3.1" }, { name = "milvus", marker = "sys_platform != 'win32' and extra == 'milvus'", specifier = ">=2.3,<2.3.8" }, - { name = "mistralai", marker = "extra == 'mistralai'", specifier = ">=1.2,<2.0" }, + { name = "mistralai", marker = "extra == 'mistralai'", specifier = ">=1.2,<2.4.6" }, { name = "motor", marker = "extra == 'mongo'", specifier = ">=3.3.2,<3.8.0" }, { name = "nest-asyncio", specifier = "~=1.6" }, { name = "numpy", marker = "python_full_version < '3.12'", specifier = ">=1.25.0" }, @@ -6514,7 +6526,7 @@ requires-dist = [ { name = "psycopg", extras = ["binary", "pool"], marker = "extra == 'postgres'", specifier = "~=3.2" }, { name = "pyarrow", marker = "extra == 'usearch'", specifier = ">=12.0,<22.0" }, { name = "pybars4", specifier = "~=0.9" }, - { name = "pydantic", specifier = ">=2.0,!=2.10.0,!=2.10.1,!=2.10.2,!=2.10.3,<2.13" }, + { name = "pydantic", specifier = ">=2.0,!=2.10.0,!=2.10.1,!=2.10.2,!=2.10.3,<2.14" }, { name = "pydantic-settings", specifier = "~=2.0" }, { name = "pymilvus", marker = "extra == 'milvus'", specifier = ">=2.3,<2.7" }, { name = "pymongo", marker = "extra == 'mongo'", specifier = ">=4.8.0,<4.16" }, @@ -6542,7 +6554,7 @@ dev = [ { name = "nbconvert", specifier = "~=7.16" }, { name = "pre-commit", specifier = "~=3.7" }, { name = "pytest", specifier = "~=8.2" }, - { name = "pytest-asyncio", specifier = "~=0.24" }, + { name = "pytest-asyncio", specifier = "~=1.0" }, { name = "pytest-cov", specifier = ">=5.0" }, { name = "pytest-timeout", specifier = ">=2.3.1" }, { name = "pytest-xdist", extras = ["psutil"], specifier = "~=3.6" }, @@ -6992,19 +7004,19 @@ wheels = [ [[package]] name = "tornado" -version = "6.5.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f8/f1/3173dfa4a18db4a9b03e5d55325559dab51ee653763bb8745a75af491286/tornado-6.5.5.tar.gz", hash = "sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9", size = 516006, upload-time = "2026-03-10T21:31:02.067Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa", size = 445983, upload-time = "2026-03-10T21:30:44.28Z" }, - { url = "https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521", size = 444246, upload-time = "2026-03-10T21:30:46.571Z" }, - { url = "https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5", size = 447229, upload-time = "2026-03-10T21:30:48.273Z" }, - { url = "https://files.pythonhosted.org/packages/34/01/74e034a30ef59afb4097ef8659515e96a39d910b712a89af76f5e4e1f93c/tornado-6.5.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07", size = 448192, upload-time = "2026-03-10T21:30:51.22Z" }, - { url = "https://files.pythonhosted.org/packages/be/00/fe9e02c5a96429fce1a1d15a517f5d8444f9c412e0bb9eadfbe3b0fc55bf/tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e", size = 448039, upload-time = "2026-03-10T21:30:53.52Z" }, - { url = "https://files.pythonhosted.org/packages/82/9e/656ee4cec0398b1d18d0f1eb6372c41c6b889722641d84948351ae19556d/tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca", size = 447445, upload-time = "2026-03-10T21:30:55.541Z" }, - { url = "https://files.pythonhosted.org/packages/5a/76/4921c00511f88af86a33de770d64141170f1cfd9c00311aea689949e274e/tornado-6.5.5-cp39-abi3-win32.whl", hash = "sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7", size = 448582, upload-time = "2026-03-10T21:30:57.142Z" }, - { url = "https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl", hash = "sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b", size = 448990, upload-time = "2026-03-10T21:30:58.857Z" }, - { url = "https://files.pythonhosted.org/packages/b7/c8/876602cbc96469911f0939f703453c1157b0c826ecb05bdd32e023397d4e/tornado-6.5.5-cp39-abi3-win_arm64.whl", hash = "sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6", size = 448016, upload-time = "2026-03-10T21:31:00.43Z" }, +version = "6.5.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/64/24/95ec527ad67b76d59299e5465b3935d05e4294b7e0290a3924b7487df30b/tornado-6.5.7.tar.gz", hash = "sha256:66c513a76cda70d53907bc27cf1447557699c2e95aa48ba27a442ff61c3ddfc2", size = 519252, upload-time = "2026-06-08T17:34:51.232Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/dc/c7043cab6fed8ae159fc1923ce829ada35c4dbd797d408a43858ffaf9639/tornado-6.5.7-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:148b2eb15c2c765a50796172c1e499649b35f30d2e3c3d3e15913cfa56bfb163", size = 448543, upload-time = "2026-06-08T17:34:38.052Z" }, + { url = "https://files.pythonhosted.org/packages/92/4f/090b1431e5a43df696feceffc268c5383cc079ecb5f08ce58f917109aafe/tornado-6.5.7-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9da38de27f1da3b78a966f0dae12b5a1ea9afe72ca805d84ff06508272ddf100", size = 446707, upload-time = "2026-06-08T17:34:39.594Z" }, + { url = "https://files.pythonhosted.org/packages/37/d8/ef374952fd5da67d4463122c2b8e5a96536ec10b4b339254c6dcde81d01c/tornado-6.5.7-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8d759e71906ee783f8867b93bf26a265743da4c1e2f4a018464c1ba019862972", size = 449774, upload-time = "2026-06-08T17:34:41.204Z" }, + { url = "https://files.pythonhosted.org/packages/35/37/d434c73f4c6e014b745b9b37085f34f40c022f007efff3d7fe65991899f3/tornado-6.5.7-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a46347a18f23fb92b396beebe0fb78f61dda0cc302445202c16203d8a18848b", size = 450745, upload-time = "2026-06-08T17:34:42.531Z" }, + { url = "https://files.pythonhosted.org/packages/b6/2b/56b9aff361d7f1ab728a805ec7d7ea835f8807afa9f5cc690ea0e630efb9/tornado-6.5.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7778b30bef919231265e91c69963ce0f49a1e9c07ac900bbe75b19ce2575ba92", size = 450578, upload-time = "2026-06-08T17:34:43.787Z" }, + { url = "https://files.pythonhosted.org/packages/02/30/a7444fb23aa76860a14198fab96ac79f1866b0a6e19e26c4381b0938e50f/tornado-6.5.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e726f0c75da7726eec023aa62751ff8878bd2737e34fbdd33b1ae5897d2200f5", size = 449985, upload-time = "2026-06-08T17:34:45.326Z" }, + { url = "https://files.pythonhosted.org/packages/5c/42/5f0e56c01e8d9d36f4e23f367b85ae6cae0c1ecddd5e6977d8388ad27488/tornado-6.5.7-cp39-abi3-win32.whl", hash = "sha256:f8de3bf12d3efdd0cbe7c8887868198f8a91415e3f29fcf258d9b8eb7b1d9ae4", size = 451047, upload-time = "2026-06-08T17:34:46.784Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a4/b393076ffb21b469eec5b328a0534cf03a3b90bfc6b1f09507cdd075d938/tornado-6.5.7-cp39-abi3-win_amd64.whl", hash = "sha256:de942f843533a039ef9fa3d9c88c7cd8a7c94553fb5ad0154270989b3d99a2c4", size = 451485, upload-time = "2026-06-08T17:34:48.248Z" }, + { url = "https://files.pythonhosted.org/packages/71/2e/7b1c769803121b809112cf9a00681c472eae1d80e32d7ec0e0bd61d0d0e1/tornado-6.5.7-cp39-abi3-win_arm64.whl", hash = "sha256:ff934fce95643af5f11efdae618eaa73d469dc588641e5c8d19295a0c65c4796", size = 450506, upload-time = "2026-06-08T17:34:49.702Z" }, ] [[package]] From 51748eecf3f814b6c8a53f7f2226fdd4a92d9551 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 09:29:35 +0000 Subject: [PATCH 05/33] Python: Bump pyjwt from 2.11.0 to 2.13.0 in /python (#14084) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.11.0 to 2.13.0.
Release notes

Sourced from pyjwt's releases.

2.13.0

PyJWT 2.13.0 — Security Release

This release bundles five security fixes plus three additional hardening / spec-compliance changes. We recommend all users upgrade.

Security

  • GHSA-xgmm-8j9v-c9wx — JWK JSON accepted as HMAC secret (algorithm confusion). HMACAlgorithm.prepare_key previously rejected PEM- and SSH-formatted asymmetric keys but did not catch a JWK passed as a raw JSON string. In a verifier configured with both symmetric and asymmetric algorithms in algorithms=[…] and a raw-JSON JWK as the key, an attacker could forge HS256 tokens using the JWK text as the HMAC secret. The guard has been extended to reject any JWK-shaped JSON. Reported by @​aradona91.

  • GHSA-jq35-7prp-9v3f — Algorithm allow-list bypass with PyJWK / PyJWKClient. When verifying with a PyJWK, the caller's algorithms=[…] allow-list was checked against the token header alg as a string only; actual verification used the algorithm bound to the PyJWK. An attacker who controlled a registered JWKS key could sign with one algorithm and advertise another on the header. PyJWT now requires the token header alg to match the PyJWK's algorithm before verification. Reported by @​sushi-gif.

  • GHSA-w7vc-732c-9m39 — DoS via base64 decode of unused payload segment when b64=false. For detached-payload JWS (b64=false), the compact-form payload segment was base64-decoded before being discarded in favor of the caller-supplied detached_payload. An attacker could inflate the unused segment to force CPU + memory cost without holding a valid signature. The segment is now required to be empty per RFC 7515 Appendix F, and is no longer decoded. Reported by @​thesmartshadow.

  • GHSA-993g-76c3-p5m4PyJWKClient accepts non-HTTP(S) URIs. PyJWKClient.fetch_data passed its URI to urllib.request.urlopen, which by default also handles file://, ftp://, and data: schemes. An application that fed an attacker-influenced URI into PyJWKClient could be coerced into reading local files or reaching other unintended schemes. PyJWKClient now rejects any URI whose scheme isn't http or https. Reported by @​KEIJOT.

  • GHSA-fhv5-28vv-h8m8PyJWKClient cache wiped on fetch error. A finally-block put(jwk_set=None) cleared the JWK Set cache whenever a fetch raised, turning a transient JWKS-endpoint outage into application-wide auth failure. The cache write was moved into the success path; transient errors no longer evict valid cached keys. Reported by @​eddieran.

Fixed

  • Reject empty HMAC keys outright in HMACAlgorithm.prepare_key with InvalidKeyError instead of accepting them with only a warning. Defends against the os.getenv("JWT_SECRET", "") footgun. Thanks to @​SnailSploit and @​spartan8806 for the reports.
  • Forward per-call options (including enforce_minimum_key_length) from PyJWT.decode through to PyJWS._verify_signature. The option was previously silently dropped between the two layers, so it only took effect when set on the PyJWT instance. Thanks to @​WLUB for the report.
  • RFC 7797 §3 compliance for b64=false: the encoder now auto-adds "b64" to crit, and the decoder rejects tokens that set b64=false without listing it in crit. Thanks to @​MachineLearning-Nerd for the report.

Changed

  • Migrate the dev, docs, and tests package extras to dependency groups, by @​kurtmckee in #1152.

Upgrade notes

Most fixes are invisible to correctly-configured callers. A few behavioral changes you may encounter:

  • Empty HMAC keys now raise. If your app passed "" or b"" as a secret (often via a missing env var, e.g. os.getenv("JWT_SECRET", "")), encode/decode will now raise InvalidKeyError. This is the intended behavior — fix the configuration.
  • PyJWK decoding now requires the token's alg to match the JWK's algorithm. Previously a mismatch was silently honored if the header alg appeared in the allow-list. Tokens that relied on this mismatch will now fail with InvalidAlgorithmError.
  • PyJWKClient now rejects non-HTTP(S) URIs at construction time. Tests or dev environments that fetched JWKS from file:// URIs need to switch to a local HTTP server or load the JWKS by other means (e.g. construct PyJWKSet.from_dict(...) directly).
  • b64=false tokens are now strictly RFC 7515 / 7797 compliant. Tokens with a non-empty compact-form payload segment, or that omit "b64" from crit, will be rejected. PyJWT-produced tokens always satisfy both invariants, so round-trips through PyJWT are unaffected.
  • enforce_minimum_key_length set per-call now takes effect. Callers who passed options={"enforce_minimum_key_length": True} to jwt.decode() previously got no enforcement; they will now get InvalidKeyError on undersized keys, as documented.

Full changelog: https://github.com/jpadilla/pyjwt/compare/2.12.1...2.13.0

2.12.1

What's Changed

Full Changelog: https://github.com/jpadilla/pyjwt/compare/2.12.0...2.12.1

2.12.0

Security

... (truncated)

Changelog

Sourced from pyjwt's changelog.

v2.13.0 <https://github.com/jpadilla/pyjwt/compare/2.12.1...2.13.0>__

Security


- Reject JWK JSON documents passed as raw HMAC secrets in
  ``HMACAlgorithm.prepare_key`` to close an algorithm-confusion gap that
  the existing PEM/SSH guard did not cover. Reported by @aradona91 in
`GHSA-xgmm-8j9v-c9wx
<https://github.com/jpadilla/pyjwt/security/advisories/GHSA-xgmm-8j9v-c9wx>`__.
- Bind the JWT header ``alg`` to ``PyJWK.algorithm_name`` during
  verification so the caller's ``algorithms=[...]`` allow-list cannot be
bypassed when decoding with a ``PyJWK`` / ``PyJWKClient`` key. Reported
by @sushi-gif in `GHSA-jq35-7prp-9v3f
<https://github.com/jpadilla/pyjwt/security/advisories/GHSA-jq35-7prp-9v3f>`__.
- Reject non-``http(s)`` URI schemes in ``PyJWKClient`` so attacker-
influenced URIs cannot read local files or reach unintended schemes via
urllib's default ``file://`` / ``ftp://`` / ``data:`` handlers. Reported
by @KEIJOT in `GHSA-993g-76c3-p5m4
<https://github.com/jpadilla/pyjwt/security/advisories/GHSA-993g-76c3-p5m4>`__.
- Preserve the cached JWK Set on fetch errors in
``PyJWKClient.fetch_data``.
  The previous ``finally``-block ``put(None)`` pattern cleared the cache
on any transient outage, turning one bad JWKS request into application-
wide auth failure. Reported by @eddieran in `GHSA-fhv5-28vv-h8m8
<https://github.com/jpadilla/pyjwt/security/advisories/GHSA-fhv5-28vv-h8m8>`__.
- Skip the unconditional base64 decode of the compact-form payload
segment
  when ``b64=false`` is set in the protected header, and require that
  segment to be empty (RFC 7515 Appendix F detached form). Closes an
  unauthenticated DoS amplifier. Reported by @thesmartshadow in
`GHSA-w7vc-732c-9m39
<https://github.com/jpadilla/pyjwt/security/advisories/GHSA-w7vc-732c-9m39>`__.

Fixed


- Reject empty HMAC keys outright in ``HMACAlgorithm.prepare_key`` with
  ``InvalidKeyError`` instead of accepting them with only a warning.
  Thanks to @SnailSploit and @spartan8806 for independently flagging the
  footgun.
- Forward per-call ``options`` (including
``enforce_minimum_key_length``)
  from ``PyJWT.decode`` through to ``PyJWS._verify_signature`` so the
option actually takes effect when set at the call site rather than only
  on the ``PyJWT`` instance. Thanks to @WLUB for the report.
- RFC 7797 §3 compliance for ``b64=false``: the encoder now auto-adds
``&quot;b64&quot;`` to the ``crit`` header parameter, and the
decoder rejects
tokens that set ``b64=false`` without listing it in ``crit``. Thanks to
  @MachineLearning-Nerd for the report.

Changed
  • Migrate the dev, docs, and tests package extras to dependency groups by @​kurtmckee in [#1152](https://github.com/jpadilla/pyjwt/issues/1152) &lt;https://github.com/jpadilla/pyjwt/pull/1152&gt;__

v2.12.1 &lt;https://github.com/jpadilla/pyjwt/compare/2.12.0...2.12.1&gt;__ </tr></table>

... (truncated)

Commits
  • 7144e45 Apply ruff format
  • d2f4bec Restore cast() calls with cross-version type: ignore for prepare_key
  • 22f478c Remove redundant casts in RSAAlgorithm.prepare_key and `ECAlgorithm.prepare...
  • 95791b1 Bundle security fixes and hardening into 2.13.0
  • dcc27a9 [pre-commit.ci] pre-commit autoupdate (#1155)
  • 9d08a9a [pre-commit.ci] pre-commit autoupdate (#1146)
  • b87c100 Bump codecov/codecov-action from 5 to 6 (#1154)
  • 40e3147 Migrate development extras to dependency groups (#1152)
  • a4e1a3d Add typing_extensions dependency for Python < 3.11 (#1151)
  • bd9700c Use PyJWK algorithm when encoding without explicit algorithm (#1148)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pyjwt&package-manager=uv&previous-version=2.11.0&new-version=2.13.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/semantic-kernel/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- python/uv.lock | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/python/uv.lock b/python/uv.lock index 2a0ef5016559..0cf93cde34f8 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -5112,11 +5112,14 @@ wheels = [ [[package]] name = "pyjwt" -version = "2.11.0" +version = "2.13.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5c/5a/b46fa56bf322901eee5b0454a34343cdbdae202cd421775a8ee4e42fd519/pyjwt-2.11.0.tar.gz", hash = "sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623", size = 98019, upload-time = "2026-01-30T19:59:55.694Z" } +dependencies = [ + { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/01/c26ce75ba460d5cd503da9e13b21a33804d38c2165dec7b716d06b13010c/pyjwt-2.11.0-py3-none-any.whl", hash = "sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469", size = 28224, upload-time = "2026-01-30T19:59:54.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" }, ] [package.optional-dependencies] From 6209c77fd52d6ff99d7797d66639055b36a91ae3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 09:30:02 +0000 Subject: [PATCH 06/33] .Net: Bump @babel/core from 7.26.10 to 7.29.7 in /dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client (#14083) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.26.10 to 7.29.7.
Release notes

Sourced from @​babel/core's releases.

v7.29.7 (2026-05-25)

Re-release all packages with npm provenance attestations

v7.29.6 (2026-05-25)

:bug: Bug Fix

Committers: 3

v7.29.5 (2026-05-05)

:house: Internal

  • babel-preset-env
    • Update @babel/* dependencies

v7.29.4 (2026-05-05)

:bug: Bug Fix

  • babel-plugin-transform-modules-systemjs
    • #17974 [7.x backport]fix(systemjs): improve module string name support (@​JLHwung)

Committers: 1

v7.29.3 (2026-04-30)

:eyeglasses: Spec Compliance

:bug: Bug Fix

  • babel-helper-create-class-features-plugin, babel-plugin-proposal-decorators
    • #17931 fix(decorators): replace super within all removed static elements (@​JLHwung)
  • babel-register
  • babel-compat-data, babel-plugin-bugfix-safari-rest-destructuring-rhs-array, babel-preset-env

:nail_care: Polish

  • babel-parser

... (truncated)

Commits
Maintainer changes

This version was pushed to npm by GitHub Actions, a new releaser for @​babel/core since your current version.


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@babel/core&package-manager=npm_and_yarn&previous-version=7.26.10&new-version=7.29.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/semantic-kernel/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../package-lock.json | 327 +++++++++--------- .../ProcessWithCloudEvents.Client/yarn.lock | 242 +++++++------ 2 files changed, 299 insertions(+), 270 deletions(-) diff --git a/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/package-lock.json b/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/package-lock.json index 69052d444e56..7eae102d80f8 100644 --- a/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/package-lock.json +++ b/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/package-lock.json @@ -33,39 +33,25 @@ "vite": "^6.4.1" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -73,23 +59,22 @@ } }, "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -105,16 +90,16 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -122,14 +107,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -138,30 +123,40 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -181,9 +176,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", "engines": { @@ -191,9 +186,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", "engines": { @@ -201,9 +196,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "engines": { @@ -211,27 +206,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.0" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -285,58 +280,48 @@ } }, "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -969,7 +954,6 @@ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", "license": "MIT", - "peer": true, "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" @@ -1291,7 +1275,6 @@ "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.61.6.tgz", "integrity": "sha512-iB/iJ9lIVrInq5nlujMny/uUDLg8OrC/kWKHFXm3AtZTlsDU6/CNwGiTCZltXTBiYjA7zgXiloUZRwb8WmQpZg==", "license": "MIT", - "peer": true, "dependencies": { "@fluentui/react-accordion": "^9.6.6", "@fluentui/react-alert": "9.0.0-beta.124", @@ -1546,7 +1529,6 @@ "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.315.tgz", "integrity": "sha512-IITWAQGgU7I32eHPDHi+TUCUF6malP27wZLUV3bqjGVF/x/lfxvTIx8yqv/cxuwF3+ITGFDpl+278ZYJtOI7ww==", "license": "MIT", - "peer": true, "dependencies": { "@griffel/react": "^1.0.0", "tslib": "^2.1.0" @@ -2616,34 +2598,31 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.0.0" + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", "engines": { @@ -2651,16 +2630,16 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -3220,7 +3199,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -3230,7 +3208,6 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -3277,7 +3254,6 @@ "integrity": "sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.29.1", "@typescript-eslint/types": "8.29.1", @@ -3493,7 +3469,6 @@ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3568,6 +3543,19 @@ "dev": true, "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.37", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.37.tgz", + "integrity": "sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3593,9 +3581,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", "dev": true, "funding": [ { @@ -3612,12 +3600,12 @@ } ], "license": "MIT", - "peer": true, "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" @@ -3637,9 +3625,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001712", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001712.tgz", - "integrity": "sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==", + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", "dev": true, "funding": [ { @@ -3849,9 +3837,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.134", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.134.tgz", - "integrity": "sha512-zSwzrLg3jNP3bwsLqWHmS5z2nIOQ5ngMnfMZOWWtXnqqQkPVyOipxK98w+1beLw1TB+EImPNcG8wVP/cLVs2Og==", + "version": "1.5.372", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.372.tgz", + "integrity": "sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA==", "dev": true, "license": "ISC" }, @@ -3859,8 +3847,7 @@ "version": "8.6.0", "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/embla-carousel-autoplay": { "version": "8.6.0", @@ -3950,7 +3937,6 @@ "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -5337,11 +5323,14 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.47", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz", + "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/optionator": { "version": "0.9.4", @@ -5556,7 +5545,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -5569,7 +5557,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -5956,7 +5943,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6035,7 +6021,6 @@ "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6155,9 +6140,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -6251,7 +6236,6 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -6345,7 +6329,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, diff --git a/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/yarn.lock b/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/yarn.lock index 3687495b06ff..b41a7ccd3e84 100644 --- a/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/yarn.lock +++ b/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/yarn.lock @@ -2,87 +2,84 @@ # yarn lockfile v1 -"@ampproject/remapping@^2.2.0": - version "2.3.0" - resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== +"@babel/code-frame@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.7.tgz#f2fbbfea87c44a21590ec515b778b2c26d8866e7" + integrity sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw== dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@babel/code-frame@^7.26.2": - version "7.26.2" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz" - integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== - dependencies: - "@babel/helper-validator-identifier" "^7.25.9" + "@babel/helper-validator-identifier" "^7.29.7" js-tokens "^4.0.0" - picocolors "^1.0.0" + picocolors "^1.1.1" -"@babel/compat-data@^7.26.8": - version "7.26.8" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz" - integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== +"@babel/compat-data@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.29.7.tgz#6f0237f0f36d2e51c0570a636faed9d2d0efe629" + integrity sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg== "@babel/core@^7.26.0": - version "7.26.10" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz" - integrity sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.10" - "@babel/helper-compilation-targets" "^7.26.5" - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helpers" "^7.26.10" - "@babel/parser" "^7.26.10" - "@babel/template" "^7.26.9" - "@babel/traverse" "^7.26.10" - "@babel/types" "^7.26.10" + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.29.7.tgz#80c10b17248082968b57a857b91640971f2070f7" + integrity sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA== + dependencies: + "@babel/code-frame" "^7.29.7" + "@babel/generator" "^7.29.7" + "@babel/helper-compilation-targets" "^7.29.7" + "@babel/helper-module-transforms" "^7.29.7" + "@babel/helpers" "^7.29.7" + "@babel/parser" "^7.29.7" + "@babel/template" "^7.29.7" + "@babel/traverse" "^7.29.7" + "@babel/types" "^7.29.7" + "@jridgewell/remapping" "^2.3.5" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.26.10", "@babel/generator@^7.27.0": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz" - integrity sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw== +"@babel/generator@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.29.7.tgz#cca0b8827e6bcf3ba176788e7f3b180ad6db2fa3" + integrity sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ== dependencies: - "@babel/parser" "^7.27.0" - "@babel/types" "^7.27.0" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" + "@babel/parser" "^7.29.7" + "@babel/types" "^7.29.7" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" jsesc "^3.0.2" -"@babel/helper-compilation-targets@^7.26.5": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz" - integrity sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA== +"@babel/helper-compilation-targets@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz#7a1def704302401c47f64fa85589e974ae217042" + integrity sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g== dependencies: - "@babel/compat-data" "^7.26.8" - "@babel/helper-validator-option" "^7.25.9" + "@babel/compat-data" "^7.29.7" + "@babel/helper-validator-option" "^7.29.7" browserslist "^4.24.0" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-module-imports@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz" - integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== +"@babel/helper-globals@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.29.7.tgz#f04a96fbd8473241b1079243f5b3f03a3010ab7b" + integrity sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA== + +"@babel/helper-module-imports@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz#ef25048a518e828d7393fac5882ddd73921d7396" + integrity sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g== dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" + "@babel/traverse" "^7.29.7" + "@babel/types" "^7.29.7" -"@babel/helper-module-transforms@^7.26.0": - version "7.26.0" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz" - integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== +"@babel/helper-module-transforms@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz#b062747a5997ba138637201328bbff77960574ae" + integrity sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg== dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-module-imports" "^7.29.7" + "@babel/helper-validator-identifier" "^7.29.7" + "@babel/traverse" "^7.29.7" "@babel/helper-plugin-utils@^7.25.9": version "7.26.5" @@ -94,31 +91,48 @@ resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz" integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== +"@babel/helper-string-parser@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz#7f0871d99824d23137d60f86fcf6130fd5a1b51f" + integrity sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw== + "@babel/helper-validator-identifier@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz" integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== -"@babel/helper-validator-option@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz" - integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== +"@babel/helper-validator-identifier@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz#bd87084ced0c796ec46bda492de6e83d29e89fc2" + integrity sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg== -"@babel/helpers@^7.26.10": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz" - integrity sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg== +"@babel/helper-validator-option@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz#cf315be940213b354eb4abcc0bd01ebe3f73bc2a" + integrity sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw== + +"@babel/helpers@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.29.7.tgz#45abfde7548997e34376c3e69feb475cffb4a607" + integrity sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg== dependencies: - "@babel/template" "^7.27.0" - "@babel/types" "^7.27.0" + "@babel/template" "^7.29.7" + "@babel/types" "^7.29.7" -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.26.10", "@babel/parser@^7.27.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7": version "7.27.0" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz" integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg== dependencies: "@babel/types" "^7.27.0" +"@babel/parser@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.7.tgz#837b87387cbf5ec5530cb634b3c622f68edb9334" + integrity sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg== + dependencies: + "@babel/types" "^7.29.7" + "@babel/plugin-transform-react-jsx-self@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz" @@ -140,29 +154,29 @@ dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.26.9", "@babel/template@^7.27.0": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz" - integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/parser" "^7.27.0" - "@babel/types" "^7.27.0" - -"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz" - integrity sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.27.0" - "@babel/parser" "^7.27.0" - "@babel/template" "^7.27.0" - "@babel/types" "^7.27.0" +"@babel/template@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.29.7.tgz#4d9d4004f645cdd304de958c725162784ecac700" + integrity sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg== + dependencies: + "@babel/code-frame" "^7.29.7" + "@babel/parser" "^7.29.7" + "@babel/types" "^7.29.7" + +"@babel/traverse@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.29.7.tgz#c47b07a41b95da0907d026b5dd894d98de7d2f2d" + integrity sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw== + dependencies: + "@babel/code-frame" "^7.29.7" + "@babel/generator" "^7.29.7" + "@babel/helper-globals" "^7.29.7" + "@babel/parser" "^7.29.7" + "@babel/template" "^7.29.7" + "@babel/types" "^7.29.7" debug "^4.3.1" - globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.27.0": +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.0": version "7.27.0" resolved "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz" integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg== @@ -170,6 +184,14 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" +"@babel/types@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.7.tgz#8005e31d82712ee7adaef6e23c63b71a62770a92" + integrity sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA== + dependencies: + "@babel/helper-string-parser" "^7.29.7" + "@babel/helper-validator-identifier" "^7.29.7" + "@ctrl/tinycolor@^3.3.4": version "3.6.1" resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz" @@ -1473,6 +1495,14 @@ resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz" integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== +"@jridgewell/gen-mapping@^0.3.12": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/gen-mapping@^0.3.5": version "0.3.8" resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz" @@ -1482,6 +1512,14 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.24" +"@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" @@ -1497,7 +1535,12 @@ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": +"@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@^0.3.24": version "0.3.25" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -1505,6 +1548,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -2346,11 +2397,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^14.0.0: version "14.0.0" resolved "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz" @@ -2967,7 +3013,7 @@ path-key@^3.1.0: resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -picocolors@^1.0.0, picocolors@^1.1.1: +picocolors@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== From 356aed0986ac650318f93232d4d9f1573ccf87cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 19:53:20 +0900 Subject: [PATCH 07/33] Python: Bump starlette from 0.52.1 to 1.3.1 in /python (#14092) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [starlette](https://github.com/Kludex/starlette) from 0.52.1 to 1.3.1.
Release notes

Sourced from starlette's releases.

Version 1.3.1

What's Changed

Full Changelog: https://github.com/Kludex/starlette/compare/1.3.0...1.3.1

Version 1.3.0

What's Changed

New Contributors

Full Changelog: https://github.com/Kludex/starlette/compare/1.2.1...1.3.0

Version 1.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/Kludex/starlette/compare/1.2.0...1.2.1

Version 1.2.0

What's Changed

Full Changelog: https://github.com/Kludex/starlette/compare/1.1.0...1.2.0

Version 1.1.0

... (truncated)

Changelog

Sourced from starlette's changelog.

1.3.1 (June 12, 2026)

Fixed

  • Enforce max_fields and max_part_size in FormParser #3329.
  • Enforce FormParser limits in parser callbacks #3331.

1.3.0 (June 11, 2026)

Added

  • Add httpx2 to the full extra #3323.
  • Annotate the URLPath protocol parameter with Literal #3285.

Fixed

  • Build request.url from structured components #3326.
  • Clamp oversized suffix ranges in FileResponse #3307.
  • Catch OSError alongside MultiPartException when closing temp files #3191.
  • Avoid collapsing exception groups raised from user code #2830.
  • Use removeprefix to strip the weak ETag indicator in is_not_modified #3193.
  • Fix IndexError in URL.replace() on a URL with no authority #3317.
  • Adjust testclient typing and warnings #3322.

1.2.1 (May 31, 2026)

Fixed

  • Use httpx2 for type checking in the testclient module #3304.
  • Add assert error for requires() when the request parameter is not a Request type #3298.

1.2.0 (May 28, 2026)

Added

  • Support httpx2 in the test client #3291.

1.1.0 (May 23, 2026)

Added

  • Use "application/octet-stream" as the FileResponse media type fallback #3283.

Fixed

  • Only dispatch standard HTTP verbs in HTTPEndpoint #3286.
  • Reject absolute paths in StaticFiles.lookup_path #3287.

1.0.1 (May 21, 2026)

... (truncated)

Commits
  • 8ebffd0 Version 1.3.1 (#3330)
  • 25b8e17 Enforce FormParser limits in parser callbacks (#3331)
  • dba1c4b Enforce max_fields and max_part_size in FormParser (#3329)
  • 45e51dc Use StarletteDeprecationWarning instead of DeprecationWarning (#3119)
  • 5f8610c Version 1.3.0 (#3327)
  • 167b585 Build request.url from structured components (#3326)
  • 3730925 Use removeprefix to strip weak ETag indicator in is_not_modified (#3193)
  • e6f7ad1 avoid collapsing exception groups from user code (#2830)
  • 115228f Annotate URLPath protocol parameter with Literal (#3285)
  • 113f193 docs: replace inline ASGI server list with link to canonical implemen… (#3204)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=starlette&package-manager=uv&previous-version=0.52.1&new-version=1.3.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/semantic-kernel/network/alerts).
--------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- python/tests/unit/data/conftest.py | 19 +++++++++++++++++++ python/uv.lock | 6 +++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/python/tests/unit/data/conftest.py b/python/tests/unit/data/conftest.py index d29bad7f8b0d..b184b60e43ed 100644 --- a/python/tests/unit/data/conftest.py +++ b/python/tests/unit/data/conftest.py @@ -2,6 +2,7 @@ import ast +import asyncio from collections.abc import Mapping, Sequence from dataclasses import dataclass from typing import Annotated, Any @@ -23,6 +24,24 @@ from semantic_kernel.kernel_types import OptionalOneOrMany +@fixture(autouse=True) +def _ensure_event_loop(): + """Ensure a current event loop exists before each test. + + Works around a pytest-asyncio 0.26 bug on Windows Python 3.10 where + asyncio.set_event_loop(None) can be left as state after a previous test's + teardown, and _provide_clean_event_loop does not recover because it only + creates a fresh loop when old_loop is not None. By guaranteeing a non-None + loop at fixture-setup time, _temporary_event_loop_policy saves a valid + old_loop, so the teardown path restores a valid loop instead of None. + """ + try: + asyncio.get_event_loop() + except RuntimeError: + asyncio.set_event_loop(asyncio.new_event_loop()) + yield + + @fixture def DictVectorStoreRecordCollection() -> type[VectorSearch]: class DictVectorStoreRecordCollection( diff --git a/python/uv.lock b/python/uv.lock index 0cf93cde34f8..c6a7b77b9c19 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -6746,15 +6746,15 @@ wheels = [ [[package]] name = "starlette" -version = "0.52.1" +version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "typing-extensions", marker = "(python_full_version < '3.13' and sys_platform == 'darwin') or (python_full_version < '3.13' and sys_platform == 'linux') or (python_full_version < '3.13' and sys_platform == 'win32')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c4/68/79977123bb7be889ad680d79a40f339082c1978b5cfcf62c2d8d196873ac/starlette-0.52.1.tar.gz", hash = "sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933", size = 2653702, upload-time = "2026-01-18T13:34:11.062Z" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/0d/13d1d239a25cbfb19e740db83143e95c772a1fe10202dda4b76792b114dd/starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74", size = 74272, upload-time = "2026-01-18T13:34:09.188Z" }, + { url = "https://files.pythonhosted.org/packages/ec/bb/2799cc2ede3ed41131f8975621e7213dfc7ef4acbbaadfa440f32500c370/starlette-1.3.1-py3-none-any.whl", hash = "sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6", size = 73632, upload-time = "2026-06-12T09:23:10.017Z" }, ] [[package]] From 367c75f4ff972e7a2281dcae4bd74800c5eef9eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:53:52 +0000 Subject: [PATCH 08/33] .Net: Bump minimatch from 3.1.2 to 3.1.5 in /dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client (#13604) Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.1.2 to 3.1.5.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=minimatch&package-manager=npm_and_yarn&previous-version=3.1.2&new-version=3.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/semantic-kernel/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../package-lock.json | 20 ++++++++--------- .../ProcessWithCloudEvents.Client/yarn.lock | 22 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/package-lock.json b/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/package-lock.json index 7eae102d80f8..793fe1b1d189 100644 --- a/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/package-lock.json +++ b/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/package-lock.json @@ -3357,9 +3357,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3367,13 +3367,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -5278,9 +5278,9 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { diff --git a/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/yarn.lock b/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/yarn.lock index b41a7ccd3e84..86a8d8fcfba1 100644 --- a/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/yarn.lock +++ b/dotnet/samples/Demos/ProcessWithCloudEvents/ProcessWithCloudEvents.Client/yarn.lock @@ -1988,10 +1988,10 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== +brace-expansion@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== dependencies: balanced-match "^1.0.0" @@ -2924,18 +2924,18 @@ micromatch@^4.0.8: picomatch "^2.3.1" minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + version "3.1.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== dependencies: brace-expansion "^1.1.7" minimatch@^9.0.4: - version "9.0.5" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + version "9.0.9" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" + integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== dependencies: - brace-expansion "^2.0.1" + brace-expansion "^2.0.2" ms@^2.1.3: version "2.1.3" From 445fd0ea5364622d30069510f639032ecea6eaff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:56:33 +0000 Subject: [PATCH 09/33] .Net: Bump Aspire.Azure.Search.Documents from 9.5.1 to 13.3.0 (#13994) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated [Aspire.Azure.Search.Documents](https://github.com/microsoft/aspire) from 9.5.1 to 13.3.0.
Release notes _Sourced from [Aspire.Azure.Search.Documents's releases](https://github.com/microsoft/aspire/releases)._ ## 13.3.0 # Aspire 13.3.0 Aspire 13.3 is here! 🚀 This release is packed with new ways to deploy, debug, and build distributed apps — including `aspire destroy`, browser telemetry in the dashboard, Kubernetes deployment, first-class JavaScript publishing, and major TypeScript AppHost parity improvements. ## Highlights - 🧹 **Clean teardown** — New **`aspire destroy`** tears down Azure, Kubernetes, and Docker Compose deployments, and pipeline summaries make deploy/publish/destroy runs easier to follow. - 🔍 **Frontend telemetry** — **Aspire.Hosting.Browsers** captures browser console logs, network requests, and screenshots right in the Aspire dashboard. - ☸️ **Kubernetes deploy preview** — **`aspire deploy`** can now generate Helm-based Kubernetes deployments, with first-class Ingress and Gateway API routing. - 🟨 **JavaScript publishing** — New **`PublishAs*`** methods support static sites, Node servers, npm-script apps, Next.js, Vite, Bun, Yarn, and pnpm. - 🌐 **TypeScript AppHost parity** — Unified `withEnvironment`, Docker Compose hooks, endpoint expressions, Azure Container Apps domains, and more close the gap with C# AppHosts. - 🛠️ **CLI upgrades** — Run the standalone dashboard with **`aspire dashboard run`**, install the CLI as a NativeAOT `dotnet tool`, and search API docs from the terminal. - ☁️ **Azure goodness** — New Azure Front Door, Network Security Perimeter, AKS, private endpoint, and Foundry Prompt Agent support. - 🐳 **Better containers** — The Aspire container tunnel is now enabled by default for consistent host connectivity across Docker Desktop, Docker Engine, and Podman. ## ⚠️ Breaking changes Notable breaking changes include `--log-level` becoming `--pipeline-log-level`, the dashboard MCP server being replaced by `aspire agent init`, `dotnet new aspire-py-starter` moving to `aspire new aspire-py-starter`, and several API shape updates across AKS, Foundry, JavaScript diagnostics, and TypeScript AppHost helpers. See the full list in the [Aspire 13.3 breaking changes](https://aspire.dev/whats-new/aspire-13-3/#%EF%B8%8F-breaking-changes). ## 📖 Learn more For the full details, examples, migration guidance, and everything new in this release, check out [What's new in Aspire 13.3](https://aspire.dev/whats-new/aspire-13-3/). Thank you to all the community contributors who helped make Aspire 13.3 possible! 💜 ## 13.2.4 # Aspire 13.2.4 ## What's New in Aspire 13.2.4 Patch release addressing a security advisory in OpenTelemetry dependencies. ### 🐛 Fixes - 🔒 Bumped OpenTelemetry dependencies to address CVE-2026-40894 (#​16420) ### 🏷️ Housekeeping - 🚀 Bumped branding to 13.2.4 (#​16436) ## 13.2.3 # What's New in Aspire 13.2.3 Patch release focused on CLI packaging, signing, and reliability fixes. ## 🐛 Fixes - 🛑 aspire stop now properly cleans up application containers on Windows (#​16123) - 🔐 Fixed macOS signing, permissions, and certificate trust with improved CI verification (#​16053) - ✍️ Fixed signing for the aspire-managed bundle payload (#​16211) - 🎭 Fixed Playwright CLI provenance verification for the new tag format (#​16134) - 🧭 Updated service discovery environment variables (#​16223) ## 🔧 Improvements - 📊 Removed telemetry API data limits and refactored URL builders (#​16023) - ⏱️ Increased native build + sign timeout to 60 minutes for reliability (#​16212) ## 🏷️ Housekeeping - 🔖 Bumped branding to 13.2.3 (#​16181) - 🧪 Temporarily disabled Verify CLI archive step on Windows while investigating (#​16276, #​16285) ## 13.2.2 This is a servicing release focused on bug fixes and platform improvements. 🐛 Bug Fixes - Fix SqlClient runtime asset layout on Unix — Resolved an issue where Microsoft.Data.SqlClient failed to load correctly on macOS and Linux due to incorrect NuGet asset layout (#​15709) - Fix IDE execution regressions for Azure Functions and class library projects — Backported fixes for 13.2 regressions impacting IDE-based execution (#​15714) - Fix NpmRunner multi-version output parsing — npm view returning multiple versions no longer breaks version resolution; also bumps @​playwright/cli to >=0.1.3 (#​15746) - Skip name validation for internal resources — ProjectRebuilderResource, installer, and venv creator resources no longer fail the 64-char name limit since they're never deployed (#​15726, fixes #​15693) 🔒 Security & Certificates - Use ASP.NET Core dev cert for DCP — Avoids ephemeral certificate trust issues by using the standard ASP.NET Core developer certificate (#​15718) - Cache PFX dev certs on Windows and Linux — Prevents binary-level changes between runs for persistent container scenarios (#​15774) 🏗️ Infrastructure & Platform - ARM64 CLI support — Added win-arm64 and linux-arm64 to the native CLI archive build matrix (#​15599) - Update DCP to 0.22.11 (#​15713) 💻 CLI Improvements - Show anonymous dashboard URLs in aspire ps — The dashboard URL is now displayed even when running without authentication (#​15731 ## 13.2.1 🐛 Bug Fixes - 🖥️ CLI bundles for ARM & musl — win-arm64, linux-arm64, and linux-musl-x64 bundles now correctly include DCP instead of silently producing broken installs (#​15529) - ⚡ aspire new in VS Code — Fixed a race where the workspace switch severed the CLI terminal before the agent init prompt could complete (#​15553) - 🔗 Dashboard resource URLs — The describe command no longer produces broken dashboard links with a stray /login?t=... in the path (#​15495) - 🌍 Guest AppHost env vars — Launch profile environment variables are now correctly forwarded to guest AppHosts (#​15637) - 📦 Legacy settings migration — .aspire/settings.json → aspire.config.json migration was silently skipped in some scenarios; now works reliably (#​15526) - 🔧 TypeScript AppHost restore — Fixed config resolution during TS AppHost restore (#​15625) - 🎭 Playwright CLI on Windows — aspire agent init now correctly installs playwright-cli on Windows (#​15559) - 📌 Emulator stability — Pinned Kusto emulator image and improved Cosmos DB emulator reliability (#​15504) ✨ Improvements - 🏗️ Brownfield TypeScript aspire init — Running aspire init in existing JS/TS projects now smartly merges package.json — scripts, dependencies, and engines — with semver-aware conflict handling (#​15123) - 🎯 Endpoint filtering — New ExcludeReferenceEndpoint property lets you filter specific endpoints from WithReference (#​15586) - 🌐 More polyglot ATS APIs — Exported additional hosting APIs for TypeScript and Go AppHost authoring (#​15557) - 🔍 Short trace ID support — The dashboard now resolves short trace IDs in addition to full-length ones (#​15613) - ⚠️ Aspire.Hosting.NodeJs deprecated — Use Aspire.Hosting.JavaScript instead; the old package no longer appears in aspire add (#​15686) ## 13.2.0 # Aspire 13.2 Aspire 13.2 brings major CLI enhancements, a new TypeScript AppHost (preview), dashboard data export/import, Microsoft Foundry integration, and multi-language improvements — all focused on making local development more streamlined for developers and AI coding agents alike. ## Highlights - 🛠️ CLI overhaul — New commands including **aspire start/stop/ps** for detached mode, **aspire describe** for resource monitoring, **aspire doctor** for environment diagnostics, **aspire secret** for managing user secrets, **aspire docs** for browsing documentation from the terminal, and **aspire agent** (renamed from **aspire mcp**) for AI agent integration. - 🌐 TypeScript AppHost (preview) — Write your apphost in TypeScript with **createBuilder()**, using the same app model concepts as C#. Full VS Code extension support included. - 🧩 VS Code extension — Dedicated Aspire Activity Bar panel with live resource state, inline CodeLens with health status and actions, gutter decorations, and a new Getting Started walkthrough. - 📊 Dashboard improvements — Bulk telemetry export/import, export environment variables as **.env** files, a new telemetry HTTP API, set parameters directly from the dashboard, and improved resource graph layout. - 🤖 Microsoft Foundry — Replaces Azure AI Foundry integration with broader **Aspire.Hosting.Foundry** support including hosted agents and model deployments. - 🔒 Azure Virtual Network & Private Endpoints — New **Aspire.Hosting.Azure.Network** integration for defining VNets, subnets, NAT gateways, NSGs, and private endpoints directly in your apphost. - 🐳 Docker Compose publishing — Generate docker-compose.yaml from your app model with **AddDockerComposeEnvironment.** - 📦 New integrations — Azure Data Lake Storage, MongoDB EF Core (**Aspire.MongoDB.EntityFrameworkCore**), Bun support for JS resources, and Certbot for automated SSL certificates. - ⚡ App model — **WithMcpServer** for declaring MCP endpoints, **rebuild** command for project resources, contextual endpoint resolution, and improved secret/certificate handling. ## ⚠️ Breaking changes Notable breaking changes include service discovery env vars now using endpoint scheme instead of name, aspire.config.json replacing split config files, AIFoundry → Foundry rename, WithSecretBuildArg → WithBuildSecret, and updated default Azure credential behavior. [See the full list of breaking changes](https://aspire.dev/whats-new/aspire-13-2/#%EF%B8%8F-breaking-changes). ## 📖 Learn more For the full details on everything in this release, check out the [What's new in Aspire 13.2](https://aspire.dev/whats-new/aspire-13-2/) documentation. Thank you to all the community contributors who helped make this release happen! 💜 ## 13.1.3 ## What's Changed * [release/13.1] Add installer publishing updates for 13.1.3 by @​radical in https://github.com/dotnet/aspire/pull/15158 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.1.2...v13.1.3 ## 13.1.2 ## What's Changed * Bump patch version from 13.1.1 to 13.1.2 by @​Copilot in https://github.com/dotnet/aspire/pull/14699 * [release/13.1] Fix template version parsing for .NET 10.0 SDK separator change by @​JamesNK in https://github.com/dotnet/aspire/pull/14698 * Update pipeline images to non-deprecated pools by @​joperezr in https://github.com/dotnet/aspire/pull/14707 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.1.1...v13.1.2 ## 13.1.1 ## What's Changed * [release/13.1] Ensure WithHostHttpsPort works when chained inline by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13678 * [release/13.1] Escape backslashes in path string to discovered vite config by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13822 * [release/13.1] [Testing] Fixing bugs for sticky slot app settings by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13810 * [release/13.1] Fix AzureBicepResource file-not-found error when using templateFile with AzurePublishingContext by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/14018 * [release/13.1] Filter dev certs without X509SubjectKeyIdentifierExtension when any cert has it by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13676 * [release/13.1] Fix Aspire.ProjectTemplates build failure from command line length limits by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/14009 * [release/13.1] Update Azure.Identity package version to 1.17.1 by @​eerhardt in https://github.com/dotnet/aspire/pull/14251 * Bump patch version from 13.1.0 to 13.1.1 by @​Copilot in https://github.com/dotnet/aspire/pull/14329 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.1.0...v13.1.1 ## 13.1.0 We are excited to share that our 13.1.0 release of Aspire has shipped! All of the packages are available in NuGet.org now. Head over to https://aspire.dev/whats-new/aspire-13-1/ to find what's new in 13.1.0! ## What's Changed * Target net10.0 in client integrations by @​eerhardt in https://github.com/dotnet/aspire/pull/12500 * Fix DockerComposeEnvironment duplicating image names in .env file by @​Copilot in https://github.com/dotnet/aspire/pull/12310 * Replace apt-get with npm for Azure Functions Core Tools installation by @​Copilot in https://github.com/dotnet/aspire/pull/12537 * Improve flaky dashboard integration test by @​JamesNK in https://github.com/dotnet/aspire/pull/12534 * Add README.md for the Aspire.Hosting.Azure.AppService package by @​ShilpiRach in https://github.com/dotnet/aspire/pull/12528 * Add support to enable automatic scaling for App Service Environment by @​ShilpiRach in https://github.com/dotnet/aspire/pull/12305 * Update to FluentUI 4.13.1 by @​JamesNK in https://github.com/dotnet/aspire/pull/12532 * Skip playground projects in build-packages workflow by @​Copilot in https://github.com/dotnet/aspire/pull/12547 * Allow HostUrl to remap both address and port by @​danegsta in https://github.com/dotnet/aspire/pull/12521 * Refactor NodeJs Integration by @​eerhardt in https://github.com/dotnet/aspire/pull/12530 * Fix MCP endpoint with redirect HTTPS by @​JamesNK in https://github.com/dotnet/aspire/pull/12556 * [main] Update dependencies from microsoft/usvc-apiserver by @​dotnet-maestro[bot] in https://github.com/dotnet/aspire/pull/12540 * Refactor AddNodeApp by @​eerhardt in https://github.com/dotnet/aspire/pull/12538 * Update Aspire branding from 13.0 to 13.1 by @​Copilot in https://github.com/dotnet/aspire/pull/12527 * Add annotation to specify custom base images for generated Dockerfiles by @​Copilot in https://github.com/dotnet/aspire/pull/12566 * Fix generating random MCP endpoint URL in templates by @​JamesNK in https://github.com/dotnet/aspire/pull/12558 * [CI] Add new Agent for disabling or quarantining tests by @​radical in https://github.com/dotnet/aspire/pull/12570 * Add `ExcludeFromMcp()` resource extension by @​JamesNK in https://github.com/dotnet/aspire/pull/12515 * Localized file check-in by OneLocBuild Task: Build definition ID 1309: Build ID 2828818 by @​dotnet-bot in https://github.com/dotnet/aspire/pull/12546 * Register IPipelineOutputService in DI for pipeline output directory management by @​Copilot in https://github.com/dotnet/aspire/pull/12563 * Add deploy support for Docker Compose by @​captainsafia in https://github.com/dotnet/aspire/pull/12548 * Quarantine flaky test: AzureServiceBusEmulatorResourceGeneratesConfigJsonWithCustomizations by @​Copilot in https://github.com/dotnet/aspire/pull/12578 * Update connection properties for non-Azure resources by @​sebastienros in https://github.com/dotnet/aspire/pull/12583 * Filter to highest package version per channel in aspire add command by @​Copilot in https://github.com/dotnet/aspire/pull/12553 * Log DCP messages at Debug/Trace level in AppHost by @​Copilot in https://github.com/dotnet/aspire/pull/12533 * Add CLI self-update prompts to `aspire update` command by @​Copilot in https://github.com/dotnet/aspire/pull/12395 * Fix golang and alpine images. by @​mitchdenny in https://github.com/dotnet/aspire/pull/12592 * Replace ContainerTargetPlatform.AllLinux with LinuxAmd64 by @​Copilot in https://github.com/dotnet/aspire/pull/12596 * [main] Update dependencies from microsoft/usvc-apiserver by @​dotnet-maestro[bot] in https://github.com/dotnet/aspire/pull/12610 * Make IReportingStep and IReportingTask completion idempotent by @​Copilot in https://github.com/dotnet/aspire/pull/12602 * Show --log-level debug hint when pipeline fails by @​Copilot in https://github.com/dotnet/aspire/pull/12603 * [main] Update dependencies from dotnet/arcade by @​dotnet-maestro[bot] in https://github.com/dotnet/aspire/pull/12622 * Rename app.py to main.py in template by @​eerhardt in https://github.com/dotnet/aspire/pull/12628 * bump extension version by @​adamint in https://github.com/dotnet/aspire/pull/12623 * don't build apphost in cli when running in extension by @​adamint in https://github.com/dotnet/aspire/pull/12621 * Detect which version of yarn is being used by @​eerhardt in https://github.com/dotnet/aspire/pull/12633 * Fix duplicate key exception when using WithExplicitStart() on resources with environment callbacks by @​Copilot in https://github.com/dotnet/aspire/pull/12604 * Support AddCSharpApp, fix some rough edges around project resources by @​adamint in https://github.com/dotnet/aspire/pull/12568 * Add missing namespace to `CertificateAuthorityCollectionResource` by @​danegsta in https://github.com/dotnet/aspire/pull/12639 * Add ModelContextProtocol assemblies to signing list by @​joperezr in https://github.com/dotnet/aspire/pull/12637 * Generate fallback Dockerfile for Python apps without UV by @​Copilot in https://github.com/dotnet/aspire/pull/12627 * Update/bump container image tags for hosting components by @​joperezr in https://github.com/dotnet/aspire/pull/12459 * Mark IDeveloperCertificateService experimental by @​danegsta in https://github.com/dotnet/aspire/pull/12648 * Wait with exponential backoff for expected Executables by @​karolz-ms in https://github.com/dotnet/aspire/pull/12647 * Make ProcessCertificateTrustConfigAsync internal by @​danegsta in https://github.com/dotnet/aspire/pull/12649 * Add test cases and ensure container cert override paths work by @​danegsta in https://github.com/dotnet/aspire/pull/12654 * Python hosting: Support .venv lookup by walking up parent directories by @​Copilot in https://github.com/dotnet/aspire/pull/12616 ... (truncated) ## 13.0.2 This patch is updating our Project Templates for our Python starter app to ensure we depend on the latest version of React. This is out of an abundance of caution, as we don't depend on any of the react packages that were flagged as vulnerable in https://github.com/advisories/GHSA-fv66-9v8q-g76r. ## What's Changed * Bump patch version from 13.0.1 to 13.0.2 by @​Copilot in https://github.com/dotnet/aspire/pull/13324 * Update React and ReactDOM to version 19.2.1 across all projects by @​joperezr in https://github.com/dotnet/aspire/pull/13325 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.0.1...v13.0.2 ## 13.0.1 ## What's Changed * Merge internal changes by @​joperezr in https://github.com/dotnet/aspire/pull/12896 * [release/13.0] Fix Azure roles resources always redeploying by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/12903 * [release/13.0] Remove .py and .js files from being signed (#​13005) by @​eerhardt in https://github.com/dotnet/aspire/pull/13032 * [release/13.0] Fix subscription ID not being disabled on Azure provisioning dialog by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/12913 * [release/13.0] Default OpenAISettings.EnableSensitiveTelemetryData to TelemetryHelpers.EnableSensitiveDataDefault by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13017 * Bump patch version from 13.0.0 to 13.0.1 by @​Copilot in https://github.com/dotnet/aspire/pull/13167 * [release/13.0] EndpointReference evaluation should wait on missing AllocatedEndpoint (#​13074) by @​karolz-ms in https://github.com/dotnet/aspire/pull/13076 * [release/13.0] Update to Npgsql 10 by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13166 * [release/13.0] Update dependencies from microsoft/usvc-apiserver by @​danegsta in https://github.com/dotnet/aspire/pull/13187 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.0.0...v13.0.1 ## 13.0.0 We are excited to share that our 13.0.0 release of Aspire has shipped! All of the packages are available in NuGet.org now. Head over to https://aspire.dev/whats-new/aspire-13/ to find what's new in 13.0.0! ## New Contributors * @​jomaxso made their first contribution in https://github.com/dotnet/aspire/pull/11840 * @​jguadagno made their first contribution in https://github.com/dotnet/aspire/pull/11876 * @​foxminchan made their first contribution in https://github.com/dotnet/aspire/pull/11700 * @​yreynhout made their first contribution in https://github.com/dotnet/aspire/pull/12087 **Full Changelog**: https://github.com/dotnet/aspire/compare/v9.5.0...v13.0.0 ## 9.5.2 ## What's Changed * [release/9.5] Revert SQL Server container image tag from 2025-latest to 2022-latest for Mac ARM compatibility by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/11908 * [release/9.5] Ensure OutputPath is created in ResourceContainerImageBuilder by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/11886 * [release/9.5] Add configuration to suppress unsecured telemetry message in dashboard by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/11954 * [release/9.5] Update dependencies from https://github.com/microsoft/usvc-apiserver build 0.17.3 by @​danegsta in https://github.com/dotnet/aspire/pull/12032 * [release/9.5] Multi-target RabbitMQ and Redis client libraries by @​eerhardt in https://github.com/dotnet/aspire/pull/12138 * Backport PR #​11951: Add noProfileSwitch to run command in DotNetCliRunner by @​Copilot in https://github.com/dotnet/aspire/pull/11959 * Bump patch version to 9.5.2 by @​Copilot in https://github.com/dotnet/aspire/pull/12139 **Full Changelog**: https://github.com/dotnet/aspire/compare/v9.5.1...v9.5.2 Commits viewable in [compare view](https://github.com/microsoft/aspire/compare/v9.5.1...v13.3.0).
[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Aspire.Azure.Search.Documents&package-manager=nuget&previous-version=9.5.1&new-version=13.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> --- dotnet/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index f1b61aaaa97f..459be834f13c 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -6,7 +6,7 @@ - + From 13f812b825aaa021505bfbc73239cdb163bddc2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:20:12 +0000 Subject: [PATCH 10/33] Python: Update pymongo requirement from <4.16,>=4.8.0 to >=4.8.0,<4.17 in /python (#13866) Updates the requirements on [pymongo](https://github.com/mongodb/mongo-python-driver) to permit the latest version.
Release notes

Sourced from pymongo's releases.

PyMongo 4.16.0

Community notes:

Changelog

Sourced from pymongo's changelog.

Changes in Version 4.16.0 (2026/01/07)

PyMongo 4.16 brings a number of changes including:

  • Removed invalid documents from :class:bson.errors.InvalidDocument error messages as doing so may leak sensitive user data. Instead, invalid documents are stored in :attr:bson.errors.InvalidDocument.document.
  • PyMongo now requires dnspython>=2.6.1, since dnspython 1.0 is no longer maintained. The minimum version is 2.6.1 to account for CVE-2023-29483 <https://www.cve.org/CVERecord?id=CVE-2023-29483>_.
  • Removed support for Eventlet. Eventlet is actively being sunset by its maintainers and has compatibility issues with PyMongo's dnspython dependency.
  • Use Zstandard support from the standard library for Python 3.14+, and use backports.zstd for older versions.
  • Fixed return type annotation for find_one_and_* methods on :class:~pymongo.asynchronous.collection.AsyncCollection and :class:~pymongo.synchronous.collection.Collection to include None.
  • Added support for NumPy 1D-arrays in :class:bson.binary.BinaryVector.
  • Prevented :class:~pymongo.encryption.ClientEncryption from loading the crypt shared library to fix "MongoCryptError: An existing crypt_shared library is loaded by the application" unless the linked library search path is set.

Changes in Version 4.15.5 (2025/12/02)

Version 4.15.5 is a bug fix release.

  • Fixed a bug that could cause AutoReconnect("connection pool paused") errors when cursors fetched more documents from the database after SDAM heartbeat failures.

Changes in Version 4.15.4 (2025/10/21)

Version 4.15.4 is a bug fix release.

  • Relaxed the callback type of :meth:~pymongo.asynchronous.client_session.AsyncClientSession.with_transaction to allow the broader Awaitable type rather than only Coroutine objects.
  • Added the missing Python 3.14 trove classifier to the package metadata.

Issues Resolved ...............

See the PyMongo 4.15.4 release notes in JIRA_ for the list of resolved issues in this release.

.. _PyMongo 4.15.4 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=47237

Changes in Version 4.15.3 (2025/10/07)

Version 4.15.3 is a bug fix release.

  • Fixed a memory leak when raising :class:bson.errors.InvalidDocument with C extensions.
  • Fixed the return type of the :meth:~pymongo.asynchronous.collection.AsyncCollection.distinct,

... (truncated)

Commits
  • 3290101 Prepare 4.16.0 release (#2672)
  • 1be94d2 PYTHON-5685 Fix unified spec sync metadata for csot and sessions tests (#2669)
  • 6585d9c PYTHON-2442: Refactor: use _asdict() in _options_dict() (#2670)
  • fdb1f7e PYTHON-5677 Prevent ClientEncryption from loading crypt shared library (#2659)
  • 0cd9763 Bump zizmorcore/zizmor-action from cb3d8e846e148d1111d90b03375b9c03deceda37 t...
  • 2f263d4 PYTHON-5680 Fix handling of expectedDocuments in Unified Test Runner (#2665)
  • e9658b2 Add 4.15.5 release date to changelog (#2666)
  • 10dd204 Update coverage[toml] requirement from <=7.10.6,>=5 to >=5,<=7.10.7 (#2662)
  • 1300677 [Spec Resync] 12-22-2025 (#2663)
  • 18c1f14 PYTHON-5529 Introduce optin setting to await for MinPoolSize population (#2664)
  • Additional commits viewable in compare view

You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: moonbox3 <35585003+moonbox3@users.noreply.github.com> --- python/pyproject.toml | 2 +- python/uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index b93a9083d533..de05937e93d2 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -106,7 +106,7 @@ mistralai = [ "mistralai >= 1.2,< 2.4.6" ] mongo = [ - "pymongo >= 4.8.0, < 4.16", + "pymongo >= 4.8.0, < 4.17", "motor >= 3.3.2,< 3.8.0" ] notebooks = [ diff --git a/python/uv.lock b/python/uv.lock index c6a7b77b9c19..dc5fc3313a7d 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -6532,7 +6532,7 @@ requires-dist = [ { name = "pydantic", specifier = ">=2.0,!=2.10.0,!=2.10.1,!=2.10.2,!=2.10.3,<2.14" }, { name = "pydantic-settings", specifier = "~=2.0" }, { name = "pymilvus", marker = "extra == 'milvus'", specifier = ">=2.3,<2.7" }, - { name = "pymongo", marker = "extra == 'mongo'", specifier = ">=4.8.0,<4.16" }, + { name = "pymongo", marker = "extra == 'mongo'", specifier = ">=4.8.0,<4.17" }, { name = "pyodbc", marker = "extra == 'sql'", specifier = ">=5.2" }, { name = "qdrant-client", marker = "extra == 'qdrant'", specifier = "~=1.9" }, { name = "redis", extras = ["hiredis"], marker = "extra == 'redis'", specifier = ">=6,<8" }, From 20be253d7b4a41c8943f36addd8b6365bdcf7299 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:47:52 +0000 Subject: [PATCH 11/33] .Net: Bump esbuild, @vitejs/plugin-react, vite, and transitive lockfile deps in /dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend (#14070) ### Motivation and Context This PR updates the ReactFrontend build toolchain dependencies and also resolves additional Dependabot alerts that target the same frontend lockfile manifests. ### Description - Removes `esbuild` (no longer directly used) - Updates `@vitejs/plugin-react` from `4.3.4` to `6.0.2` - Updates `vite` from `6.4.1` to `8.0.16` - Updates transitive lockfile entries in `package-lock.json` and `yarn.lock` for: - `js-yaml` to `4.2.0` - `ws` to `7.5.11` - `mdast-util-to-hast` to `13.2.1` These dependency updates were kept scoped to `dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend`. ### Contribution Checklist - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone :smile: --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com> --- .../package-lock.json | 1733 +++-------------- .../package.json | 4 +- .../yarn.lock | 815 ++------ 3 files changed, 389 insertions(+), 2163 deletions(-) diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json index a2c8a6da6e7b..98663274936a 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json @@ -25,763 +25,42 @@ "@protobuf-ts/plugin": "^2.9.6", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^4.3.4", + "@vitejs/plugin-react": "^6.0.2", "eslint": "^9.21.0", "eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-react-refresh": "^0.4.19", "globals": "^15.15.0", "typescript": "~5.7.2", "typescript-eslint": "^8.24.1", - "vite": "^6.4.1" + "vite": "^8.0.16" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.27.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", - "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", - "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@ctrl/tinycolor": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", - "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/@emotion/hash": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", - "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", - "license": "MIT" - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", - "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@babel/runtime": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", - "cpu": [ - "ia32" - ], - "dev": true, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" }, "node_modules/@eslint-community/eslint-utils": { "version": "4.5.1", @@ -2643,59 +1922,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@microsoft/signalr": { "version": "8.0.7", "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-8.0.7.tgz", @@ -2747,6 +1973,16 @@ "node": ">= 8" } }, + "node_modules/@oxc-project/types": { + "version": "0.133.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", + "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@protobuf-ts/grpcweb-transport": { "version": "2.9.6", "resolved": "https://registry.npmjs.org/@protobuf-ts/grpcweb-transport/-/grpcweb-transport-2.9.6.tgz", @@ -2839,337 +2075,67 @@ "@protobuf-ts/runtime": "^2.9.6" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.39.0.tgz", - "integrity": "sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.39.0.tgz", - "integrity": "sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.39.0.tgz", - "integrity": "sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.39.0.tgz", - "integrity": "sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.39.0.tgz", - "integrity": "sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.39.0.tgz", - "integrity": "sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", + "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.39.0.tgz", - "integrity": "sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.39.0.tgz", - "integrity": "sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.39.0.tgz", - "integrity": "sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.39.0.tgz", - "integrity": "sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.39.0.tgz", - "integrity": "sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.39.0.tgz", - "integrity": "sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==", - "cpu": [ - "ppc64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.39.0.tgz", - "integrity": "sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", + "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", "cpu": [ - "riscv64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.39.0.tgz", - "integrity": "sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==", - "cpu": [ - "riscv64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.39.0.tgz", - "integrity": "sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==", - "cpu": [ - "s390x" - ], + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "license": "MIT" }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.53.3", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", - "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.39.0.tgz", - "integrity": "sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.39.0.tgz", - "integrity": "sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.39.0.tgz", - "integrity": "sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.39.0.tgz", - "integrity": "sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@swc/helpers": { - "version": "0.5.17", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", - "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/babel__traverse": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", - "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", - "dev": true, - "license": "MIT", + "node_modules/@swc/helpers": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", + "license": "Apache-2.0", "dependencies": { - "@babel/types": "^7.20.7" + "tslib": "^2.8.0" } }, "node_modules/@types/debug": { @@ -3477,23 +2443,29 @@ "license": "ISC" }, "node_modules/@vitejs/plugin-react": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", - "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.2.tgz", + "integrity": "sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.26.0", - "@babel/plugin-transform-react-jsx-self": "^7.25.9", - "@babel/plugin-transform-react-jsx-source": "^7.25.9", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.2" + "@rolldown/pluginutils": "^1.0.0" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + } } }, "node_modules/abort-controller": { @@ -3629,39 +2601,6 @@ "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -3685,27 +2624,6 @@ "node": ">=6" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001712", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001712.tgz", - "integrity": "sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, "node_modules/ccount": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", @@ -3822,13 +2740,6 @@ "dev": true, "license": "MIT" }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -3905,6 +2816,16 @@ "node": ">=6" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -3932,13 +2853,6 @@ "node": ">= 0.4" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.134", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.134.tgz", - "integrity": "sha512-zSwzrLg3jNP3bwsLqWHmS5z2nIOQ5ngMnfMZOWWtXnqqQkPVyOipxK98w+1beLw1TB+EImPNcG8wVP/cLVs2Og==", - "dev": true, - "license": "ISC" - }, "node_modules/embla-carousel": { "version": "8.6.0", "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", @@ -4008,57 +2922,6 @@ "node": ">= 0.4" } }, - "node_modules/esbuild": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", - "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.2", - "@esbuild/android-arm": "0.25.2", - "@esbuild/android-arm64": "0.25.2", - "@esbuild/android-x64": "0.25.2", - "@esbuild/darwin-arm64": "0.25.2", - "@esbuild/darwin-x64": "0.25.2", - "@esbuild/freebsd-arm64": "0.25.2", - "@esbuild/freebsd-x64": "0.25.2", - "@esbuild/linux-arm": "0.25.2", - "@esbuild/linux-arm64": "0.25.2", - "@esbuild/linux-ia32": "0.25.2", - "@esbuild/linux-loong64": "0.25.2", - "@esbuild/linux-mips64el": "0.25.2", - "@esbuild/linux-ppc64": "0.25.2", - "@esbuild/linux-riscv64": "0.25.2", - "@esbuild/linux-s390x": "0.25.2", - "@esbuild/linux-x64": "0.25.2", - "@esbuild/netbsd-arm64": "0.25.2", - "@esbuild/netbsd-x64": "0.25.2", - "@esbuild/openbsd-arm64": "0.25.2", - "@esbuild/openbsd-x64": "0.25.2", - "@esbuild/sunos-x64": "0.25.2", - "@esbuild/win32-arm64": "0.25.2", - "@esbuild/win32-ia32": "0.25.2", - "@esbuild/win32-x64": "0.25.2" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -4420,9 +3283,7 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", - "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "version": "1.15.11", "funding": [ { "type": "individual", @@ -4440,36 +3301,19 @@ } }, "node_modules/form-data": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", - "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "version": "4.0.5", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.4", - "mime-types": "^2.1.35" + "hasown": "^2.0.2", + "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -4479,16 +3323,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -4609,9 +3443,9 @@ } }, "node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -4809,18 +3643,21 @@ "dev": true, "license": "ISC" }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -4829,19 +3666,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -4863,19 +3687,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/keyborg": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.6.0.tgz", @@ -4906,6 +3717,78 @@ "node": ">= 0.8.0" } }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -4939,16 +3822,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -5057,9 +3930,9 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -5588,8 +4461,6 @@ }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -5618,9 +4489,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true, "funding": [ { @@ -5663,13 +4534,6 @@ } } }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, - "license": "MIT" - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -5799,9 +4663,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -5819,7 +4683,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5955,16 +4819,6 @@ "react": ">=18" } }, - "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", @@ -6031,59 +4885,39 @@ "node": ">=0.10.0" } }, - "node_modules/rollup": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.39.0.tgz", - "integrity": "sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==", + "node_modules/rolldown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", + "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.7" + "@oxc-project/types": "=0.133.0", + "@rolldown/pluginutils": "^1.0.0" }, "bin": { - "rollup": "dist/bin/rollup" + "rolldown": "bin/cli.mjs" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.39.0", - "@rollup/rollup-android-arm64": "4.39.0", - "@rollup/rollup-darwin-arm64": "4.39.0", - "@rollup/rollup-darwin-x64": "4.39.0", - "@rollup/rollup-freebsd-arm64": "4.39.0", - "@rollup/rollup-freebsd-x64": "4.39.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.39.0", - "@rollup/rollup-linux-arm-musleabihf": "4.39.0", - "@rollup/rollup-linux-arm64-gnu": "4.39.0", - "@rollup/rollup-linux-arm64-musl": "4.39.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.39.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.39.0", - "@rollup/rollup-linux-riscv64-gnu": "4.39.0", - "@rollup/rollup-linux-riscv64-musl": "4.39.0", - "@rollup/rollup-linux-s390x-gnu": "4.39.0", - "@rollup/rollup-linux-x64-gnu": "4.39.0", - "@rollup/rollup-linux-x64-musl": "4.39.0", - "@rollup/rollup-win32-arm64-msvc": "4.39.0", - "@rollup/rollup-win32-ia32-msvc": "4.39.0", - "@rollup/rollup-win32-x64-msvc": "4.39.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.39.0.tgz", - "integrity": "sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "@rolldown/binding-android-arm64": "1.0.3", + "@rolldown/binding-darwin-arm64": "1.0.3", + "@rolldown/binding-darwin-x64": "1.0.3", + "@rolldown/binding-freebsd-x64": "1.0.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", + "@rolldown/binding-linux-arm64-gnu": "1.0.3", + "@rolldown/binding-linux-arm64-musl": "1.0.3", + "@rolldown/binding-linux-ppc64-gnu": "1.0.3", + "@rolldown/binding-linux-s390x-gnu": "1.0.3", + "@rolldown/binding-linux-x64-gnu": "1.0.3", + "@rolldown/binding-linux-x64-musl": "1.0.3", + "@rolldown/binding-openharmony-arm64": "1.0.3", + "@rolldown/binding-wasm32-wasi": "1.0.3", + "@rolldown/binding-win32-arm64-msvc": "1.0.3", + "@rolldown/binding-win32-x64-msvc": "1.0.3" + } }, "node_modules/rtl-css-js": { "version": "1.16.1", @@ -6124,16 +4958,6 @@ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/set-cookie-parser": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", @@ -6261,14 +5085,14 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -6296,9 +5120,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -6527,37 +5351,6 @@ "node": ">= 4.0.0" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -6629,24 +5422,23 @@ } }, "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "version": "8.0.16", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz", + "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.15", + "rolldown": "1.0.3", + "tinyglobby": "^0.2.17" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -6655,14 +5447,15 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -6671,13 +5464,16 @@ "@types/node": { "optional": true }, - "jiti": { + "@vitejs/devtools": { "optional": true }, - "less": { + "esbuild": { + "optional": true + }, + "jiti": { "optional": true }, - "lightningcss": { + "less": { "optional": true }, "sass": { @@ -6703,28 +5499,10 @@ } } }, - "node_modules/vite/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, "node_modules/vite/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -6777,9 +5555,9 @@ } }, "node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz", + "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==", "license": "MIT", "engines": { "node": ">=8.3.0" @@ -6797,13 +5575,6 @@ } } }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package.json b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package.json index 046283fa6634..ddf690c6c514 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package.json +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package.json @@ -27,13 +27,13 @@ "@protobuf-ts/plugin": "^2.9.6", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^4.3.4", + "@vitejs/plugin-react": "^6.0.2", "eslint": "^9.21.0", "eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-react-refresh": "^0.4.19", "globals": "^15.15.0", "typescript": "~5.7.2", "typescript-eslint": "^8.24.1", - "vite": "^6.4.1" + "vite": "^8.0.16" } } \ No newline at end of file diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock index c5946becc005..16779dcd3b6d 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock @@ -2,137 +2,6 @@ # yarn lockfile v1 -"@ampproject/remapping@^2.2.0": - version "2.3.0" - resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@babel/code-frame@^7.26.2": - version "7.26.2" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz" - integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== - dependencies: - "@babel/helper-validator-identifier" "^7.25.9" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/compat-data@^7.26.8": - version "7.26.8" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz" - integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== - -"@babel/core@^7.26.0": - version "7.26.10" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz" - integrity sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.10" - "@babel/helper-compilation-targets" "^7.26.5" - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helpers" "^7.26.10" - "@babel/parser" "^7.26.10" - "@babel/template" "^7.26.9" - "@babel/traverse" "^7.26.10" - "@babel/types" "^7.26.10" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/generator@^7.26.10", "@babel/generator@^7.27.0": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz" - integrity sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw== - dependencies: - "@babel/parser" "^7.27.0" - "@babel/types" "^7.27.0" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^3.0.2" - -"@babel/helper-compilation-targets@^7.26.5": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz" - integrity sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA== - dependencies: - "@babel/compat-data" "^7.26.8" - "@babel/helper-validator-option" "^7.25.9" - browserslist "^4.24.0" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-module-imports@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz" - integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== - dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helper-module-transforms@^7.26.0": - version "7.26.0" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz" - integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/helper-plugin-utils@^7.25.9": - version "7.26.5" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz" - integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== - -"@babel/helper-string-parser@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz" - integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== - -"@babel/helper-validator-identifier@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz" - integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== - -"@babel/helper-validator-option@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz" - integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== - -"@babel/helpers@^7.26.10": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz" - integrity sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg== - dependencies: - "@babel/template" "^7.27.0" - "@babel/types" "^7.27.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.26.10", "@babel/parser@^7.27.0": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz" - integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg== - dependencies: - "@babel/types" "^7.27.0" - -"@babel/plugin-transform-react-jsx-self@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz" - integrity sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-react-jsx-source@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz" - integrity sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/runtime@^7.1.2": version "7.27.0" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz" @@ -140,36 +9,6 @@ dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.26.9", "@babel/template@^7.27.0": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz" - integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/parser" "^7.27.0" - "@babel/types" "^7.27.0" - -"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz" - integrity sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.27.0" - "@babel/parser" "^7.27.0" - "@babel/template" "^7.27.0" - "@babel/types" "^7.27.0" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.27.0": - version "7.27.0" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz" - integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg== - dependencies: - "@babel/helper-string-parser" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@ctrl/tinycolor@^3.3.4": version "3.6.1" resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz" @@ -180,131 +19,6 @@ resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz" integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g== -"@esbuild/aix-ppc64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz#b87036f644f572efb2b3c75746c97d1d2d87ace8" - integrity sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag== - -"@esbuild/android-arm64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz#5ca7dc20a18f18960ad8d5e6ef5cf7b0a256e196" - integrity sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w== - -"@esbuild/android-arm@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.2.tgz#3c49f607b7082cde70c6ce0c011c362c57a194ee" - integrity sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA== - -"@esbuild/android-x64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.2.tgz#8a00147780016aff59e04f1036e7cb1b683859e2" - integrity sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg== - -"@esbuild/darwin-arm64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz#486efe7599a8d90a27780f2bb0318d9a85c6c423" - integrity sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA== - -"@esbuild/darwin-x64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz#95ee222aacf668c7a4f3d7ee87b3240a51baf374" - integrity sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA== - -"@esbuild/freebsd-arm64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz#67efceda8554b6fc6a43476feba068fb37fa2ef6" - integrity sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w== - -"@esbuild/freebsd-x64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz#88a9d7ecdd3adadbfe5227c2122d24816959b809" - integrity sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ== - -"@esbuild/linux-arm64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz#87be1099b2bbe61282333b084737d46bc8308058" - integrity sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g== - -"@esbuild/linux-arm@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz#72a285b0fe64496e191fcad222185d7bf9f816f6" - integrity sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g== - -"@esbuild/linux-ia32@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz#337a87a4c4dd48a832baed5cbb022be20809d737" - integrity sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ== - -"@esbuild/linux-loong64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz#1b81aa77103d6b8a8cfa7c094ed3d25c7579ba2a" - integrity sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w== - -"@esbuild/linux-mips64el@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz#afbe380b6992e7459bf7c2c3b9556633b2e47f30" - integrity sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q== - -"@esbuild/linux-ppc64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz#6bf8695cab8a2b135cca1aa555226dc932d52067" - integrity sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g== - -"@esbuild/linux-riscv64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz#43c2d67a1a39199fb06ba978aebb44992d7becc3" - integrity sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw== - -"@esbuild/linux-s390x@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz#419e25737ec815c6dce2cd20d026e347cbb7a602" - integrity sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q== - -"@esbuild/linux-x64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz#22451f6edbba84abe754a8cbd8528ff6e28d9bcb" - integrity sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg== - -"@esbuild/netbsd-arm64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz#744affd3b8d8236b08c5210d828b0698a62c58ac" - integrity sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw== - -"@esbuild/netbsd-x64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz#dbbe7521fd6d7352f34328d676af923fc0f8a78f" - integrity sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg== - -"@esbuild/openbsd-arm64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz#f9caf987e3e0570500832b487ce3039ca648ce9f" - integrity sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg== - -"@esbuild/openbsd-x64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz#d2bb6a0f8ffea7b394bb43dfccbb07cabd89f768" - integrity sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw== - -"@esbuild/sunos-x64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz#49b437ed63fe333b92137b7a0c65a65852031afb" - integrity sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA== - -"@esbuild/win32-arm64@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz#081424168463c7d6c7fb78f631aede0c104373cf" - integrity sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q== - -"@esbuild/win32-ia32@0.25.2": - version "0.25.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz#3f9e87143ddd003133d21384944a6c6cadf9693f" - integrity sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg== - -"@esbuild/win32-x64@0.25.2": - version "0.25.2" - resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz" - integrity sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA== - "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.5.1" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz" @@ -360,7 +74,7 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.24.0", "@eslint/js@^9.21.0": +"@eslint/js@^9.21.0", "@eslint/js@9.24.0": version "9.24.0" resolved "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz" integrity sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA== @@ -390,7 +104,7 @@ resolved "https://registry.npmjs.org/@floating-ui/devtools/-/devtools-0.2.3.tgz" integrity sha512-ZTcxTvgo9CRlP7vJV62yCxdqmahHTGpSTi5QaTDgGoyQq0OyjaVZhUhXv/qdkQFOI3Sxlfmz0XGG4HaZMsDf8Q== -"@floating-ui/dom@^1.6.12": +"@floating-ui/dom@^1.0.0", "@floating-ui/dom@^1.6.12": version "1.6.13" resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz" integrity sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w== @@ -621,7 +335,7 @@ "@griffel/react" "^1.5.32" "@swc/helpers" "^0.5.1" -"@fluentui/react-components@^9.72.7": +"@fluentui/react-components@^9.72.7", "@fluentui/react-components@>=9.70.0 <10.0.0": version "9.72.7" resolved "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.72.7.tgz" integrity sha512-tuC8ZMBQicF4p+f9MJv9cVYZUSktQVreAGJq/YJxQ0Ts1mO2rnAuIBkBFlgjnjyebDiAO1FoAAz/wW99hrIh6A== @@ -761,7 +475,7 @@ "@griffel/react" "^1.5.32" "@swc/helpers" "^0.5.1" -"@fluentui/react-icons@^2.0.237", "@fluentui/react-icons@^2.0.239", "@fluentui/react-icons@^2.0.245": +"@fluentui/react-icons@^2.0.237", "@fluentui/react-icons@^2.0.239", "@fluentui/react-icons@^2.0.245", "@fluentui/react-icons@>=2.0.204 <3.0.0": version "2.0.315" resolved "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.315.tgz" integrity sha512-IITWAQGgU7I32eHPDHi+TUCUF6malP27wZLUV3bqjGVF/x/lfxvTIx8yqv/cxuwF3+ITGFDpl+278ZYJtOI7ww== @@ -1496,38 +1210,6 @@ resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz" integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.8" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz" - integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.5.0" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== - -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - "@microsoft/signalr@^8.0.7": version "8.0.7" resolved "https://registry.npmjs.org/@microsoft/signalr/-/signalr-8.0.7.tgz" @@ -1547,7 +1229,7 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== @@ -1560,6 +1242,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@oxc-project/types@=0.133.0": + version "0.133.0" + resolved "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz" + integrity sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA== + "@protobuf-ts/grpcweb-transport@^2.9.6": version "2.9.6" resolved "https://registry.npmjs.org/@protobuf-ts/grpcweb-transport/-/grpcweb-transport-2.9.6.tgz" @@ -1604,116 +1291,26 @@ resolved "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.9.6.tgz" integrity sha512-C0CfpKx4n4LBbUrajOdRj2BTbd3qBoK0SiKWLq7RgCoU6xiN4wesBMFHUOBp3fFzKeZwgU8Q2KtzaqzIvPLRXg== -"@rollup/rollup-android-arm-eabi@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz#7e478b66180c5330429dd161bf84dad66b59c8eb" - integrity sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w== - -"@rollup/rollup-android-arm64@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz#2b025510c53a5e3962d3edade91fba9368c9d71c" - integrity sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w== - -"@rollup/rollup-darwin-arm64@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz#3577c38af68ccf34c03e84f476bfd526abca10a0" - integrity sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA== - -"@rollup/rollup-darwin-x64@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz#2bf5f2520a1f3b551723d274b9669ba5b75ed69c" - integrity sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ== - -"@rollup/rollup-freebsd-arm64@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz#4bb9cc80252564c158efc0710153c71633f1927c" - integrity sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w== - -"@rollup/rollup-freebsd-x64@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz#2301289094d49415a380cf942219ae9d8b127440" - integrity sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q== - -"@rollup/rollup-linux-arm-gnueabihf@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz#1d03d776f2065e09fc141df7d143476e94acca88" - integrity sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw== - -"@rollup/rollup-linux-arm-musleabihf@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz#8623de0e040b2fd52a541c602688228f51f96701" - integrity sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg== - -"@rollup/rollup-linux-arm64-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz#ce2d1999bc166277935dde0301cde3dd0417fb6e" - integrity sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w== - -"@rollup/rollup-linux-arm64-musl@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz#88c2523778444da952651a2219026416564a4899" - integrity sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A== - -"@rollup/rollup-linux-loong64-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz#578ca2220a200ac4226c536c10c8cc6e4f276714" - integrity sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g== - -"@rollup/rollup-linux-ppc64-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz#aa338d3effd4168a20a5023834a74ba2c3081293" - integrity sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw== - -"@rollup/rollup-linux-riscv64-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz#16ba582f9f6cff58119aa242782209b1557a1508" - integrity sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g== +"@rolldown/binding-linux-x64-gnu@1.0.3": + version "1.0.3" + resolved "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz" + integrity sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg== -"@rollup/rollup-linux-riscv64-musl@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz#e404a77ebd6378483888b8064c703adb011340ab" - integrity sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A== +"@rolldown/binding-linux-x64-musl@1.0.3": + version "1.0.3" + resolved "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz" + integrity sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow== -"@rollup/rollup-linux-s390x-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz#92ad52d306227c56bec43d96ad2164495437ffe6" - integrity sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg== +"@rolldown/pluginutils@^1.0.0": + version "1.0.1" + resolved "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz" + integrity sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw== "@rollup/rollup-linux-x64-gnu@4.53.3": version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz#fd0dea3bb9aa07e7083579f25e1c2285a46cb9fa" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz" integrity sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w== -"@rollup/rollup-linux-x64-musl@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz#37a3efb09f18d555f8afc490e1f0444885de8951" - integrity sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q== - -"@rollup/rollup-openharmony-arm64@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz#c489bec9f4f8320d42c9b324cca220c90091c1f7" - integrity sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw== - -"@rollup/rollup-win32-arm64-msvc@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz#152832b5f79dc22d1606fac3db946283601b7080" - integrity sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw== - -"@rollup/rollup-win32-ia32-msvc@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz#54d91b2bb3bf3e9f30d32b72065a4e52b3a172a5" - integrity sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA== - -"@rollup/rollup-win32-x64-gnu@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz#df9df03e61a003873efec8decd2034e7f135c71e" - integrity sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg== - -"@rollup/rollup-win32-x64-msvc@4.53.3": - version "4.53.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz#38ae84f4c04226c1d56a3b17296ef1e0460ecdfe" - integrity sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ== - "@swc/helpers@^0.5.1", "@swc/helpers@~0.5.11": version "0.5.17" resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz" @@ -1721,39 +1318,6 @@ dependencies: tslib "^2.8.0" -"@types/babel__core@^7.20.5": - version "7.20.5" - resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz" - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== - dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.27.0" - resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz" - integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.4" - resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz" - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*": - version "7.20.7" - resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz" - integrity sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng== - dependencies: - "@babel/types" "^7.20.7" - "@types/debug@^4.0.0": version "4.1.12" resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz" @@ -1773,11 +1337,6 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz" integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== -"@types/estree@1.0.8": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" - integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== - "@types/hast@^3.0.0": version "3.0.4" resolved "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz" @@ -1802,12 +1361,12 @@ resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz" integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== -"@types/react-dom@^19.2.3": +"@types/react-dom@^19.2.3", "@types/react-dom@>=16.8.0 <20.0.0", "@types/react-dom@>=16.9.0 <20.0.0": version "19.2.3" resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz" integrity sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ== -"@types/react@^19.2.7": +"@types/react@^19.2.0", "@types/react@^19.2.7", "@types/react@>=16.14.0 <20.0.0", "@types/react@>=16.8.0 <20.0.0", "@types/react@>=18": version "19.2.7" resolved "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz" integrity sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg== @@ -1839,7 +1398,7 @@ natural-compare "^1.4.0" ts-api-utils "^2.0.1" -"@typescript-eslint/parser@8.29.1": +"@typescript-eslint/parser@^8.0.0 || ^8.0.0-alpha.0", "@typescript-eslint/parser@8.29.1": version "8.29.1" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.29.1.tgz" integrity sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg== @@ -1910,16 +1469,12 @@ resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz" integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== -"@vitejs/plugin-react@^4.3.4": - version "4.3.4" - resolved "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz" - integrity sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug== +"@vitejs/plugin-react@^6.0.2": + version "6.0.2" + resolved "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.2.tgz" + integrity sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg== dependencies: - "@babel/core" "^7.26.0" - "@babel/plugin-transform-react-jsx-self" "^7.25.9" - "@babel/plugin-transform-react-jsx-source" "^7.25.9" - "@types/babel__core" "^7.20.5" - react-refresh "^0.14.2" + "@rolldown/pluginutils" "^1.0.0" abort-controller@^3.0.0: version "3.0.0" @@ -1933,7 +1488,7 @@ acorn-jsx@^5.3.2: resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.14.0: +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.14.0: version "8.14.1" resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz" integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== @@ -2006,16 +1561,6 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" -browserslist@^4.24.0: - version "4.24.4" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz" - integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== - dependencies: - caniuse-lite "^1.0.30001688" - electron-to-chromium "^1.5.73" - node-releases "^2.0.19" - update-browserslist-db "^1.1.1" - call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz" @@ -2029,11 +1574,6 @@ callsites@^3.0.0: resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -caniuse-lite@^1.0.30001688: - version "1.0.30001712" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001712.tgz" - integrity sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig== - ccount@^2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz" @@ -2096,11 +1636,6 @@ concat-map@0.0.1: resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" @@ -2115,7 +1650,7 @@ csstype@^3.1.3, csstype@^3.2.2: resolved "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz" integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ== -debug@^4.0.0, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@^4.0.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.4.0" resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz" integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== @@ -2144,6 +1679,11 @@ dequal@^2.0.0: resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== +detect-libc@^2.0.3: + version "2.1.2" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz" + integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + devlop@^1.0.0, devlop@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz" @@ -2160,11 +1700,6 @@ dunder-proto@^1.0.1: es-errors "^1.3.0" gopd "^1.2.0" -electron-to-chromium@^1.5.73: - version "1.5.134" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.134.tgz" - integrity sha512-zSwzrLg3jNP3bwsLqWHmS5z2nIOQ5ngMnfMZOWWtXnqqQkPVyOipxK98w+1beLw1TB+EImPNcG8wVP/cLVs2Og== - embla-carousel-autoplay@^8.5.1: version "8.6.0" resolved "https://registry.npmjs.org/embla-carousel-autoplay/-/embla-carousel-autoplay-8.6.0.tgz" @@ -2175,7 +1710,7 @@ embla-carousel-fade@^8.5.1: resolved "https://registry.npmjs.org/embla-carousel-fade/-/embla-carousel-fade-8.6.0.tgz" integrity sha512-qaYsx5mwCz72ZrjlsXgs1nKejSrW+UhkbOMwLgfRT7w2LtdEB03nPRI06GHuHv5ac2USvbEiX2/nAHctcDwvpg== -embla-carousel@^8.5.1: +embla-carousel@^8.5.1, embla-carousel@8.6.0: version "8.6.0" resolved "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz" integrity sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA== @@ -2207,42 +1742,6 @@ es-set-tostringtag@^2.1.0: has-tostringtag "^1.0.2" hasown "^2.0.2" -esbuild@^0.25.0: - version "0.25.2" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz" - integrity sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ== - optionalDependencies: - "@esbuild/aix-ppc64" "0.25.2" - "@esbuild/android-arm" "0.25.2" - "@esbuild/android-arm64" "0.25.2" - "@esbuild/android-x64" "0.25.2" - "@esbuild/darwin-arm64" "0.25.2" - "@esbuild/darwin-x64" "0.25.2" - "@esbuild/freebsd-arm64" "0.25.2" - "@esbuild/freebsd-x64" "0.25.2" - "@esbuild/linux-arm" "0.25.2" - "@esbuild/linux-arm64" "0.25.2" - "@esbuild/linux-ia32" "0.25.2" - "@esbuild/linux-loong64" "0.25.2" - "@esbuild/linux-mips64el" "0.25.2" - "@esbuild/linux-ppc64" "0.25.2" - "@esbuild/linux-riscv64" "0.25.2" - "@esbuild/linux-s390x" "0.25.2" - "@esbuild/linux-x64" "0.25.2" - "@esbuild/netbsd-arm64" "0.25.2" - "@esbuild/netbsd-x64" "0.25.2" - "@esbuild/openbsd-arm64" "0.25.2" - "@esbuild/openbsd-x64" "0.25.2" - "@esbuild/sunos-x64" "0.25.2" - "@esbuild/win32-arm64" "0.25.2" - "@esbuild/win32-ia32" "0.25.2" - "@esbuild/win32-x64" "0.25.2" - -escalade@^3.2.0: - version "3.2.0" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz" - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== - escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" @@ -2276,7 +1775,7 @@ eslint-visitor-keys@^4.2.0: resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== -eslint@^9.21.0: +"eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^8.57.0 || ^9.0.0", eslint@^9.21.0, eslint@>=8.40: version "9.24.0" resolved "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz" integrity sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ== @@ -2403,9 +1902,9 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -fdir@^6.4.4, fdir@^6.5.0: +fdir@^6.5.0: version "6.5.0" - resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + resolved "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz" integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== fetch-cookie@^2.0.3: @@ -2467,21 +1966,11 @@ form-data@^4.0.4: hasown "^2.0.4" mime-types "^2.1.35" -fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - get-intrinsic@^1.2.6: version "1.3.0" resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz" @@ -2520,11 +2009,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^14.0.0: version "14.0.0" resolved "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz" @@ -2682,23 +2166,13 @@ isexe@^2.0.0: resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + version "4.2.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz" + integrity sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw== dependencies: argparse "^2.0.1" -jsesc@^3.0.2: - version "3.1.0" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz" - integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== - json-buffer@3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" @@ -2714,12 +2188,7 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json5@^2.2.3: - version "2.2.3" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -keyborg@2.6.0, keyborg@^2.6.0: +keyborg@^2.6.0, keyborg@2.6.0: version "2.6.0" resolved "https://registry.npmjs.org/keyborg/-/keyborg-2.6.0.tgz" integrity sha512-o5kvLbuTF+o326CMVYpjlaykxqYP9DphFQZ2ZpgrvBouyvOxyEB7oqe8nOLFpiV5VCtz0D3pt8gXQYWpLpBnmA== @@ -2739,6 +2208,35 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lightningcss-linux-x64-gnu@1.32.0: + version "1.32.0" + resolved "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz" + integrity sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA== + +lightningcss-linux-x64-musl@1.32.0: + version "1.32.0" + resolved "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz" + integrity sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg== + +lightningcss@^1.32.0: + version "1.32.0" + resolved "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz" + integrity sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ== + dependencies: + detect-libc "^2.0.3" + optionalDependencies: + lightningcss-android-arm64 "1.32.0" + lightningcss-darwin-arm64 "1.32.0" + lightningcss-darwin-x64 "1.32.0" + lightningcss-freebsd-x64 "1.32.0" + lightningcss-linux-arm-gnueabihf "1.32.0" + lightningcss-linux-arm64-gnu "1.32.0" + lightningcss-linux-arm64-musl "1.32.0" + lightningcss-linux-x64-gnu "1.32.0" + lightningcss-linux-x64-musl "1.32.0" + lightningcss-win32-arm64-msvc "1.32.0" + lightningcss-win32-x64-msvc "1.32.0" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" @@ -2756,13 +2254,6 @@ longest-streak@^3.0.0: resolved "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz" integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g== -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - math-intrinsics@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" @@ -2837,9 +2328,9 @@ mdast-util-phrasing@^4.0.0: unist-util-is "^6.0.0" mdast-util-to-hast@^13.0.0: - version "13.2.0" - resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz" - integrity sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA== + version "13.2.1" + resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz" + integrity sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA== dependencies: "@types/hast" "^3.0.0" "@types/mdast" "^4.0.0" @@ -3111,10 +2602,10 @@ ms@^2.1.3: resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -nanoid@^3.3.8: - version "3.3.11" - resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz" - integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== +nanoid@^3.3.12: + version "3.3.12" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz" + integrity sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ== natural-compare@^1.4.0: version "1.4.0" @@ -3128,11 +2619,6 @@ node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" -node-releases@^2.0.19: - version "2.0.19" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz" - integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== - optionator@^0.9.3: version "0.9.4" resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz" @@ -3189,7 +2675,7 @@ path-key@^3.1.0: resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -picocolors@^1.0.0, picocolors@^1.1.1: +picocolors@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== @@ -3199,17 +2685,17 @@ picomatch@^2.3.1: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -picomatch@^4.0.2, picomatch@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" - integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== +"picomatch@^3 || ^4", picomatch@^4.0.4: + version "4.0.4" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz" + integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== -postcss@^8.5.3: - version "8.5.3" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz" - integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== +postcss@^8.5.15: + version "8.5.15" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz" + integrity sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A== dependencies: - nanoid "^3.3.8" + nanoid "^3.3.12" picocolors "^1.1.1" source-map-js "^1.2.1" @@ -3250,7 +2736,7 @@ queue-microtask@^1.2.2: resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -react-dom@^19.2.1: +react-dom@^19.2.1, "react-dom@>=16.14.0 <20.0.0", "react-dom@>=16.8.0 <20.0.0": version "19.2.1" resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz" integrity sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg== @@ -3279,12 +2765,7 @@ react-markdown@^10.1.0: unist-util-visit "^5.0.0" vfile "^6.0.0" -react-refresh@^0.14.2: - version "0.14.2" - resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz" - integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== - -react@^19.2.1: +"react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", react@^19.2.1, "react@>=16.14.0 <20.0.0", "react@>=16.8.0 <20.0.0", react@>=18: version "19.2.1" resolved "https://registry.npmjs.org/react/-/react-19.2.1.tgz" integrity sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw== @@ -3330,36 +2811,29 @@ reusify@^1.0.4: resolved "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz" integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== -rollup@^4.34.9: - version "4.53.3" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.53.3.tgz#dbc8cd8743b38710019fb8297e8d7a76e3faa406" - integrity sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA== +rolldown@1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz" + integrity sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g== dependencies: - "@types/estree" "1.0.8" + "@oxc-project/types" "=0.133.0" + "@rolldown/pluginutils" "^1.0.0" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.53.3" - "@rollup/rollup-android-arm64" "4.53.3" - "@rollup/rollup-darwin-arm64" "4.53.3" - "@rollup/rollup-darwin-x64" "4.53.3" - "@rollup/rollup-freebsd-arm64" "4.53.3" - "@rollup/rollup-freebsd-x64" "4.53.3" - "@rollup/rollup-linux-arm-gnueabihf" "4.53.3" - "@rollup/rollup-linux-arm-musleabihf" "4.53.3" - "@rollup/rollup-linux-arm64-gnu" "4.53.3" - "@rollup/rollup-linux-arm64-musl" "4.53.3" - "@rollup/rollup-linux-loong64-gnu" "4.53.3" - "@rollup/rollup-linux-ppc64-gnu" "4.53.3" - "@rollup/rollup-linux-riscv64-gnu" "4.53.3" - "@rollup/rollup-linux-riscv64-musl" "4.53.3" - "@rollup/rollup-linux-s390x-gnu" "4.53.3" - "@rollup/rollup-linux-x64-gnu" "4.53.3" - "@rollup/rollup-linux-x64-musl" "4.53.3" - "@rollup/rollup-openharmony-arm64" "4.53.3" - "@rollup/rollup-win32-arm64-msvc" "4.53.3" - "@rollup/rollup-win32-ia32-msvc" "4.53.3" - "@rollup/rollup-win32-x64-gnu" "4.53.3" - "@rollup/rollup-win32-x64-msvc" "4.53.3" - fsevents "~2.3.2" + "@rolldown/binding-android-arm64" "1.0.3" + "@rolldown/binding-darwin-arm64" "1.0.3" + "@rolldown/binding-darwin-x64" "1.0.3" + "@rolldown/binding-freebsd-x64" "1.0.3" + "@rolldown/binding-linux-arm-gnueabihf" "1.0.3" + "@rolldown/binding-linux-arm64-gnu" "1.0.3" + "@rolldown/binding-linux-arm64-musl" "1.0.3" + "@rolldown/binding-linux-ppc64-gnu" "1.0.3" + "@rolldown/binding-linux-s390x-gnu" "1.0.3" + "@rolldown/binding-linux-x64-gnu" "1.0.3" + "@rolldown/binding-linux-x64-musl" "1.0.3" + "@rolldown/binding-openharmony-arm64" "1.0.3" + "@rolldown/binding-wasm32-wasi" "1.0.3" + "@rolldown/binding-win32-arm64-msvc" "1.0.3" + "@rolldown/binding-win32-x64-msvc" "1.0.3" rtl-css-js@^1.16.1: version "1.16.1" @@ -3375,16 +2849,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -scheduler@^0.27.0: +scheduler@^0.27.0, scheduler@>=0.19.0: version "0.27.0" resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz" integrity sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q== -semver@^6.3.1: - version "6.3.1" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - semver@^7.6.0: version "7.7.1" resolved "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz" @@ -3466,13 +2935,13 @@ tabster@^8.5.5: optionalDependencies: "@rollup/rollup-linux-x64-gnu" "4.53.3" -tinyglobby@^0.2.13: - version "0.2.15" - resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2" - integrity sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ== +tinyglobby@^0.2.17: + version "0.2.17" + resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz" + integrity sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g== dependencies: fdir "^6.5.0" - picomatch "^4.0.3" + picomatch "^4.0.4" to-regex-range@^5.0.1: version "5.0.1" @@ -3537,7 +3006,7 @@ typescript@^3.9: resolved "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz" integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== -typescript@~5.7.2: +typescript@>=4.8.4, "typescript@>=4.8.4 <5.9.0", typescript@~5.7.2: version "5.7.3" resolved "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz" integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== @@ -3598,14 +3067,6 @@ universalify@^0.2.0: resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz" integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== -update-browserslist-db@^1.1.1: - version "1.1.3" - resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz" - integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== - dependencies: - escalade "^3.2.0" - picocolors "^1.1.1" - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" @@ -3647,17 +3108,16 @@ vfile@^6.0.0: "@types/unist" "^3.0.0" vfile-message "^4.0.0" -vite@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/vite/-/vite-6.4.1.tgz#afbe14518cdd6887e240a4b0221ab6d0ce733f96" - integrity sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g== - dependencies: - esbuild "^0.25.0" - fdir "^6.4.4" - picomatch "^4.0.2" - postcss "^8.5.3" - rollup "^4.34.9" - tinyglobby "^0.2.13" +vite@^8.0.0, vite@^8.0.16: + version "8.0.16" + resolved "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz" + integrity sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw== + dependencies: + lightningcss "^1.32.0" + picomatch "^4.0.4" + postcss "^8.5.15" + rolldown "1.0.3" + tinyglobby "^0.2.17" optionalDependencies: fsevents "~2.3.3" @@ -3687,14 +3147,9 @@ word-wrap@^1.2.5: integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== ws@^7.4.5: - version "7.5.10" - resolved "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz" - integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + version "7.5.11" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz" + integrity sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA== yocto-queue@^0.1.0: version "0.1.0" From 8ce2bcc07f0ce5e56052ffd4abd0332cc8fc08e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:51:30 +0000 Subject: [PATCH 12/33] .Net: Bump Aspire.Hosting.Azure.CognitiveServices from 13.0.0 to 13.3.0 (#13996) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated [Aspire.Hosting.Azure.CognitiveServices](https://github.com/microsoft/aspire) from 13.0.0 to 13.3.0.
Release notes _Sourced from [Aspire.Hosting.Azure.CognitiveServices's releases](https://github.com/microsoft/aspire/releases)._ ## 13.3.0 # Aspire 13.3.0 Aspire 13.3 is here! 🚀 This release is packed with new ways to deploy, debug, and build distributed apps — including `aspire destroy`, browser telemetry in the dashboard, Kubernetes deployment, first-class JavaScript publishing, and major TypeScript AppHost parity improvements. ## Highlights - 🧹 **Clean teardown** — New **`aspire destroy`** tears down Azure, Kubernetes, and Docker Compose deployments, and pipeline summaries make deploy/publish/destroy runs easier to follow. - 🔍 **Frontend telemetry** — **Aspire.Hosting.Browsers** captures browser console logs, network requests, and screenshots right in the Aspire dashboard. - ☸️ **Kubernetes deploy preview** — **`aspire deploy`** can now generate Helm-based Kubernetes deployments, with first-class Ingress and Gateway API routing. - 🟨 **JavaScript publishing** — New **`PublishAs*`** methods support static sites, Node servers, npm-script apps, Next.js, Vite, Bun, Yarn, and pnpm. - 🌐 **TypeScript AppHost parity** — Unified `withEnvironment`, Docker Compose hooks, endpoint expressions, Azure Container Apps domains, and more close the gap with C# AppHosts. - 🛠️ **CLI upgrades** — Run the standalone dashboard with **`aspire dashboard run`**, install the CLI as a NativeAOT `dotnet tool`, and search API docs from the terminal. - ☁️ **Azure goodness** — New Azure Front Door, Network Security Perimeter, AKS, private endpoint, and Foundry Prompt Agent support. - 🐳 **Better containers** — The Aspire container tunnel is now enabled by default for consistent host connectivity across Docker Desktop, Docker Engine, and Podman. ## ⚠️ Breaking changes Notable breaking changes include `--log-level` becoming `--pipeline-log-level`, the dashboard MCP server being replaced by `aspire agent init`, `dotnet new aspire-py-starter` moving to `aspire new aspire-py-starter`, and several API shape updates across AKS, Foundry, JavaScript diagnostics, and TypeScript AppHost helpers. See the full list in the [Aspire 13.3 breaking changes](https://aspire.dev/whats-new/aspire-13-3/#%EF%B8%8F-breaking-changes). ## 📖 Learn more For the full details, examples, migration guidance, and everything new in this release, check out [What's new in Aspire 13.3](https://aspire.dev/whats-new/aspire-13-3/). Thank you to all the community contributors who helped make Aspire 13.3 possible! 💜 ## 13.2.4 # Aspire 13.2.4 ## What's New in Aspire 13.2.4 Patch release addressing a security advisory in OpenTelemetry dependencies. ### 🐛 Fixes - 🔒 Bumped OpenTelemetry dependencies to address CVE-2026-40894 (#​16420) ### 🏷️ Housekeeping - 🚀 Bumped branding to 13.2.4 (#​16436) ## 13.2.3 # What's New in Aspire 13.2.3 Patch release focused on CLI packaging, signing, and reliability fixes. ## 🐛 Fixes - 🛑 aspire stop now properly cleans up application containers on Windows (#​16123) - 🔐 Fixed macOS signing, permissions, and certificate trust with improved CI verification (#​16053) - ✍️ Fixed signing for the aspire-managed bundle payload (#​16211) - 🎭 Fixed Playwright CLI provenance verification for the new tag format (#​16134) - 🧭 Updated service discovery environment variables (#​16223) ## 🔧 Improvements - 📊 Removed telemetry API data limits and refactored URL builders (#​16023) - ⏱️ Increased native build + sign timeout to 60 minutes for reliability (#​16212) ## 🏷️ Housekeeping - 🔖 Bumped branding to 13.2.3 (#​16181) - 🧪 Temporarily disabled Verify CLI archive step on Windows while investigating (#​16276, #​16285) ## 13.2.2 This is a servicing release focused on bug fixes and platform improvements. 🐛 Bug Fixes - Fix SqlClient runtime asset layout on Unix — Resolved an issue where Microsoft.Data.SqlClient failed to load correctly on macOS and Linux due to incorrect NuGet asset layout (#​15709) - Fix IDE execution regressions for Azure Functions and class library projects — Backported fixes for 13.2 regressions impacting IDE-based execution (#​15714) - Fix NpmRunner multi-version output parsing — npm view returning multiple versions no longer breaks version resolution; also bumps @​playwright/cli to >=0.1.3 (#​15746) - Skip name validation for internal resources — ProjectRebuilderResource, installer, and venv creator resources no longer fail the 64-char name limit since they're never deployed (#​15726, fixes #​15693) 🔒 Security & Certificates - Use ASP.NET Core dev cert for DCP — Avoids ephemeral certificate trust issues by using the standard ASP.NET Core developer certificate (#​15718) - Cache PFX dev certs on Windows and Linux — Prevents binary-level changes between runs for persistent container scenarios (#​15774) 🏗️ Infrastructure & Platform - ARM64 CLI support — Added win-arm64 and linux-arm64 to the native CLI archive build matrix (#​15599) - Update DCP to 0.22.11 (#​15713) 💻 CLI Improvements - Show anonymous dashboard URLs in aspire ps — The dashboard URL is now displayed even when running without authentication (#​15731 ## 13.2.1 🐛 Bug Fixes - 🖥️ CLI bundles for ARM & musl — win-arm64, linux-arm64, and linux-musl-x64 bundles now correctly include DCP instead of silently producing broken installs (#​15529) - ⚡ aspire new in VS Code — Fixed a race where the workspace switch severed the CLI terminal before the agent init prompt could complete (#​15553) - 🔗 Dashboard resource URLs — The describe command no longer produces broken dashboard links with a stray /login?t=... in the path (#​15495) - 🌍 Guest AppHost env vars — Launch profile environment variables are now correctly forwarded to guest AppHosts (#​15637) - 📦 Legacy settings migration — .aspire/settings.json → aspire.config.json migration was silently skipped in some scenarios; now works reliably (#​15526) - 🔧 TypeScript AppHost restore — Fixed config resolution during TS AppHost restore (#​15625) - 🎭 Playwright CLI on Windows — aspire agent init now correctly installs playwright-cli on Windows (#​15559) - 📌 Emulator stability — Pinned Kusto emulator image and improved Cosmos DB emulator reliability (#​15504) ✨ Improvements - 🏗️ Brownfield TypeScript aspire init — Running aspire init in existing JS/TS projects now smartly merges package.json — scripts, dependencies, and engines — with semver-aware conflict handling (#​15123) - 🎯 Endpoint filtering — New ExcludeReferenceEndpoint property lets you filter specific endpoints from WithReference (#​15586) - 🌐 More polyglot ATS APIs — Exported additional hosting APIs for TypeScript and Go AppHost authoring (#​15557) - 🔍 Short trace ID support — The dashboard now resolves short trace IDs in addition to full-length ones (#​15613) - ⚠️ Aspire.Hosting.NodeJs deprecated — Use Aspire.Hosting.JavaScript instead; the old package no longer appears in aspire add (#​15686) ## 13.2.0 # Aspire 13.2 Aspire 13.2 brings major CLI enhancements, a new TypeScript AppHost (preview), dashboard data export/import, Microsoft Foundry integration, and multi-language improvements — all focused on making local development more streamlined for developers and AI coding agents alike. ## Highlights - 🛠️ CLI overhaul — New commands including **aspire start/stop/ps** for detached mode, **aspire describe** for resource monitoring, **aspire doctor** for environment diagnostics, **aspire secret** for managing user secrets, **aspire docs** for browsing documentation from the terminal, and **aspire agent** (renamed from **aspire mcp**) for AI agent integration. - 🌐 TypeScript AppHost (preview) — Write your apphost in TypeScript with **createBuilder()**, using the same app model concepts as C#. Full VS Code extension support included. - 🧩 VS Code extension — Dedicated Aspire Activity Bar panel with live resource state, inline CodeLens with health status and actions, gutter decorations, and a new Getting Started walkthrough. - 📊 Dashboard improvements — Bulk telemetry export/import, export environment variables as **.env** files, a new telemetry HTTP API, set parameters directly from the dashboard, and improved resource graph layout. - 🤖 Microsoft Foundry — Replaces Azure AI Foundry integration with broader **Aspire.Hosting.Foundry** support including hosted agents and model deployments. - 🔒 Azure Virtual Network & Private Endpoints — New **Aspire.Hosting.Azure.Network** integration for defining VNets, subnets, NAT gateways, NSGs, and private endpoints directly in your apphost. - 🐳 Docker Compose publishing — Generate docker-compose.yaml from your app model with **AddDockerComposeEnvironment.** - 📦 New integrations — Azure Data Lake Storage, MongoDB EF Core (**Aspire.MongoDB.EntityFrameworkCore**), Bun support for JS resources, and Certbot for automated SSL certificates. - ⚡ App model — **WithMcpServer** for declaring MCP endpoints, **rebuild** command for project resources, contextual endpoint resolution, and improved secret/certificate handling. ## ⚠️ Breaking changes Notable breaking changes include service discovery env vars now using endpoint scheme instead of name, aspire.config.json replacing split config files, AIFoundry → Foundry rename, WithSecretBuildArg → WithBuildSecret, and updated default Azure credential behavior. [See the full list of breaking changes](https://aspire.dev/whats-new/aspire-13-2/#%EF%B8%8F-breaking-changes). ## 📖 Learn more For the full details on everything in this release, check out the [What's new in Aspire 13.2](https://aspire.dev/whats-new/aspire-13-2/) documentation. Thank you to all the community contributors who helped make this release happen! 💜 ## 13.1.3 ## What's Changed * [release/13.1] Add installer publishing updates for 13.1.3 by @​radical in https://github.com/dotnet/aspire/pull/15158 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.1.2...v13.1.3 ## 13.1.2 ## What's Changed * Bump patch version from 13.1.1 to 13.1.2 by @​Copilot in https://github.com/dotnet/aspire/pull/14699 * [release/13.1] Fix template version parsing for .NET 10.0 SDK separator change by @​JamesNK in https://github.com/dotnet/aspire/pull/14698 * Update pipeline images to non-deprecated pools by @​joperezr in https://github.com/dotnet/aspire/pull/14707 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.1.1...v13.1.2 ## 13.1.1 ## What's Changed * [release/13.1] Ensure WithHostHttpsPort works when chained inline by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13678 * [release/13.1] Escape backslashes in path string to discovered vite config by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13822 * [release/13.1] [Testing] Fixing bugs for sticky slot app settings by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13810 * [release/13.1] Fix AzureBicepResource file-not-found error when using templateFile with AzurePublishingContext by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/14018 * [release/13.1] Filter dev certs without X509SubjectKeyIdentifierExtension when any cert has it by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13676 * [release/13.1] Fix Aspire.ProjectTemplates build failure from command line length limits by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/14009 * [release/13.1] Update Azure.Identity package version to 1.17.1 by @​eerhardt in https://github.com/dotnet/aspire/pull/14251 * Bump patch version from 13.1.0 to 13.1.1 by @​Copilot in https://github.com/dotnet/aspire/pull/14329 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.1.0...v13.1.1 ## 13.1.0 We are excited to share that our 13.1.0 release of Aspire has shipped! All of the packages are available in NuGet.org now. Head over to https://aspire.dev/whats-new/aspire-13-1/ to find what's new in 13.1.0! ## What's Changed * Target net10.0 in client integrations by @​eerhardt in https://github.com/dotnet/aspire/pull/12500 * Fix DockerComposeEnvironment duplicating image names in .env file by @​Copilot in https://github.com/dotnet/aspire/pull/12310 * Replace apt-get with npm for Azure Functions Core Tools installation by @​Copilot in https://github.com/dotnet/aspire/pull/12537 * Improve flaky dashboard integration test by @​JamesNK in https://github.com/dotnet/aspire/pull/12534 * Add README.md for the Aspire.Hosting.Azure.AppService package by @​ShilpiRach in https://github.com/dotnet/aspire/pull/12528 * Add support to enable automatic scaling for App Service Environment by @​ShilpiRach in https://github.com/dotnet/aspire/pull/12305 * Update to FluentUI 4.13.1 by @​JamesNK in https://github.com/dotnet/aspire/pull/12532 * Skip playground projects in build-packages workflow by @​Copilot in https://github.com/dotnet/aspire/pull/12547 * Allow HostUrl to remap both address and port by @​danegsta in https://github.com/dotnet/aspire/pull/12521 * Refactor NodeJs Integration by @​eerhardt in https://github.com/dotnet/aspire/pull/12530 * Fix MCP endpoint with redirect HTTPS by @​JamesNK in https://github.com/dotnet/aspire/pull/12556 * [main] Update dependencies from microsoft/usvc-apiserver by @​dotnet-maestro[bot] in https://github.com/dotnet/aspire/pull/12540 * Refactor AddNodeApp by @​eerhardt in https://github.com/dotnet/aspire/pull/12538 * Update Aspire branding from 13.0 to 13.1 by @​Copilot in https://github.com/dotnet/aspire/pull/12527 * Add annotation to specify custom base images for generated Dockerfiles by @​Copilot in https://github.com/dotnet/aspire/pull/12566 * Fix generating random MCP endpoint URL in templates by @​JamesNK in https://github.com/dotnet/aspire/pull/12558 * [CI] Add new Agent for disabling or quarantining tests by @​radical in https://github.com/dotnet/aspire/pull/12570 * Add `ExcludeFromMcp()` resource extension by @​JamesNK in https://github.com/dotnet/aspire/pull/12515 * Localized file check-in by OneLocBuild Task: Build definition ID 1309: Build ID 2828818 by @​dotnet-bot in https://github.com/dotnet/aspire/pull/12546 * Register IPipelineOutputService in DI for pipeline output directory management by @​Copilot in https://github.com/dotnet/aspire/pull/12563 * Add deploy support for Docker Compose by @​captainsafia in https://github.com/dotnet/aspire/pull/12548 * Quarantine flaky test: AzureServiceBusEmulatorResourceGeneratesConfigJsonWithCustomizations by @​Copilot in https://github.com/dotnet/aspire/pull/12578 * Update connection properties for non-Azure resources by @​sebastienros in https://github.com/dotnet/aspire/pull/12583 * Filter to highest package version per channel in aspire add command by @​Copilot in https://github.com/dotnet/aspire/pull/12553 * Log DCP messages at Debug/Trace level in AppHost by @​Copilot in https://github.com/dotnet/aspire/pull/12533 * Add CLI self-update prompts to `aspire update` command by @​Copilot in https://github.com/dotnet/aspire/pull/12395 * Fix golang and alpine images. by @​mitchdenny in https://github.com/dotnet/aspire/pull/12592 * Replace ContainerTargetPlatform.AllLinux with LinuxAmd64 by @​Copilot in https://github.com/dotnet/aspire/pull/12596 * [main] Update dependencies from microsoft/usvc-apiserver by @​dotnet-maestro[bot] in https://github.com/dotnet/aspire/pull/12610 * Make IReportingStep and IReportingTask completion idempotent by @​Copilot in https://github.com/dotnet/aspire/pull/12602 * Show --log-level debug hint when pipeline fails by @​Copilot in https://github.com/dotnet/aspire/pull/12603 * [main] Update dependencies from dotnet/arcade by @​dotnet-maestro[bot] in https://github.com/dotnet/aspire/pull/12622 * Rename app.py to main.py in template by @​eerhardt in https://github.com/dotnet/aspire/pull/12628 * bump extension version by @​adamint in https://github.com/dotnet/aspire/pull/12623 * don't build apphost in cli when running in extension by @​adamint in https://github.com/dotnet/aspire/pull/12621 * Detect which version of yarn is being used by @​eerhardt in https://github.com/dotnet/aspire/pull/12633 * Fix duplicate key exception when using WithExplicitStart() on resources with environment callbacks by @​Copilot in https://github.com/dotnet/aspire/pull/12604 * Support AddCSharpApp, fix some rough edges around project resources by @​adamint in https://github.com/dotnet/aspire/pull/12568 * Add missing namespace to `CertificateAuthorityCollectionResource` by @​danegsta in https://github.com/dotnet/aspire/pull/12639 * Add ModelContextProtocol assemblies to signing list by @​joperezr in https://github.com/dotnet/aspire/pull/12637 * Generate fallback Dockerfile for Python apps without UV by @​Copilot in https://github.com/dotnet/aspire/pull/12627 * Update/bump container image tags for hosting components by @​joperezr in https://github.com/dotnet/aspire/pull/12459 * Mark IDeveloperCertificateService experimental by @​danegsta in https://github.com/dotnet/aspire/pull/12648 * Wait with exponential backoff for expected Executables by @​karolz-ms in https://github.com/dotnet/aspire/pull/12647 * Make ProcessCertificateTrustConfigAsync internal by @​danegsta in https://github.com/dotnet/aspire/pull/12649 * Add test cases and ensure container cert override paths work by @​danegsta in https://github.com/dotnet/aspire/pull/12654 * Python hosting: Support .venv lookup by walking up parent directories by @​Copilot in https://github.com/dotnet/aspire/pull/12616 ... (truncated) ## 13.0.2 This patch is updating our Project Templates for our Python starter app to ensure we depend on the latest version of React. This is out of an abundance of caution, as we don't depend on any of the react packages that were flagged as vulnerable in https://github.com/advisories/GHSA-fv66-9v8q-g76r. ## What's Changed * Bump patch version from 13.0.1 to 13.0.2 by @​Copilot in https://github.com/dotnet/aspire/pull/13324 * Update React and ReactDOM to version 19.2.1 across all projects by @​joperezr in https://github.com/dotnet/aspire/pull/13325 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.0.1...v13.0.2 ## 13.0.1 ## What's Changed * Merge internal changes by @​joperezr in https://github.com/dotnet/aspire/pull/12896 * [release/13.0] Fix Azure roles resources always redeploying by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/12903 * [release/13.0] Remove .py and .js files from being signed (#​13005) by @​eerhardt in https://github.com/dotnet/aspire/pull/13032 * [release/13.0] Fix subscription ID not being disabled on Azure provisioning dialog by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/12913 * [release/13.0] Default OpenAISettings.EnableSensitiveTelemetryData to TelemetryHelpers.EnableSensitiveDataDefault by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13017 * Bump patch version from 13.0.0 to 13.0.1 by @​Copilot in https://github.com/dotnet/aspire/pull/13167 * [release/13.0] EndpointReference evaluation should wait on missing AllocatedEndpoint (#​13074) by @​karolz-ms in https://github.com/dotnet/aspire/pull/13076 * [release/13.0] Update to Npgsql 10 by @​github-actions[bot] in https://github.com/dotnet/aspire/pull/13166 * [release/13.0] Update dependencies from microsoft/usvc-apiserver by @​danegsta in https://github.com/dotnet/aspire/pull/13187 **Full Changelog**: https://github.com/dotnet/aspire/compare/v13.0.0...v13.0.1 Commits viewable in [compare view](https://github.com/microsoft/aspire/compare/v13.0.0...v13.3.0).
[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Aspire.Hosting.Azure.CognitiveServices&package-manager=nuget&previous-version=13.0.0&new-version=13.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> --- dotnet/Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 459be834f13c..871f35361f2e 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -8,11 +8,11 @@ - + - + From 91efa2120cc3fd193829f01fa629937c9d2606b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:42:09 +0200 Subject: [PATCH 13/33] Python: Bump bleach from 6.3.0 to 6.4.0 in /python (#14089) Bumps [bleach](https://github.com/mozilla/bleach) from 6.3.0 to 6.4.0.
Changelog

Sourced from bleach's changelog.

Version 6.4.0 (June 5th, 2026)

NOTE: 2026-06-05: Bleach is no longer maintained. There will be no future releases including for security issues. See issue: <https://github.com/mozilla/bleach/issues/698>__

Backwards incompatible changes

  • Dropped support for pypy 3.10. (#764)

Security fixes

  • Fix bug 2023812 / GHSA-8rfp-98v4-mmr6.

    Fix XSS issue with sanitize_uri_value where disallowed schemes with Unicode invisible characters wouldn't be rejected.

    For example::

    import bleach payload1 = 'Click' result1 = bleach.clean(payload1) print(repr(result1))

    outputs::

    'Click'

    See the advisory for details.

  • Fix GHSA-gj48-438w-jh9v.

    Fix issue where URI sanitization wasn't happening in formaction attributes.

    See the advisory for details.

Bug fixes

  • Add support for pypy 3.11. (#764)

  • Drop version max in tinycss2 pin. (#772)

    This removes one of the things we had to keep checking and updating. Users now own the responsibility for correctness with the version of tinycss2 they're using.

Commits
  • f0355a7 fix: fix last release date in CHANGES
  • ae4e8a2 chore: bleach 6.4.0 and final release
  • 970df58 fix: uri-sanitization in formaction attributes
  • 7c4867c fix: xss bypass in allowed protocol test using unicode invisible characters
  • 913ab75 fix: reduce redundancy in workflow jobs
  • 218c15a fix: rework pip caching
  • 4f0b097 fix: fix tox platform restrictions
  • e95a79d chore: update pytest
  • 91539d4 Bump actions/cache from 5.0.3 to 5.0.4
  • cd47b4c fix: handle left-angle-bracket that's not a tag (#733)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=bleach&package-manager=uv&previous-version=6.3.0&new-version=6.4.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/semantic-kernel/network/alerts).
--------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- python/tests/unit/data/conftest.py | 11 +++++ .../test_vector_store_record_collection.py | 46 ++++++++----------- python/uv.lock | 6 +-- 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/python/tests/unit/data/conftest.py b/python/tests/unit/data/conftest.py index b184b60e43ed..7033a6cfc166 100644 --- a/python/tests/unit/data/conftest.py +++ b/python/tests/unit/data/conftest.py @@ -240,6 +240,17 @@ def data_model_pandas_definition() -> object: ) +@fixture +async def pandas_vector_store_record_collection(DictVectorStoreRecordCollection, data_model_pandas_definition): + from pandas import DataFrame + + return DictVectorStoreRecordCollection( + collection_name="test", + record_type=DataFrame, + definition=data_model_pandas_definition, + ) + + @fixture def record_type_vanilla(): @vectorstoremodel diff --git a/python/tests/unit/data/test_vector_store_record_collection.py b/python/tests/unit/data/test_vector_store_record_collection.py index ece736b9338b..cb133ddc05e4 100644 --- a/python/tests/unit/data/test_vector_store_record_collection.py +++ b/python/tests/unit/data/test_vector_store_record_collection.py @@ -172,46 +172,36 @@ async def test_crud_batch_operations_container(vector_store_record_collection): assert len(vector_store_record_collection.inner_storage) == 0 -@mark.parametrize( - "vector_store_record_collection", - ["definition_pandas"], - indirect=True, -) -async def test_crud_operations_pandas(vector_store_record_collection): +async def test_crud_operations_pandas(pandas_vector_store_record_collection): id = "test_id" record = DataFrame([{"id": id, "content": "test_content", "vector": [1.0, 2.0, 3.0]}]) - no_records = await vector_store_record_collection.get(id) + no_records = await pandas_vector_store_record_collection.get(id) assert no_records is None - await vector_store_record_collection.upsert(record) - assert len(vector_store_record_collection.inner_storage) == 1 + await pandas_vector_store_record_collection.upsert(record) + assert len(pandas_vector_store_record_collection.inner_storage) == 1 - assert vector_store_record_collection.inner_storage[id]["content"] == record["content"].values[0] - assert vector_store_record_collection.inner_storage[id]["vector"] == record["vector"].values[0] - record_2 = await vector_store_record_collection.get(id) + assert pandas_vector_store_record_collection.inner_storage[id]["content"] == record["content"].values[0] + assert pandas_vector_store_record_collection.inner_storage[id]["vector"] == record["vector"].values[0] + record_2 = await pandas_vector_store_record_collection.get(id) assert record_2.equals(record) - await vector_store_record_collection.delete(id) - assert len(vector_store_record_collection.inner_storage) == 0 + await pandas_vector_store_record_collection.delete(id) + assert len(pandas_vector_store_record_collection.inner_storage) == 0 -@mark.parametrize( - "vector_store_record_collection", - ["definition_pandas"], - indirect=True, -) -async def test_crud_batch_operations_pandas(vector_store_record_collection): +async def test_crud_batch_operations_pandas(pandas_vector_store_record_collection): ids = ["test_id_1", "test_id_2"] batch = DataFrame([{"id": id, "content": "test_content", "vector": [1.0, 2.0, 3.0]} for id in ids]) - no_records = await vector_store_record_collection.get(ids) + no_records = await pandas_vector_store_record_collection.get(ids) assert no_records is None - await vector_store_record_collection.upsert(batch) - assert len(vector_store_record_collection.inner_storage) == 2 - assert vector_store_record_collection.inner_storage[ids[0]]["content"] == batch["content"].values[0] - assert vector_store_record_collection.inner_storage[ids[0]]["vector"] == batch["vector"].values[0] - records = await vector_store_record_collection.get(ids) + await pandas_vector_store_record_collection.upsert(batch) + assert len(pandas_vector_store_record_collection.inner_storage) == 2 + assert pandas_vector_store_record_collection.inner_storage[ids[0]]["content"] == batch["content"].values[0] + assert pandas_vector_store_record_collection.inner_storage[ids[0]]["vector"] == batch["vector"].values[0] + records = await pandas_vector_store_record_collection.get(ids) assert records.equals(batch) - await vector_store_record_collection.delete(ids) - assert len(vector_store_record_collection.inner_storage) == 0 + await pandas_vector_store_record_collection.delete(ids) + assert len(pandas_vector_store_record_collection.inner_storage) == 0 # region Fails diff --git a/python/uv.lock b/python/uv.lock index dc5fc3313a7d..6db672130626 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -648,14 +648,14 @@ wheels = [ [[package]] name = "bleach" -version = "6.3.0" +version = "6.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "webencodings", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/07/18/3c8523962314be6bf4c8989c79ad9531c825210dd13a8669f6b84336e8bd/bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22", size = 203533, upload-time = "2025-10-27T17:57:39.211Z" } +sdist = { url = "https://files.pythonhosted.org/packages/48/3c/e12ac860709702bd5ebeb9b56a4fe334f1001246ee1b8f2b7ee28912df7d/bleach-6.4.0.tar.gz", hash = "sha256:4202482733d85cedd04e59fcb2f89f4e4c7c385a78d3c3c23c30446843a37452", size = 204857, upload-time = "2026-06-05T13:01:13.734Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6", size = 164437, upload-time = "2025-10-27T17:57:37.538Z" }, + { url = "https://files.pythonhosted.org/packages/58/9d/40b6267367182187139a4000b82a3b287d84d745bccd808e75d916920e9d/bleach-6.4.0-py3-none-any.whl", hash = "sha256:4b6b6a54fff2e69a3dde9d21cc6301220bee3c3cb792187d11403fd795031081", size = 165109, upload-time = "2026-06-05T13:01:12.504Z" }, ] [package.optional-dependencies] From 03f73aee5e06ec411d3e261bdcdd8452ae9d6620 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:43:08 +0000 Subject: [PATCH 14/33] Python: Bump torch from 2.8.0 to 2.12.0 in /python (#14065) Bumps [torch](https://github.com/pytorch/pytorch) from 2.8.0 to 2.12.0.
Release notes

Sourced from torch's releases.

PyTorch 2.12.0 Release Notes

Highlights

For more details about these highlighted features, you can look at the release blogpost. Below are the full release notes for this release.

Backwards Incompatible Changes

Build Frontend

  • Strengthened SVE compile checks in FindARM.cmake, which may reject previously accepted but incorrect SVE configurations (#176646)

    Source builds that enable SVE now validate the compiler configuration more strictly. If a build previously passed with an incomplete or mismatched SVE setup, it may now fail during CMake configuration instead of later in compilation. Update the compiler/toolchain flags so they accurately describe the target SVE support, or disable SVE for that build.

  • Updated the minimum CUDA version required to build PyTorch from source to CUDA 12.6 (#178925)

    Building PyTorch from source with CUDA versions older than 12.6 is no longer supported. Users building custom binaries should install CUDA 12.6 or newer and make sure CUDA_HOME points to that installation.

    Version 2.11:

    CUDA_HOME=/usr/local/cuda-12.4 python setup.py
    develop
    

    Version 2.12:

    CUDA_HOME=/usr/local/cuda-12.6 python setup.py
    develop
    
  • Enforced a C++20 minimum in CMake build files (#178662)

... (truncated)

Commits
  • 0d62256 [release] Dockerfile: skip torchaudio install when CUDA_PATH=cu132 (#183346)
  • 7661cd9 [MPS] Fix SDPA wrong output for permuted q/k/v with B > 1 (#181886)
  • 9da6087 Fix stale PYTORCH_RELEASES_CODE_CC dict (fixes #182250) (#182369)
  • e4c37cc Avoid raw stream name collisions in Inductor (#182178)
  • 822d047 [MPS] Fix bool mask handling in 1-pass SDPA decode kernel (#182285) (#182311)
  • 5c5e523 Add enable_gqa parameter to SDPA MPS meta registration (#181550)
  • eece52e [AOTI] Add BC-safe c_shim v2 for _scaled_dot_product_attention_math_for_mps e...
  • b39330b [Inductor] Call latest c_shim version for versioned fallback ops (#181548)
  • 06f10d0 Revert "[FSDP2] add fqn to communication ops" (#182100) (#182157)
  • 449e339 Revert "[Inductor] Improve materialization heuristic for a chain of computaio...
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=torch&package-manager=uv&previous-version=2.8.0&new-version=2.12.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/semantic-kernel/network/alerts).
--------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GitHub Copilot --- python/pyproject.toml | 2 +- python/uv.lock | 303 ++++++++++++++++++++++++++++-------------- 2 files changed, 204 insertions(+), 101 deletions(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index de05937e93d2..b274b90e8242 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -93,7 +93,7 @@ google = [ hugging_face = [ "transformers[torch] ~= 4.28", "sentence-transformers >= 2.2,< 6.0", - "torch == 2.8.0" + "torch==2.12.0" ] mcp = [ "mcp>=1.8", diff --git a/python/uv.lock b/python/uv.lock index 6db672130626..001063e7362b 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -1223,6 +1223,76 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bc/58/6b3d24e6b9bc474a2dcdee65dfd1f008867015408a271562e4b690561a4d/cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7", size = 3407605, upload-time = "2026-02-10T19:18:29.233Z" }, ] +[[package]] +name = "cuda-bindings" +version = "13.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cuda-pathfinder", marker = "sys_platform == 'linux'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/21/8464d133752951c154feafb3b65c297e7d80f301183d220bec4c830f1441/cuda_bindings-13.3.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:120fcc53d57903df529c3486962c56528cba5b7d6c57c99537320ed9922c8b86", size = 6073403, upload-time = "2026-05-29T23:11:36.22Z" }, + { url = "https://files.pythonhosted.org/packages/a8/1f/5ef51f5fbaa5d4d3201bb3d7555af028ec1aa4416275ccbf73c9e34e3d2d/cuda_bindings-13.3.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9851b0caa8bfd3bc6fa054eaf57bea7c8e9c3a62db2d2621224677f49f3c53d0", size = 6675244, upload-time = "2026-05-29T23:11:38.664Z" }, + { url = "https://files.pythonhosted.org/packages/51/6b/457ca12dad3ee9bfcc9a545cfd6b64b359ba49de40f776f6e028e678f262/cuda_bindings-13.3.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c5879712accf6e14bb01aa5e67440eb84998b8d104b509cc7a6dc0b8f656a474", size = 6053539, upload-time = "2026-05-29T23:11:43.19Z" }, + { url = "https://files.pythonhosted.org/packages/95/7a/c5e3c34a409b148f5c0f5a4ea374158f95d488862c1dffedf9aa5c639df9/cuda_bindings-13.3.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:04436a9364059c84b8f9636f359eccda1cf814341f5b670c71d80d2f79dbc708", size = 6674166, upload-time = "2026-05-29T23:11:45.478Z" }, + { url = "https://files.pythonhosted.org/packages/ce/67/5e7dba1ba576dd73da5dee894ca076ca5e959450dfff66d6d510a255d1f7/cuda_bindings-13.3.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7855c4868aabc0cfae28abbe83d56734bdfbd08f08fc234ac1912a12858bf49", size = 6025351, upload-time = "2026-05-29T23:11:49.685Z" }, + { url = "https://files.pythonhosted.org/packages/39/2a/6d2e9047d1fb243dbaa364b01e0297534b9ed7fd27dba1c9f361519cf69b/cuda_bindings-13.3.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e32d08f71ebcdf00f0f41eab2eb37e8da94c8ed411cc9f7f7a019ce6b34abe3a", size = 6657965, upload-time = "2026-05-29T23:11:52.227Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6e/2394f8163360f8391f8f1b7e72d300a82724edb81a7b7084c799fbd4c91f/cuda_bindings-13.3.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9efb21c1ee64981e184b9e0ba5eb3179e5ba3d4b51665a6cb52b8ef3d01a7cbf", size = 5920504, upload-time = "2026-05-29T23:11:56.883Z" }, + { url = "https://files.pythonhosted.org/packages/34/c2/ef9b6a63f7dc432712a462c816662e662e00d38caa9b861c8c2588195d03/cuda_bindings-13.3.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2732904099e0a4d4db774a5fc6d91ee95fae065b4d2ecabb4968c5fe2406c9d7", size = 6476660, upload-time = "2026-05-29T23:11:59.188Z" }, + { url = "https://files.pythonhosted.org/packages/b1/81/bff68ce829999c1e4209c761bbf903b1c06ec570416ddb25020864ad5907/cuda_bindings-13.3.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ab2f74ed65bfef4163ba07a8db16f1085e0729291db12a2423aff84ee8278b8", size = 6013639, upload-time = "2026-05-29T23:12:03.509Z" }, + { url = "https://files.pythonhosted.org/packages/d4/e0/c8a1f0c8f9ffdea4f5fe6dbab89b326cef4d85caf489dad39e209da89416/cuda_bindings-13.3.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd4c814d311ec08c981f6dded1dbe7d4b371067ee4f6c14cccec4bde9590f80", size = 6534419, upload-time = "2026-05-29T23:12:05.633Z" }, + { url = "https://files.pythonhosted.org/packages/52/b8/83b1f563925b290f2d11a01a77a84013ba56052fe3653a5bef3ccfbb43d6/cuda_bindings-13.3.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3c772dfff49681541d59630c90f858e173ac926b9c593a2b7123f2a1043cc76", size = 5809771, upload-time = "2026-05-29T23:12:10.422Z" }, + { url = "https://files.pythonhosted.org/packages/12/20/e79b4bfe98f075195afb6343d41c498f9dbd2d161d7021d4d28bceb83581/cuda_bindings-13.3.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36febb7c1079d68a981dbbd8d5a67235b399802b82075c9388624719607e52b9", size = 6358584, upload-time = "2026-05-29T23:12:12.767Z" }, +] + +[[package]] +name = "cuda-pathfinder" +version = "1.5.5" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/c8/26f2e4aae92f11522a96043892ba39a90eac610d5242523aa863212bc1c7/cuda_pathfinder-1.5.5-py3-none-any.whl", hash = "sha256:0228c023f95d1480f143ef5c8922d27a2ab052087a942e81dc289c9eb8f91689", size = 51671, upload-time = "2026-05-27T01:21:25.413Z" }, +] + +[[package]] +name = "cuda-toolkit" +version = "13.0.2" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/57/b2/453099f5f3b698d7d0eab38916aac44c7f76229f451709e2eb9db6615dcd/cuda_toolkit-13.0.2-py2.py3-none-any.whl", hash = "sha256:b198824cf2f54003f50d64ada3a0f184b42ca0846c1c94192fa269ecd97a66eb", size = 2364, upload-time = "2025-12-19T23:24:07.328Z" }, +] + +[package.optional-dependencies] +cudart = [ + { name = "nvidia-cuda-runtime", marker = "sys_platform == 'linux'" }, +] +cufft = [ + { name = "nvidia-cufft", marker = "sys_platform == 'linux'" }, +] +cufile = [ + { name = "nvidia-cufile", marker = "sys_platform == 'linux'" }, +] +cupti = [ + { name = "nvidia-cuda-cupti", marker = "sys_platform == 'linux'" }, +] +curand = [ + { name = "nvidia-curand", marker = "sys_platform == 'linux'" }, +] +cusolver = [ + { name = "nvidia-cusolver", marker = "sys_platform == 'linux'" }, +] +cusparse = [ + { name = "nvidia-cusparse", marker = "sys_platform == 'linux'" }, +] +nvjitlink = [ + { name = "nvidia-nvjitlink", marker = "sys_platform == 'linux'" }, +] +nvrtc = [ + { name = "nvidia-cuda-nvrtc", marker = "sys_platform == 'linux'" }, +] +nvtx = [ + { name = "nvidia-nvtx", marker = "sys_platform == 'linux'" }, +] + [[package]] name = "debugpy" version = "1.8.20" @@ -3596,129 +3666,155 @@ wheels = [ ] [[package]] -name = "nvidia-cublas-cu12" -version = "12.8.4.1" +name = "nvidia-cublas" +version = "13.1.1.3" source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-cuda-nvrtc", marker = "sys_platform == 'linux'" }, +] wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/61/e24b560ab2e2eaeb3c839129175fb330dfcfc29e5203196e5541a4c44682/nvidia_cublas_cu12-12.8.4.1-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:8ac4e771d5a348c551b2a426eda6193c19aa630236b418086020df5ba9667142", size = 594346921, upload-time = "2025-03-07T01:44:31.254Z" }, + { url = "https://files.pythonhosted.org/packages/a7/a1/0bd24ee8c8d03adac032fd2909426a00c88f8c57961b1277ded97f91119f/nvidia_cublas-13.1.1.3-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:b7a210458267ac818974c53038fbec2e969d5c99f305ab15c72522fa9f001dd5", size = 542848918, upload-time = "2026-04-08T18:46:22.985Z" }, + { url = "https://files.pythonhosted.org/packages/3b/cd/154ca20c38269e05eff77c1464e6c1da89f50a6390b565e9d82e06bc11e1/nvidia_cublas-13.1.1.3-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:37936a16db8fe4ac1f065c2139360608a543a09275cb1a1af612e08cfa065436", size = 423138758, upload-time = "2026-04-08T18:46:58.655Z" }, ] [[package]] -name = "nvidia-cuda-cupti-cu12" -version = "12.8.90" +name = "nvidia-cuda-cupti" +version = "13.0.85" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f8/02/2adcaa145158bf1a8295d83591d22e4103dbfd821bcaf6f3f53151ca4ffa/nvidia_cuda_cupti_cu12-12.8.90-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ea0cb07ebda26bb9b29ba82cda34849e73c166c18162d3913575b0c9db9a6182", size = 10248621, upload-time = "2025-03-07T01:40:21.213Z" }, + { url = "https://files.pythonhosted.org/packages/2a/2a/80353b103fc20ce05ef51e928daed4b6015db4aaa9162ed0997090fe2250/nvidia_cuda_cupti-13.0.85-py3-none-manylinux_2_25_aarch64.whl", hash = "sha256:796bd679890ee55fb14a94629b698b6db54bcfd833d391d5e94017dd9d7d3151", size = 10310827, upload-time = "2025-09-04T08:26:42.012Z" }, + { url = "https://files.pythonhosted.org/packages/33/6d/737d164b4837a9bbd202f5ae3078975f0525a55730fe871d8ed4e3b952b0/nvidia_cuda_cupti-13.0.85-py3-none-manylinux_2_25_x86_64.whl", hash = "sha256:4eb01c08e859bf924d222250d2e8f8b8ff6d3db4721288cf35d14252a4d933c8", size = 10715597, upload-time = "2025-09-04T08:26:51.312Z" }, ] [[package]] -name = "nvidia-cuda-nvrtc-cu12" -version = "12.8.93" +name = "nvidia-cuda-nvrtc" +version = "13.0.88" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/05/6b/32f747947df2da6994e999492ab306a903659555dddc0fbdeb9d71f75e52/nvidia_cuda_nvrtc_cu12-12.8.93-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:a7756528852ef889772a84c6cd89d41dfa74667e24cca16bb31f8f061e3e9994", size = 88040029, upload-time = "2025-03-07T01:42:13.562Z" }, + { url = "https://files.pythonhosted.org/packages/c3/68/483a78f5e8f31b08fb1bb671559968c0ca3a065ac7acabfc7cee55214fd6/nvidia_cuda_nvrtc-13.0.88-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:ad9b6d2ead2435f11cbb6868809d2adeeee302e9bb94bcf0539c7a40d80e8575", size = 90215200, upload-time = "2025-09-04T08:28:44.204Z" }, + { url = "https://files.pythonhosted.org/packages/b7/dc/6bb80850e0b7edd6588d560758f17e0550893a1feaf436807d64d2da040f/nvidia_cuda_nvrtc-13.0.88-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d27f20a0ca67a4bb34268a5e951033496c5b74870b868bacd046b1b8e0c3267b", size = 43015449, upload-time = "2025-09-04T08:28:20.239Z" }, ] [[package]] -name = "nvidia-cuda-runtime-cu12" -version = "12.8.90" +name = "nvidia-cuda-runtime" +version = "13.0.96" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/9b/a997b638fcd068ad6e4d53b8551a7d30fe8b404d6f1804abf1df69838932/nvidia_cuda_runtime_cu12-12.8.90-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:adade8dcbd0edf427b7204d480d6066d33902cab2a4707dcfc48a2d0fd44ab90", size = 954765, upload-time = "2025-03-07T01:40:01.615Z" }, + { url = "https://files.pythonhosted.org/packages/87/4f/17d7b9b8e285199c58ce28e31b5c5bbaa4d8271af06a89b6405258245de2/nvidia_cuda_runtime-13.0.96-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ef9bcbe90493a2b9d810e43d249adb3d02e98dd30200d86607d8d02687c43f55", size = 2261060, upload-time = "2025-10-09T08:55:15.78Z" }, + { url = "https://files.pythonhosted.org/packages/2e/24/d1558f3b68b1d26e706813b1d10aa1d785e4698c425af8db8edc3dced472/nvidia_cuda_runtime-13.0.96-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7f82250d7782aa23b6cfe765ecc7db554bd3c2870c43f3d1821f1d18aebf0548", size = 2243632, upload-time = "2025-10-09T08:55:36.117Z" }, ] [[package]] -name = "nvidia-cudnn-cu12" -version = "9.10.2.21" +name = "nvidia-cudnn-cu13" +version = "9.20.0.48" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cublas-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cublas", marker = "sys_platform == 'linux'" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/51/e123d997aa098c61d029f76663dedbfb9bc8dcf8c60cbd6adbe42f76d049/nvidia_cudnn_cu12-9.10.2.21-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:949452be657fa16687d0930933f032835951ef0892b37d2d53824d1a84dc97a8", size = 706758467, upload-time = "2025-06-06T21:54:08.597Z" }, + { url = "https://files.pythonhosted.org/packages/56/c5/83384d846b2fd17c44bd499b36c75a45ed4f095fbbb2252294e89cea5c5c/nvidia_cudnn_cu13-9.20.0.48-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:e31454ae00094b0c55319d9d15b6fa2fc50a9e1c0f5c8c80fb75258234e731e1", size = 444574296, upload-time = "2026-03-09T19:28:27.751Z" }, + { url = "https://files.pythonhosted.org/packages/6e/5e/edb9c0ae051602c3ccaffe424256463636d639e27d7f302dde9975ef9e7a/nvidia_cudnn_cu13-9.20.0.48-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:0c45dd8eeb50b603f07995b1b300c62ffe6a1980482b82b3bcf94a4ca9d49304", size = 366173588, upload-time = "2026-03-09T19:29:34.474Z" }, ] [[package]] -name = "nvidia-cufft-cu12" -version = "11.3.3.83" +name = "nvidia-cufft" +version = "12.0.0.61" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nvjitlink", marker = "sys_platform == 'linux'" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/13/ee4e00f30e676b66ae65b4f08cb5bcbb8392c03f54f2d5413ea99a5d1c80/nvidia_cufft_cu12-11.3.3.83-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d2dd21ec0b88cf61b62e6b43564355e5222e4a3fb394cac0db101f2dd0d4f74", size = 193118695, upload-time = "2025-03-07T01:45:27.821Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ae/f417a75c0259e85c1d2f83ca4e960289a5f814ed0cea74d18c353d3e989d/nvidia_cufft-12.0.0.61-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2708c852ef8cd89d1d2068bdbece0aa188813a0c934db3779b9b1faa8442e5f5", size = 214053554, upload-time = "2025-09-04T08:31:38.196Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2f/7b57e29836ea8714f81e9898409196f47d772d5ddedddf1592eadb8ab743/nvidia_cufft-12.0.0.61-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6c44f692dce8fd5ffd3e3df134b6cdb9c2f72d99cf40b62c32dde45eea9ddad3", size = 214085489, upload-time = "2025-09-04T08:31:56.044Z" }, ] [[package]] -name = "nvidia-cufile-cu12" -version = "1.13.1.3" +name = "nvidia-cufile" +version = "1.15.1.6" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bb/fe/1bcba1dfbfb8d01be8d93f07bfc502c93fa23afa6fd5ab3fc7c1df71038a/nvidia_cufile_cu12-1.13.1.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1d069003be650e131b21c932ec3d8969c1715379251f8d23a1860554b1cb24fc", size = 1197834, upload-time = "2025-03-07T01:45:50.723Z" }, + { url = "https://files.pythonhosted.org/packages/3f/70/4f193de89a48b71714e74602ee14d04e4019ad36a5a9f20c425776e72cd6/nvidia_cufile-1.15.1.6-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:08a3ecefae5a01c7f5117351c64f17c7c62efa5fffdbe24fc7d298da19cd0b44", size = 1223672, upload-time = "2025-09-04T08:32:22.779Z" }, + { url = "https://files.pythonhosted.org/packages/ab/73/cc4a14c9813a8a0d509417cf5f4bdaba76e924d58beb9864f5a7baceefbf/nvidia_cufile-1.15.1.6-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:bdc0deedc61f548bddf7733bdc216456c2fdb101d020e1ab4b88d232d5e2f6d1", size = 1136992, upload-time = "2025-09-04T08:32:14.119Z" }, ] [[package]] -name = "nvidia-curand-cu12" -version = "10.3.9.90" +name = "nvidia-curand" +version = "10.4.0.35" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/aa/6584b56dc84ebe9cf93226a5cde4d99080c8e90ab40f0c27bda7a0f29aa1/nvidia_curand_cu12-10.3.9.90-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:b32331d4f4df5d6eefa0554c565b626c7216f87a06a4f56fab27c3b68a830ec9", size = 63619976, upload-time = "2025-03-07T01:46:23.323Z" }, + { url = "https://files.pythonhosted.org/packages/1e/72/7c2ae24fb6b63a32e6ae5d241cc65263ea18d08802aaae087d9f013335a2/nvidia_curand-10.4.0.35-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:133df5a7509c3e292aaa2b477afd0194f06ce4ea24d714d616ff36439cee349a", size = 61962106, upload-time = "2025-08-04T10:21:41.128Z" }, + { url = "https://files.pythonhosted.org/packages/a5/9f/be0a41ca4a4917abf5cb9ae0daff1a6060cc5de950aec0396de9f3b52bc5/nvidia_curand-10.4.0.35-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:1aee33a5da6e1db083fe2b90082def8915f30f3248d5896bcec36a579d941bfc", size = 59544258, upload-time = "2025-08-04T10:22:03.992Z" }, ] [[package]] -name = "nvidia-cusolver-cu12" -version = "11.7.3.90" +name = "nvidia-cusolver" +version = "12.0.4.66" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cublas-cu12", marker = "sys_platform == 'linux'" }, - { name = "nvidia-cusparse-cu12", marker = "sys_platform == 'linux'" }, - { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cublas", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cusparse", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nvjitlink", marker = "sys_platform == 'linux'" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/85/48/9a13d2975803e8cf2777d5ed57b87a0b6ca2cc795f9a4f59796a910bfb80/nvidia_cusolver_cu12-11.7.3.90-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:4376c11ad263152bd50ea295c05370360776f8c3427b30991df774f9fb26c450", size = 267506905, upload-time = "2025-03-07T01:47:16.273Z" }, + { url = "https://files.pythonhosted.org/packages/c8/c3/b30c9e935fc01e3da443ec0116ed1b2a009bb867f5324d3f2d7e533e776b/nvidia_cusolver-12.0.4.66-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:02c2457eaa9e39de20f880f4bd8820e6a1cfb9f9a34f820eb12a155aa5bc92d2", size = 223467760, upload-time = "2025-09-04T08:33:04.222Z" }, + { url = "https://files.pythonhosted.org/packages/5f/67/cba3777620cdacb99102da4042883709c41c709f4b6323c10781a9c3aa34/nvidia_cusolver-12.0.4.66-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:0a759da5dea5c0ea10fd307de75cdeb59e7ea4fcb8add0924859b944babf1112", size = 200941980, upload-time = "2025-09-04T08:33:22.767Z" }, ] [[package]] -name = "nvidia-cusparse-cu12" -version = "12.5.8.93" +name = "nvidia-cusparse" +version = "12.6.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nvjitlink", marker = "sys_platform == 'linux'" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/f5/e1854cb2f2bcd4280c44736c93550cc300ff4b8c95ebe370d0aa7d2b473d/nvidia_cusparse_cu12-12.5.8.93-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ec05d76bbbd8b61b06a80e1eaf8cf4959c3d4ce8e711b65ebd0443bb0ebb13b", size = 288216466, upload-time = "2025-03-07T01:48:13.779Z" }, + { url = "https://files.pythonhosted.org/packages/f8/94/5c26f33738ae35276672f12615a64bd008ed5be6d1ebcb23579285d960a9/nvidia_cusparse-12.6.3.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:80bcc4662f23f1054ee334a15c72b8940402975e0eab63178fc7e670aa59472c", size = 162155568, upload-time = "2025-09-04T08:33:42.864Z" }, + { url = "https://files.pythonhosted.org/packages/fa/18/623c77619c31d62efd55302939756966f3ecc8d724a14dab2b75f1508850/nvidia_cusparse-12.6.3.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2b3c89c88d01ee0e477cb7f82ef60a11a4bcd57b6b87c33f789350b59759360b", size = 145942937, upload-time = "2025-09-04T08:33:58.029Z" }, ] [[package]] -name = "nvidia-cusparselt-cu12" -version = "0.7.1" +name = "nvidia-cusparselt-cu13" +version = "0.8.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/e1/cdc1797eadf82d3a9a575a19b33fdc871a97edbec42c00b5b5e914f4aff4/nvidia_cusparselt_cu13-0.8.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4dca476c50bf4780d46cd0bfbd82e2bc10a08e4fef7950917ce8d7578d22a23f", size = 221051344, upload-time = "2025-09-05T18:49:51.289Z" }, + { url = "https://files.pythonhosted.org/packages/34/7d/2661f2fb3ac4302f3a246f5fc030213ac60c1fe0bce84f9783dbd831dbb7/nvidia_cusparselt_cu13-0.8.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:786ce87568c303fadb5afcc7102d454cd3040d75f6f8626f5db460d1871f4dd0", size = 170148586, upload-time = "2025-09-05T18:50:50.248Z" }, +] + +[[package]] +name = "nvidia-nccl-cu13" +version = "2.29.7" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/56/79/12978b96bd44274fe38b5dde5cfb660b1d114f70a65ef962bcbbed99b549/nvidia_cusparselt_cu12-0.7.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:f1bb701d6b930d5a7cea44c19ceb973311500847f81b634d802b7b539dc55623", size = 287193691, upload-time = "2025-02-26T00:15:44.104Z" }, + { url = "https://files.pythonhosted.org/packages/72/0d/daf50d44177ee0cbc7ff0a0c91eb5ff676c82be42f9a970bc7597f440c3a/nvidia_nccl_cu13-2.29.7-py3-none-manylinux_2_18_aarch64.whl", hash = "sha256:674a12383e3c38a1bcccae7d4f3633b37852230b6047883cb2f4c2d1b36d9bf5", size = 206014712, upload-time = "2026-03-03T05:34:20.843Z" }, + { url = "https://files.pythonhosted.org/packages/67/f4/58e4e91b6919367c7aafb8e36fce9aad1a3047e536bf7e2fd560927d3a4c/nvidia_nccl_cu13-2.29.7-py3-none-manylinux_2_18_x86_64.whl", hash = "sha256:edd81538446786ec3b73972543e53bb43bcaf0bfc8ef76cb679fcc390ffe136d", size = 205976000, upload-time = "2026-03-03T05:36:24.472Z" }, ] [[package]] -name = "nvidia-nccl-cu12" -version = "2.27.3" +name = "nvidia-nvjitlink" +version = "13.0.88" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/5b/4e4fff7bad39adf89f735f2bc87248c81db71205b62bcc0d5ca5b606b3c3/nvidia_nccl_cu12-2.27.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:adf27ccf4238253e0b826bce3ff5fa532d65fc42322c8bfdfaf28024c0fbe039", size = 322364134, upload-time = "2025-06-03T21:58:04.013Z" }, + { url = "https://files.pythonhosted.org/packages/56/7a/123e033aaff487c77107195fa5a2b8686795ca537935a24efae476c41f05/nvidia_nvjitlink-13.0.88-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:13a74f429e23b921c1109976abefacc69835f2f433ebd323d3946e11d804e47b", size = 40713933, upload-time = "2025-09-04T08:35:43.553Z" }, + { url = "https://files.pythonhosted.org/packages/ab/2c/93c5250e64df4f894f1cbb397c6fd71f79813f9fd79d7cd61de3f97b3c2d/nvidia_nvjitlink-13.0.88-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e931536ccc7d467a98ba1d8b89ff7fa7f1fa3b13f2b0069118cd7f47bff07d0c", size = 38768748, upload-time = "2025-09-04T08:35:20.008Z" }, ] [[package]] -name = "nvidia-nvjitlink-cu12" -version = "12.8.93" +name = "nvidia-nvshmem-cu13" +version = "3.4.5" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f6/74/86a07f1d0f42998ca31312f998bd3b9a7eff7f52378f4f270c8679c77fb9/nvidia_nvjitlink_cu12-12.8.93-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:81ff63371a7ebd6e6451970684f916be2eab07321b73c9d244dc2b4da7f73b88", size = 39254836, upload-time = "2025-03-07T01:49:55.661Z" }, + { url = "https://files.pythonhosted.org/packages/dc/0f/05cc9c720236dcd2db9c1ab97fff629e96821be2e63103569da0c9b72f19/nvidia_nvshmem_cu13-3.4.5-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6dc2a197f38e5d0376ad52cd1a2a3617d3cdc150fd5966f4aee9bcebb1d68fe9", size = 60215947, upload-time = "2025-09-06T00:32:20.022Z" }, + { url = "https://files.pythonhosted.org/packages/3c/35/a9bf80a609e74e3b000fef598933235c908fcefcef9026042b8e6dfde2a9/nvidia_nvshmem_cu13-3.4.5-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:290f0a2ee94c9f3687a02502f3b9299a9f9fe826e6d0287ee18482e78d495b80", size = 60412546, upload-time = "2025-09-06T00:32:41.564Z" }, ] [[package]] -name = "nvidia-nvtx-cu12" -version = "12.8.90" +name = "nvidia-nvtx" +version = "13.0.85" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/eb/86626c1bbc2edb86323022371c39aa48df6fd8b0a1647bc274577f72e90b/nvidia_nvtx_cu12-12.8.90-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5b17e2001cc0d751a5bc2c6ec6d26ad95913324a4adb86788c944f8ce9ba441f", size = 89954, upload-time = "2025-03-07T01:42:44.131Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f3/d86c845465a2723ad7e1e5c36dcd75ddb82898b3f53be47ebd429fb2fa5d/nvidia_nvtx-13.0.85-py3-none-manylinux1_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4936d1d6780fbe68db454f5e72a42ff64d1fd6397df9f363ae786930fd5c1cd4", size = 148047, upload-time = "2025-09-04T08:29:01.761Z" }, + { url = "https://files.pythonhosted.org/packages/a8/64/3708a90d1ebe202ffdeb7185f878a3c84d15c2b2c31858da2ce0583e2def/nvidia_nvtx-13.0.85-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cb7780edb6b14107373c835bf8b72e7a178bac7367e23da7acb108f973f157a6", size = 148878, upload-time = "2025-09-04T08:28:53.627Z" }, ] [[package]] @@ -6539,7 +6635,7 @@ requires-dist = [ { name = "redisvl", marker = "extra == 'redis'", specifier = "~=0.4" }, { name = "scipy", specifier = ">=1.15.1" }, { name = "sentence-transformers", marker = "extra == 'hugging-face'", specifier = ">=2.2,<6.0" }, - { name = "torch", marker = "extra == 'hugging-face'", specifier = "==2.8.0" }, + { name = "torch", marker = "extra == 'hugging-face'", specifier = "==2.12.0" }, { name = "transformers", extras = ["torch"], marker = "extra == 'hugging-face'", specifier = "~=4.28" }, { name = "types-redis", marker = "extra == 'redis'", specifier = "~=4.6.0.20240425" }, { name = "typing-extensions", specifier = ">=4.13" }, @@ -6589,11 +6685,11 @@ wheels = [ [[package]] name = "setuptools" -version = "82.0.1" +version = "81.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4f/db/cfac1baf10650ab4d1c111714410d2fbb77ac5a616db26775db562c8fab2/setuptools-82.0.1.tar.gz", hash = "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9", size = 1152316, upload-time = "2026-03-09T12:47:17.221Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/1c/73e719955c59b8e424d015ab450f51c0af856ae46ea2da83eba51cc88de1/setuptools-81.0.0.tar.gz", hash = "sha256:487b53915f52501f0a79ccfd0c02c165ffe06631443a886740b91af4b7a5845a", size = 1198299, upload-time = "2026-02-06T21:10:39.601Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl", hash = "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb", size = 1006223, upload-time = "2026-03-09T12:47:15.026Z" }, + { url = "https://files.pythonhosted.org/packages/e1/e3/c164c88b2e5ce7b24d667b9bd83589cf4f3520d97cad01534cd3c4f55fdb/setuptools-81.0.0-py3-none-any.whl", hash = "sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6", size = 1062021, upload-time = "2026-02-06T21:10:37.175Z" }, ] [[package]] @@ -6955,54 +7051,55 @@ wheels = [ [[package]] name = "torch" -version = "2.8.0" +version = "2.12.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "cuda-bindings", marker = "sys_platform == 'linux'" }, + { name = "cuda-toolkit", extra = ["cudart", "cufft", "cufile", "cupti", "curand", "cusolver", "cusparse", "nvjitlink", "nvrtc", "nvtx"], marker = "sys_platform == 'linux'" }, { name = "filelock", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "fsspec", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "jinja2", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "networkx", version = "3.4.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, { name = "networkx", version = "3.6.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "nvidia-cublas-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cuda-cupti-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cuda-nvrtc-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cuda-runtime-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cudnn-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cufft-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cufile-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-curand-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cusolver-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cusparse-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cusparselt-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-nccl-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-nvjitlink-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-nvtx-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "setuptools", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "nvidia-cublas", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cudnn-cu13", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cusparselt-cu13", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nccl-cu13", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nvshmem-cu13", marker = "sys_platform == 'linux'" }, + { name = "setuptools", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "sympy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "triton", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "triton", marker = "sys_platform == 'linux'" }, { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/63/28/110f7274254f1b8476c561dada127173f994afa2b1ffc044efb773c15650/torch-2.8.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:0be92c08b44009d4131d1ff7a8060d10bafdb7ddcb7359ef8d8c5169007ea905", size = 102052793, upload-time = "2025-08-06T14:53:15.852Z" }, - { url = "https://files.pythonhosted.org/packages/70/1c/58da560016f81c339ae14ab16c98153d51c941544ae568da3cb5b1ceb572/torch-2.8.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:89aa9ee820bb39d4d72b794345cccef106b574508dd17dbec457949678c76011", size = 888025420, upload-time = "2025-08-06T14:54:18.014Z" }, - { url = "https://files.pythonhosted.org/packages/70/87/f69752d0dd4ba8218c390f0438130c166fa264a33b7025adb5014b92192c/torch-2.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e8e5bf982e87e2b59d932769938b698858c64cc53753894be25629bdf5cf2f46", size = 241363614, upload-time = "2025-08-06T14:53:31.496Z" }, - { url = "https://files.pythonhosted.org/packages/ef/d6/e6d4c57e61c2b2175d3aafbfb779926a2cfd7c32eeda7c543925dceec923/torch-2.8.0-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:a3f16a58a9a800f589b26d47ee15aca3acf065546137fc2af039876135f4c760", size = 73611154, upload-time = "2025-08-06T14:53:10.919Z" }, - { url = "https://files.pythonhosted.org/packages/8f/c4/3e7a3887eba14e815e614db70b3b529112d1513d9dae6f4d43e373360b7f/torch-2.8.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:220a06fd7af8b653c35d359dfe1aaf32f65aa85befa342629f716acb134b9710", size = 102073391, upload-time = "2025-08-06T14:53:20.937Z" }, - { url = "https://files.pythonhosted.org/packages/5a/63/4fdc45a0304536e75a5e1b1bbfb1b56dd0e2743c48ee83ca729f7ce44162/torch-2.8.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:c12fa219f51a933d5f80eeb3a7a5d0cbe9168c0a14bbb4055f1979431660879b", size = 888063640, upload-time = "2025-08-06T14:55:05.325Z" }, - { url = "https://files.pythonhosted.org/packages/84/57/2f64161769610cf6b1c5ed782bd8a780e18a3c9d48931319f2887fa9d0b1/torch-2.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:8c7ef765e27551b2fbfc0f41bcf270e1292d9bf79f8e0724848b1682be6e80aa", size = 241366752, upload-time = "2025-08-06T14:53:38.692Z" }, - { url = "https://files.pythonhosted.org/packages/a4/5e/05a5c46085d9b97e928f3f037081d3d2b87fb4b4195030fc099aaec5effc/torch-2.8.0-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:5ae0524688fb6707c57a530c2325e13bb0090b745ba7b4a2cd6a3ce262572916", size = 73621174, upload-time = "2025-08-06T14:53:25.44Z" }, - { url = "https://files.pythonhosted.org/packages/49/0c/2fd4df0d83a495bb5e54dca4474c4ec5f9c62db185421563deeb5dabf609/torch-2.8.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:e2fab4153768d433f8ed9279c8133a114a034a61e77a3a104dcdf54388838705", size = 101906089, upload-time = "2025-08-06T14:53:52.631Z" }, - { url = "https://files.pythonhosted.org/packages/99/a8/6acf48d48838fb8fe480597d98a0668c2beb02ee4755cc136de92a0a956f/torch-2.8.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2aca0939fb7e4d842561febbd4ffda67a8e958ff725c1c27e244e85e982173c", size = 887913624, upload-time = "2025-08-06T14:56:44.33Z" }, - { url = "https://files.pythonhosted.org/packages/af/8a/5c87f08e3abd825c7dfecef5a0f1d9aa5df5dd0e3fd1fa2f490a8e512402/torch-2.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:2f4ac52f0130275d7517b03a33d2493bab3693c83dcfadf4f81688ea82147d2e", size = 241326087, upload-time = "2025-08-06T14:53:46.503Z" }, - { url = "https://files.pythonhosted.org/packages/be/66/5c9a321b325aaecb92d4d1855421e3a055abd77903b7dab6575ca07796db/torch-2.8.0-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:619c2869db3ada2c0105487ba21b5008defcc472d23f8b80ed91ac4a380283b0", size = 73630478, upload-time = "2025-08-06T14:53:57.144Z" }, - { url = "https://files.pythonhosted.org/packages/10/4e/469ced5a0603245d6a19a556e9053300033f9c5baccf43a3d25ba73e189e/torch-2.8.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:2b2f96814e0345f5a5aed9bf9734efa913678ed19caf6dc2cddb7930672d6128", size = 101936856, upload-time = "2025-08-06T14:54:01.526Z" }, - { url = "https://files.pythonhosted.org/packages/16/82/3948e54c01b2109238357c6f86242e6ecbf0c63a1af46906772902f82057/torch-2.8.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:65616ca8ec6f43245e1f5f296603e33923f4c30f93d65e103d9e50c25b35150b", size = 887922844, upload-time = "2025-08-06T14:55:50.78Z" }, - { url = "https://files.pythonhosted.org/packages/e3/54/941ea0a860f2717d86a811adf0c2cd01b3983bdd460d0803053c4e0b8649/torch-2.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:659df54119ae03e83a800addc125856effda88b016dfc54d9f65215c3975be16", size = 241330968, upload-time = "2025-08-06T14:54:45.293Z" }, - { url = "https://files.pythonhosted.org/packages/de/69/8b7b13bba430f5e21d77708b616f767683629fc4f8037564a177d20f90ed/torch-2.8.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:1a62a1ec4b0498930e2543535cf70b1bef8c777713de7ceb84cd79115f553767", size = 73915128, upload-time = "2025-08-06T14:54:34.769Z" }, - { url = "https://files.pythonhosted.org/packages/15/0e/8a800e093b7f7430dbaefa80075aee9158ec22e4c4fc3c1a66e4fb96cb4f/torch-2.8.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:83c13411a26fac3d101fe8035a6b0476ae606deb8688e904e796a3534c197def", size = 102020139, upload-time = "2025-08-06T14:54:39.047Z" }, - { url = "https://files.pythonhosted.org/packages/4a/15/5e488ca0bc6162c86a33b58642bc577c84ded17c7b72d97e49b5833e2d73/torch-2.8.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:8f0a9d617a66509ded240add3754e462430a6c1fc5589f86c17b433dd808f97a", size = 887990692, upload-time = "2025-08-06T14:56:18.286Z" }, - { url = "https://files.pythonhosted.org/packages/b4/a8/6a04e4b54472fc5dba7ca2341ab219e529f3c07b6941059fbf18dccac31f/torch-2.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:a7242b86f42be98ac674b88a4988643b9bc6145437ec8f048fea23f72feb5eca", size = 241603453, upload-time = "2025-08-06T14:55:22.945Z" }, - { url = "https://files.pythonhosted.org/packages/04/6e/650bb7f28f771af0cb791b02348db8b7f5f64f40f6829ee82aa6ce99aabe/torch-2.8.0-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:7b677e17f5a3e69fdef7eb3b9da72622f8d322692930297e4ccb52fefc6c8211", size = 73632395, upload-time = "2025-08-06T14:55:28.645Z" }, + { url = "https://files.pythonhosted.org/packages/c2/b7/53fe0436586716ab7aecff41e26b9302d57c85ded481fd83a2cd741e6b4e/torch-2.12.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:1834bd984f8a2f4f16bdfbeecca9146184b220aa46276bf5756735b5dae12812", size = 87981887, upload-time = "2026-05-13T14:55:53.234Z" }, + { url = "https://files.pythonhosted.org/packages/34/60/d930eac44c30de06ed16f6d1ba4e785e1632532b50d8f0bf9bf699a4d0c7/torch-2.12.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:d4d029801cb7b6df858804a2a21b00cc2aa0bf0ee5d2ab18d343c9e9e5681f35", size = 426355000, upload-time = "2026-05-13T14:54:31.944Z" }, + { url = "https://files.pythonhosted.org/packages/8e/0c/c76b6a087820bab55705b94dfc074e520de9ae91f5ef90da2ecbf2a3ef12/torch-2.12.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:d47e7dee68ac4cd7a068b26bcd6b989935427709fae1c8f7bd0019978f829e15", size = 532144998, upload-time = "2026-05-13T14:56:05.523Z" }, + { url = "https://files.pythonhosted.org/packages/4a/64/8a0d036e166a6aa85ee09bef072f3655d1ba5d5486a68d1b03b6813c01b3/torch-2.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:cf9839790285dd472e7a16aafcb4a4e6bf58ec1b494045044b0eefb0eb4bd1f2", size = 122949877, upload-time = "2026-05-13T14:55:46.841Z" }, + { url = "https://files.pythonhosted.org/packages/18/62/131124fb95df03811b8260d1d43dcc5ee85ea1a344b964613d7efe77fb08/torch-2.12.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:10802fd383bbfed646212e765a72c37d2185205d4f26eb197a254e8ac7ddcb25", size = 87990344, upload-time = "2026-05-13T14:55:42.154Z" }, + { url = "https://files.pythonhosted.org/packages/12/9c/dda0dbd547dc549839824135f223792fd0e725f28ed0715dda366b7acaa2/torch-2.12.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c12592630aef72feaf18bd3f197ef587bbfa21131b31c38b23ab2e55fce92e36", size = 426362932, upload-time = "2026-05-13T14:54:15.295Z" }, + { url = "https://files.pythonhosted.org/packages/e2/d2/a7dd5a3f9bdaa7842124e8e2359202b317c48d47d2fc5816fafdf2049adb/torch-2.12.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:415c1b8d0412f67551c8e89a2daca0fb3e56694af0281ba155eaa9da481f58b4", size = 532170085, upload-time = "2026-05-13T14:55:20.788Z" }, + { url = "https://files.pythonhosted.org/packages/12/1b/a61ce2004f9ab0ea8964a6e6168133a127795667639e2ff4f8f2bdb16a65/torch-2.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:dd37188ea325042cb1f6cafa56822b11ada2520c04791a52629b0af25bdfbfd9", size = 122953128, upload-time = "2026-05-13T14:54:52.744Z" }, + { url = "https://files.pythonhosted.org/packages/ef/bb/285d643f254731294c9b595a007eac39db4600a98682d7bca688f42ca164/torch-2.12.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:b41339df93d491435e790ff8bcbae1c0ce777175889bfd1281d119862793e6a2", size = 88010197, upload-time = "2026-05-13T14:55:35.414Z" }, + { url = "https://files.pythonhosted.org/packages/79/81/76debf1db1343bd929bbb5d74c89fb437c2ed88eb144712557e7bd3eea45/torch-2.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:8fbef9f108a863e7722a73740998967e3b074742a834fc5be3a535a2befa7057", size = 426376751, upload-time = "2026-05-13T14:55:03.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/f0/80026028b603c4650ff270fc3785bdef4bd6738765a9cc5a0f5a637d65a2/torch-2.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4b4f64c2c2b11f7510d93dd6412b87025ff6eddd6bb61c3b5a3d892ea20c4756", size = 532261691, upload-time = "2026-05-13T14:52:54.453Z" }, + { url = "https://files.pythonhosted.org/packages/b9/c2/64b06cbb7830fb3cd9be13e1158b31a3f36b68e6a209105ee3c9d9480be0/torch-2.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:8b958caff4a14d3a3b0b2dfc6a378f64dda9728a9dad28c08a0db9ce4dafb549", size = 122988114, upload-time = "2026-05-13T14:54:42.153Z" }, + { url = "https://files.pythonhosted.org/packages/86/ca/01896c80ba921676aa45886b2c5b8d774912de2a1f719de48169c6f755cd/torch-2.12.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:90dd587a5f61bfe1307148b581e2084fc5bc4a06e2b90a20e9a36b81087ff16b", size = 88009511, upload-time = "2026-05-13T14:54:47.411Z" }, + { url = "https://files.pythonhosted.org/packages/a5/04/52bdaf4787eab6ac7d7f5851dff934e4def0bc8ead9c8fd2b69b3e529699/torch-2.12.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:864392c73b7654f4d2b3ae712f607937d0dbb1101c4555fbb41848106b297f39", size = 426383231, upload-time = "2026-05-13T14:53:32.129Z" }, + { url = "https://files.pythonhosted.org/packages/49/8a/94bdecd13f5aaa90d45920b89789d9fe7c6f4af8c3cdd7ce01fcb59908fc/torch-2.12.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5d6b560dfa7d56291c07d615c3bb73e8d9943d9b6d87f76cd0d9d570c4797fa6", size = 532269288, upload-time = "2026-05-13T14:53:49.423Z" }, + { url = "https://files.pythonhosted.org/packages/3e/2f/bdbaaa267de519ef1b73054bf590d8c93c37a266c9a4e24a01bd38b6918f/torch-2.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:3fee918902090ade827643e758e98363278815de583c75d111fdd665ebffde9f", size = 122987706, upload-time = "2026-05-13T14:54:00.335Z" }, + { url = "https://files.pythonhosted.org/packages/9b/ad/e95e822f3538171e22640a7fbe839a1fdb666600bf6487025de2ff03b11a/torch-2.12.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:10ee1448a9f304d3b987eb4656f664ba6e4d7b410ca7a5a7c642199777a2cf88", size = 88319556, upload-time = "2026-05-13T14:54:05.574Z" }, + { url = "https://files.pythonhosted.org/packages/b7/07/055d06d985b445d67422d25b033c11cf55bbb81785d4c4e68e28bca5820e/torch-2.12.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:af68dbf403439cae9ceaeaaf92f8352b460787dcd27b92aa05c40dd4a19c0f1e", size = 426397656, upload-time = "2026-05-13T14:52:38.84Z" }, + { url = "https://files.pythonhosted.org/packages/43/94/b0b4fdc3014122e0a7302fb90086d352aa48f2576f0b252561ebb38c01a8/torch-2.12.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:a6a2eebb237d3b1d9ad3b378e86d9b9e0782afdea8b1e0eba6a13646b9b49c07", size = 532183124, upload-time = "2026-05-13T14:53:16.178Z" }, + { url = "https://files.pythonhosted.org/packages/d8/c8/052405e6ad05d3237bfe5a4df78f917773956f8e17813a2d44c059068b74/torch-2.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2140e373e9a51a3e22ef62e8d14366d0b470d18f0adf19fdc757368077133a34", size = 123232462, upload-time = "2026-05-13T14:52:27.26Z" }, + { url = "https://files.pythonhosted.org/packages/67/dc/ac069f8d6e8be701535921141055293b0d4819d3d7f224a4612cf157c7f9/torch-2.12.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f7dfae4a519197dfa050e98d8e36378a0fb5899625a875c2b54445005a2e404e", size = 88027282, upload-time = "2026-05-13T14:53:05.258Z" }, + { url = "https://files.pythonhosted.org/packages/33/c3/1c1eb00e34555b536dddf792676026a988d710ed36981aa00499b36b0620/torch-2.12.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:891c769072637c74e9a5a77a3bc782894696d8ffec83b938df8536dee7f0ba78", size = 426386961, upload-time = "2026-05-13T14:51:28.406Z" }, + { url = "https://files.pythonhosted.org/packages/cd/d4/7e730dba0c7032a4154dc9056b76cf9625515e030e269cfbf8098fcfee7d/torch-2.12.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:e2ad3eb85d39c3cab62dfa93ed5a73516e6a53c6713cb97d004004fe089f0f1f", size = 532272265, upload-time = "2026-05-13T14:51:59.308Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b4/92c80d1bbfee1c0036c06d1d2155a3065bd2423134c83bf8a47e65cd6b9b/torch-2.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:c66696857e987efb8bc1777a37357ec4f60ab5e8af6250b83d6034437fa2d8f3", size = 122987138, upload-time = "2026-05-13T14:51:45.942Z" }, + { url = "https://files.pythonhosted.org/packages/7b/78/2e12b37ce50a19a037d7bc62d652a5a8f27385a7b05859d6bc9204f20cfe/torch-2.12.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:b4556715c8572758625d62b6e0ae3b1f76c440221913a6fb5e100f321fb4fb02", size = 88320100, upload-time = "2026-05-13T14:51:39.955Z" }, + { url = "https://files.pythonhosted.org/packages/56/5e/83c450ec7b0bb40a7b74611c1b5440f9260e33c54c90d556fd4a1f0fd955/torch-2.12.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:a43ac605a5e13116c72b64c359644cce0229f213dde48d2ae0ae5eb5becf7feb", size = 426391871, upload-time = "2026-05-13T14:52:14.989Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e9/1a0b575d98d0afedd8f157d23fa3d2759421483660448e60d0a4b10b6daa/torch-2.12.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:6a7512adfdd7f6732e40de1c620831e3c75b39b98cef60b11d0c5f0a76473ec5", size = 532192241, upload-time = "2026-05-13T14:51:07.795Z" }, + { url = "https://files.pythonhosted.org/packages/88/21/afadd25ecd81b3cea1e11c73cf1ab41a983a50271548c3ec7ec3b9efc3e9/torch-2.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:5f96b63f8287f66a005dd1b5a6abba2920f11156c5e5c4d815f3e2050fd1aa16", size = 123231092, upload-time = "2026-05-13T14:51:18.854Z" }, ] [[package]] @@ -7072,17 +7169,23 @@ torch = [ [[package]] name = "triton" -version = "3.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "setuptools", marker = "sys_platform == 'linux'" }, -] -wheels = [ - { url = "https://files.pythonhosted.org/packages/62/ee/0ee5f64a87eeda19bbad9bc54ae5ca5b98186ed00055281fd40fb4beb10e/triton-3.4.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ff2785de9bc02f500e085420273bb5cc9c9bb767584a4aa28d6e360cec70128", size = 155430069, upload-time = "2025-07-30T19:58:21.715Z" }, - { url = "https://files.pythonhosted.org/packages/7d/39/43325b3b651d50187e591eefa22e236b2981afcebaefd4f2fc0ea99df191/triton-3.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b70f5e6a41e52e48cfc087436c8a28c17ff98db369447bcaff3b887a3ab4467", size = 155531138, upload-time = "2025-07-30T19:58:29.908Z" }, - { url = "https://files.pythonhosted.org/packages/d0/66/b1eb52839f563623d185f0927eb3530ee4d5ffe9d377cdaf5346b306689e/triton-3.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:31c1d84a5c0ec2c0f8e8a072d7fd150cab84a9c239eaddc6706c081bfae4eb04", size = 155560068, upload-time = "2025-07-30T19:58:37.081Z" }, - { url = "https://files.pythonhosted.org/packages/30/7b/0a685684ed5322d2af0bddefed7906674f67974aa88b0fae6e82e3b766f6/triton-3.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00be2964616f4c619193cb0d1b29a99bd4b001d7dc333816073f92cf2a8ccdeb", size = 155569223, upload-time = "2025-07-30T19:58:44.017Z" }, - { url = "https://files.pythonhosted.org/packages/20/63/8cb444ad5cdb25d999b7d647abac25af0ee37d292afc009940c05b82dda0/triton-3.4.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7936b18a3499ed62059414d7df563e6c163c5e16c3773678a3ee3d417865035d", size = 155659780, upload-time = "2025-07-30T19:58:51.171Z" }, +version = "3.7.0" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3e/97/dcd1f2a0f8336691bff74abc59b2ed9c69a0c0f8f65cd77109c49e05f068/triton-3.7.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223ac302091491436c248a34ee1e6c47a1026486579103c906ffd805be50cb89", size = 188367104, upload-time = "2026-05-07T19:04:56.68Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c0/c2ac4fd2d8809b7579d4a820a0f9e5de62a9bc8a757ed4b3abf4f7ee964a/triton-3.7.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c631b65668d4951213b948a413c0564184305b77bb45cc9d686d3e1ecc4701a3", size = 201313191, upload-time = "2026-05-07T18:45:58.444Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c1/5d842314bb6c78442cc60437928781701c6050b8d479bc2a1aed691d37ca/triton-3.7.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9e71fc392675fac364e0ecf4ef3f76f85b7f5433a16f4c3c5fe5f05a52c85fe", size = 188480277, upload-time = "2026-05-07T19:05:03.231Z" }, + { url = "https://files.pythonhosted.org/packages/13/31/8315ea5f8dd18e60970b3022e3a8b93fd37e0b784fbbef86e10c8e6e5ca1/triton-3.7.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22bacffce443f54593dd20f05294d5a40622e0ea9ab632816f87154504356221", size = 201415942, upload-time = "2026-05-07T18:46:06.479Z" }, + { url = "https://files.pythonhosted.org/packages/f7/13/ec05adfcd87311d532ba61e3af143e8be59fcd26675884c4682841406a20/triton-3.7.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4bf49b00a7a377a68a6da603a876e797614e6455a80e9021669c476a953ad9a", size = 188505104, upload-time = "2026-05-07T19:05:09.843Z" }, + { url = "https://files.pythonhosted.org/packages/62/7b/468a576e35beef1426e0828e28e9ba9e65f5474d496f16ee126c15646324/triton-3.7.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f111161d49bf903c0eaedde3962353a3d841c08a836839b7cc1025b8426efcf", size = 201457567, upload-time = "2026-05-07T18:46:13.505Z" }, + { url = "https://files.pythonhosted.org/packages/01/e1/a59a583de59b8f62c495d67c80ee3ea97d09e91ac80c4c6e76456ed8d8ac/triton-3.7.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:abdf6beaa89b1bcfb9a43cd990536ce66091a997841a4814b260b7bee4c88c3c", size = 188503209, upload-time = "2026-05-07T19:05:17.935Z" }, + { url = "https://files.pythonhosted.org/packages/30/b1/b7507bb9815d403927c8dd51d4158ed2e11751a92dbc118a044f247b6848/triton-3.7.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a35d7afe3f3f058e7ec49fcce09794049e0ffc5c59019ac25ec3413741b8c4e7", size = 201453566, upload-time = "2026-05-07T18:46:20.427Z" }, + { url = "https://files.pythonhosted.org/packages/a6/8f/0bea7a6a0c989315c9135a1d7fb37e41905cfb3a17cbc1f10044ebd4cc3a/triton-3.7.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc1d61c172d257db80ddf42595131fb196ad2e9bdd751e90fe2ef13531734e8b", size = 188612899, upload-time = "2026-05-07T19:05:24.955Z" }, + { url = "https://files.pythonhosted.org/packages/e1/02/d96f57828d0912aec733b9bc7e0e7dbfd2c6f079a8fa433ac25cb93d1a30/triton-3.7.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:70fb9bbdc9f400afc54bbf6eb2670af28829a6ae3996863317964783141daf56", size = 201553816, upload-time = "2026-05-07T18:46:27.49Z" }, + { url = "https://files.pythonhosted.org/packages/40/fb/82a802dac4689f2a2fb2e69302e6a138eecc3e175bbe976ba3cfc717683a/triton-3.7.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a44a8476d0d3571eac4e4d1048e1ff75aad81a09ff4602ccfc56c6dea1672e", size = 188507879, upload-time = "2026-05-07T19:05:32.209Z" }, + { url = "https://files.pythonhosted.org/packages/8f/af/9904ec6d3c93d9b24e5ec360445bbdf758b7f00bfbeedb89cb0eb64eb8bb/triton-3.7.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b9b85e72968a9d8bba5ddb24e9b64aaabaf48affb042f2755cb7cfa92b7531ce", size = 201460637, upload-time = "2026-05-07T18:46:34.749Z" }, + { url = "https://files.pythonhosted.org/packages/a1/f9/4835a8ea746b88727d8899f4e3ccce4f9cacb38abfc3bb0a638266c53111/triton-3.7.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18a160de426fd99f92b0baf509045360afbd3bfaa0b4a5171dde800ec9f09684", size = 188608706, upload-time = "2026-05-07T19:05:39.218Z" }, + { url = "https://files.pythonhosted.org/packages/c1/68/fa86e5a39608000f645535b2c124920126327ab731f8c4fafd5b07ff8d4b/triton-3.7.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce061073102714b725f3660ec6939d94a1da7984b3aa99c921417cae273672f5", size = 201546766, upload-time = "2026-05-07T18:46:42.088Z" }, ] [[package]] From f6f47a298c297799b02cb0d4708a2dd0ff4b4e90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:43:27 +0000 Subject: [PATCH 15/33] Bump pyarrow from 21.0.0 to 23.0.1 in /python (#14058) Bumps [pyarrow](https://github.com/apache/arrow) from 21.0.0 to 23.0.1.
Release notes

Sourced from pyarrow's releases.

Apache Arrow 23.0.1

Release Notes URL: https://arrow.apache.org/release/23.0.1.html

Apache Arrow 23.0.1 RC0

Release Notes: Release Candidate: 23.0.1 RC0

Apache Arrow 23.0.0

Release Notes URL: https://arrow.apache.org/release/23.0.0.html

Apache Arrow 23.0.0 RC2

Release Notes: Release Candidate: 23.0.0 RC2

Apache Arrow 22.0.0

Release Notes URL: https://arrow.apache.org/release/22.0.0.html

Apache Arrow 22.0.0 RC1

Release Notes: Release Candidate: 22.0.0 RC1

Apache Arrow 22.0.0 RC0

Release Notes: Release Candidate: 22.0.0 RC0

Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- python/pyproject.toml | 2 +- python/uv.lock | 94 +++++++++++++++++++++++++------------------ 2 files changed, 55 insertions(+), 41 deletions(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index b274b90e8242..e0fccc8d4fec 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -150,7 +150,7 @@ sql = [ ] usearch = [ "usearch ~= 2.16", - "pyarrow >= 12.0,< 22.0" + "pyarrow>=12.0,<24.0" ] weaviate = [ "weaviate-client>=4.17.0,<5.0", diff --git a/python/uv.lock b/python/uv.lock index 001063e7362b..946e059380bc 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -4820,45 +4820,59 @@ wheels = [ [[package]] name = "pyarrow" -version = "21.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ef/c2/ea068b8f00905c06329a3dfcd40d0fcc2b7d0f2e355bdb25b65e0a0e4cd4/pyarrow-21.0.0.tar.gz", hash = "sha256:5051f2dccf0e283ff56335760cbc8622cf52264d67e359d5569541ac11b6d5bc", size = 1133487, upload-time = "2025-07-18T00:57:31.761Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/17/d9/110de31880016e2afc52d8580b397dbe47615defbf09ca8cf55f56c62165/pyarrow-21.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:e563271e2c5ff4d4a4cbeb2c83d5cf0d4938b891518e676025f7268c6fe5fe26", size = 31196837, upload-time = "2025-07-18T00:54:34.755Z" }, - { url = "https://files.pythonhosted.org/packages/df/5f/c1c1997613abf24fceb087e79432d24c19bc6f7259cab57c2c8e5e545fab/pyarrow-21.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:fee33b0ca46f4c85443d6c450357101e47d53e6c3f008d658c27a2d020d44c79", size = 32659470, upload-time = "2025-07-18T00:54:38.329Z" }, - { url = "https://files.pythonhosted.org/packages/3e/ed/b1589a777816ee33ba123ba1e4f8f02243a844fed0deec97bde9fb21a5cf/pyarrow-21.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:7be45519b830f7c24b21d630a31d48bcebfd5d4d7f9d3bdb49da9cdf6d764edb", size = 41055619, upload-time = "2025-07-18T00:54:42.172Z" }, - { url = "https://files.pythonhosted.org/packages/44/28/b6672962639e85dc0ac36f71ab3a8f5f38e01b51343d7aa372a6b56fa3f3/pyarrow-21.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:26bfd95f6bff443ceae63c65dc7e048670b7e98bc892210acba7e4995d3d4b51", size = 42733488, upload-time = "2025-07-18T00:54:47.132Z" }, - { url = "https://files.pythonhosted.org/packages/f8/cc/de02c3614874b9089c94eac093f90ca5dfa6d5afe45de3ba847fd950fdf1/pyarrow-21.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bd04ec08f7f8bd113c55868bd3fc442a9db67c27af098c5f814a3091e71cc61a", size = 43329159, upload-time = "2025-07-18T00:54:51.686Z" }, - { url = "https://files.pythonhosted.org/packages/a6/3e/99473332ac40278f196e105ce30b79ab8affab12f6194802f2593d6b0be2/pyarrow-21.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9b0b14b49ac10654332a805aedfc0147fb3469cbf8ea951b3d040dab12372594", size = 45050567, upload-time = "2025-07-18T00:54:56.679Z" }, - { url = "https://files.pythonhosted.org/packages/7b/f5/c372ef60593d713e8bfbb7e0c743501605f0ad00719146dc075faf11172b/pyarrow-21.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:9d9f8bcb4c3be7738add259738abdeddc363de1b80e3310e04067aa1ca596634", size = 26217959, upload-time = "2025-07-18T00:55:00.482Z" }, - { url = "https://files.pythonhosted.org/packages/94/dc/80564a3071a57c20b7c32575e4a0120e8a330ef487c319b122942d665960/pyarrow-21.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c077f48aab61738c237802836fc3844f85409a46015635198761b0d6a688f87b", size = 31243234, upload-time = "2025-07-18T00:55:03.812Z" }, - { url = "https://files.pythonhosted.org/packages/ea/cc/3b51cb2db26fe535d14f74cab4c79b191ed9a8cd4cbba45e2379b5ca2746/pyarrow-21.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:689f448066781856237eca8d1975b98cace19b8dd2ab6145bf49475478bcaa10", size = 32714370, upload-time = "2025-07-18T00:55:07.495Z" }, - { url = "https://files.pythonhosted.org/packages/24/11/a4431f36d5ad7d83b87146f515c063e4d07ef0b7240876ddb885e6b44f2e/pyarrow-21.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:479ee41399fcddc46159a551705b89c05f11e8b8cb8e968f7fec64f62d91985e", size = 41135424, upload-time = "2025-07-18T00:55:11.461Z" }, - { url = "https://files.pythonhosted.org/packages/74/dc/035d54638fc5d2971cbf1e987ccd45f1091c83bcf747281cf6cc25e72c88/pyarrow-21.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:40ebfcb54a4f11bcde86bc586cbd0272bac0d516cfa539c799c2453768477569", size = 42823810, upload-time = "2025-07-18T00:55:16.301Z" }, - { url = "https://files.pythonhosted.org/packages/2e/3b/89fced102448a9e3e0d4dded1f37fa3ce4700f02cdb8665457fcc8015f5b/pyarrow-21.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8d58d8497814274d3d20214fbb24abcad2f7e351474357d552a8d53bce70c70e", size = 43391538, upload-time = "2025-07-18T00:55:23.82Z" }, - { url = "https://files.pythonhosted.org/packages/fb/bb/ea7f1bd08978d39debd3b23611c293f64a642557e8141c80635d501e6d53/pyarrow-21.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:585e7224f21124dd57836b1530ac8f2df2afc43c861d7bf3d58a4870c42ae36c", size = 45120056, upload-time = "2025-07-18T00:55:28.231Z" }, - { url = "https://files.pythonhosted.org/packages/6e/0b/77ea0600009842b30ceebc3337639a7380cd946061b620ac1a2f3cb541e2/pyarrow-21.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:555ca6935b2cbca2c0e932bedd853e9bc523098c39636de9ad4693b5b1df86d6", size = 26220568, upload-time = "2025-07-18T00:55:32.122Z" }, - { url = "https://files.pythonhosted.org/packages/ca/d4/d4f817b21aacc30195cf6a46ba041dd1be827efa4a623cc8bf39a1c2a0c0/pyarrow-21.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:3a302f0e0963db37e0a24a70c56cf91a4faa0bca51c23812279ca2e23481fccd", size = 31160305, upload-time = "2025-07-18T00:55:35.373Z" }, - { url = "https://files.pythonhosted.org/packages/a2/9c/dcd38ce6e4b4d9a19e1d36914cb8e2b1da4e6003dd075474c4cfcdfe0601/pyarrow-21.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:b6b27cf01e243871390474a211a7922bfbe3bda21e39bc9160daf0da3fe48876", size = 32684264, upload-time = "2025-07-18T00:55:39.303Z" }, - { url = "https://files.pythonhosted.org/packages/4f/74/2a2d9f8d7a59b639523454bec12dba35ae3d0a07d8ab529dc0809f74b23c/pyarrow-21.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:e72a8ec6b868e258a2cd2672d91f2860ad532d590ce94cdf7d5e7ec674ccf03d", size = 41108099, upload-time = "2025-07-18T00:55:42.889Z" }, - { url = "https://files.pythonhosted.org/packages/ad/90/2660332eeb31303c13b653ea566a9918484b6e4d6b9d2d46879a33ab0622/pyarrow-21.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b7ae0bbdc8c6674259b25bef5d2a1d6af5d39d7200c819cf99e07f7dfef1c51e", size = 42829529, upload-time = "2025-07-18T00:55:47.069Z" }, - { url = "https://files.pythonhosted.org/packages/33/27/1a93a25c92717f6aa0fca06eb4700860577d016cd3ae51aad0e0488ac899/pyarrow-21.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:58c30a1729f82d201627c173d91bd431db88ea74dcaa3885855bc6203e433b82", size = 43367883, upload-time = "2025-07-18T00:55:53.069Z" }, - { url = "https://files.pythonhosted.org/packages/05/d9/4d09d919f35d599bc05c6950095e358c3e15148ead26292dfca1fb659b0c/pyarrow-21.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:072116f65604b822a7f22945a7a6e581cfa28e3454fdcc6939d4ff6090126623", size = 45133802, upload-time = "2025-07-18T00:55:57.714Z" }, - { url = "https://files.pythonhosted.org/packages/71/30/f3795b6e192c3ab881325ffe172e526499eb3780e306a15103a2764916a2/pyarrow-21.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf56ec8b0a5c8c9d7021d6fd754e688104f9ebebf1bf4449613c9531f5346a18", size = 26203175, upload-time = "2025-07-18T00:56:01.364Z" }, - { url = "https://files.pythonhosted.org/packages/16/ca/c7eaa8e62db8fb37ce942b1ea0c6d7abfe3786ca193957afa25e71b81b66/pyarrow-21.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e99310a4ebd4479bcd1964dff9e14af33746300cb014aa4a3781738ac63baf4a", size = 31154306, upload-time = "2025-07-18T00:56:04.42Z" }, - { url = "https://files.pythonhosted.org/packages/ce/e8/e87d9e3b2489302b3a1aea709aaca4b781c5252fcb812a17ab6275a9a484/pyarrow-21.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:d2fe8e7f3ce329a71b7ddd7498b3cfac0eeb200c2789bd840234f0dc271a8efe", size = 32680622, upload-time = "2025-07-18T00:56:07.505Z" }, - { url = "https://files.pythonhosted.org/packages/84/52/79095d73a742aa0aba370c7942b1b655f598069489ab387fe47261a849e1/pyarrow-21.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:f522e5709379d72fb3da7785aa489ff0bb87448a9dc5a75f45763a795a089ebd", size = 41104094, upload-time = "2025-07-18T00:56:10.994Z" }, - { url = "https://files.pythonhosted.org/packages/89/4b/7782438b551dbb0468892a276b8c789b8bbdb25ea5c5eb27faadd753e037/pyarrow-21.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:69cbbdf0631396e9925e048cfa5bce4e8c3d3b41562bbd70c685a8eb53a91e61", size = 42825576, upload-time = "2025-07-18T00:56:15.569Z" }, - { url = "https://files.pythonhosted.org/packages/b3/62/0f29de6e0a1e33518dec92c65be0351d32d7ca351e51ec5f4f837a9aab91/pyarrow-21.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:731c7022587006b755d0bdb27626a1a3bb004bb56b11fb30d98b6c1b4718579d", size = 43368342, upload-time = "2025-07-18T00:56:19.531Z" }, - { url = "https://files.pythonhosted.org/packages/90/c7/0fa1f3f29cf75f339768cc698c8ad4ddd2481c1742e9741459911c9ac477/pyarrow-21.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc56bc708f2d8ac71bd1dcb927e458c93cec10b98eb4120206a4091db7b67b99", size = 45131218, upload-time = "2025-07-18T00:56:23.347Z" }, - { url = "https://files.pythonhosted.org/packages/01/63/581f2076465e67b23bc5a37d4a2abff8362d389d29d8105832e82c9c811c/pyarrow-21.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:186aa00bca62139f75b7de8420f745f2af12941595bbbfa7ed3870ff63e25636", size = 26087551, upload-time = "2025-07-18T00:56:26.758Z" }, - { url = "https://files.pythonhosted.org/packages/c9/ab/357d0d9648bb8241ee7348e564f2479d206ebe6e1c47ac5027c2e31ecd39/pyarrow-21.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:a7a102574faa3f421141a64c10216e078df467ab9576684d5cd696952546e2da", size = 31290064, upload-time = "2025-07-18T00:56:30.214Z" }, - { url = "https://files.pythonhosted.org/packages/3f/8a/5685d62a990e4cac2043fc76b4661bf38d06efed55cf45a334b455bd2759/pyarrow-21.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:1e005378c4a2c6db3ada3ad4c217b381f6c886f0a80d6a316fe586b90f77efd7", size = 32727837, upload-time = "2025-07-18T00:56:33.935Z" }, - { url = "https://files.pythonhosted.org/packages/fc/de/c0828ee09525c2bafefd3e736a248ebe764d07d0fd762d4f0929dbc516c9/pyarrow-21.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:65f8e85f79031449ec8706b74504a316805217b35b6099155dd7e227eef0d4b6", size = 41014158, upload-time = "2025-07-18T00:56:37.528Z" }, - { url = "https://files.pythonhosted.org/packages/6e/26/a2865c420c50b7a3748320b614f3484bfcde8347b2639b2b903b21ce6a72/pyarrow-21.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:3a81486adc665c7eb1a2bde0224cfca6ceaba344a82a971ef059678417880eb8", size = 42667885, upload-time = "2025-07-18T00:56:41.483Z" }, - { url = "https://files.pythonhosted.org/packages/0a/f9/4ee798dc902533159250fb4321267730bc0a107d8c6889e07c3add4fe3a5/pyarrow-21.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fc0d2f88b81dcf3ccf9a6ae17f89183762c8a94a5bdcfa09e05cfe413acf0503", size = 43276625, upload-time = "2025-07-18T00:56:48.002Z" }, - { url = "https://files.pythonhosted.org/packages/5a/da/e02544d6997037a4b0d22d8e5f66bc9315c3671371a8b18c79ade1cefe14/pyarrow-21.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6299449adf89df38537837487a4f8d3bd91ec94354fdd2a7d30bc11c48ef6e79", size = 44951890, upload-time = "2025-07-18T00:56:52.568Z" }, - { url = "https://files.pythonhosted.org/packages/e5/4e/519c1bc1876625fe6b71e9a28287c43ec2f20f73c658b9ae1d485c0c206e/pyarrow-21.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:222c39e2c70113543982c6b34f3077962b44fca38c0bd9e68bb6781534425c10", size = 26371006, upload-time = "2025-07-18T00:56:56.379Z" }, +version = "23.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/88/22/134986a4cc224d593c1afde5494d18ff629393d74cc2eddb176669f234a4/pyarrow-23.0.1.tar.gz", hash = "sha256:b8c5873e33440b2bc2f4a79d2b47017a89c5a24116c055625e6f2ee50523f019", size = 1167336, upload-time = "2026-02-16T10:14:12.39Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/a8/24e5dc6855f50a62936ceb004e6e9645e4219a8065f304145d7fb8a79d5d/pyarrow-23.0.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:3fab8f82571844eb3c460f90a75583801d14ca0cc32b1acc8c361650e006fd56", size = 34307390, upload-time = "2026-02-16T10:08:08.654Z" }, + { url = "https://files.pythonhosted.org/packages/bc/8e/4be5617b4aaae0287f621ad31c6036e5f63118cfca0dc57d42121ff49b51/pyarrow-23.0.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:3f91c038b95f71ddfc865f11d5876c42f343b4495535bd262c7b321b0b94507c", size = 35853761, upload-time = "2026-02-16T10:08:17.811Z" }, + { url = "https://files.pythonhosted.org/packages/2e/08/3e56a18819462210432ae37d10f5c8eed3828be1d6c751b6e6a2e93c286a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:d0744403adabef53c985a7f8a082b502a368510c40d184df349a0a8754533258", size = 44493116, upload-time = "2026-02-16T10:08:25.792Z" }, + { url = "https://files.pythonhosted.org/packages/f8/82/c40b68001dbec8a3faa4c08cd8c200798ac732d2854537c5449dc859f55a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c33b5bf406284fd0bba436ed6f6c3ebe8e311722b441d89397c54f871c6863a2", size = 47564532, upload-time = "2026-02-16T10:08:34.27Z" }, + { url = "https://files.pythonhosted.org/packages/20/bc/73f611989116b6f53347581b02177f9f620efdf3cd3f405d0e83cdf53a83/pyarrow-23.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ddf743e82f69dcd6dbbcb63628895d7161e04e56794ef80550ac6f3315eeb1d5", size = 48183685, upload-time = "2026-02-16T10:08:42.889Z" }, + { url = "https://files.pythonhosted.org/packages/b0/cc/6c6b3ecdae2a8c3aced99956187e8302fc954cc2cca2a37cf2111dad16ce/pyarrow-23.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e052a211c5ac9848ae15d5ec875ed0943c0221e2fcfe69eee80b604b4e703222", size = 50605582, upload-time = "2026-02-16T10:08:51.641Z" }, + { url = "https://files.pythonhosted.org/packages/8d/94/d359e708672878d7638a04a0448edf7c707f9e5606cee11e15aaa5c7535a/pyarrow-23.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:5abde149bb3ce524782d838eb67ac095cd3fd6090eba051130589793f1a7f76d", size = 27521148, upload-time = "2026-02-16T10:08:58.077Z" }, + { url = "https://files.pythonhosted.org/packages/b0/41/8e6b6ef7e225d4ceead8459427a52afdc23379768f54dd3566014d7618c1/pyarrow-23.0.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6f0147ee9e0386f519c952cc670eb4a8b05caa594eeffe01af0e25f699e4e9bb", size = 34302230, upload-time = "2026-02-16T10:09:03.859Z" }, + { url = "https://files.pythonhosted.org/packages/bf/4a/1472c00392f521fea03ae93408bf445cc7bfa1ab81683faf9bc188e36629/pyarrow-23.0.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:0ae6e17c828455b6265d590100c295193f93cc5675eb0af59e49dbd00d2de350", size = 35850050, upload-time = "2026-02-16T10:09:11.877Z" }, + { url = "https://files.pythonhosted.org/packages/0c/b2/bd1f2f05ded56af7f54d702c8364c9c43cd6abb91b0e9933f3d77b4f4132/pyarrow-23.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:fed7020203e9ef273360b9e45be52a2a47d3103caf156a30ace5247ffb51bdbd", size = 44491918, upload-time = "2026-02-16T10:09:18.144Z" }, + { url = "https://files.pythonhosted.org/packages/0b/62/96459ef5b67957eac38a90f541d1c28833d1b367f014a482cb63f3b7cd2d/pyarrow-23.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:26d50dee49d741ac0e82185033488d28d35be4d763ae6f321f97d1140eb7a0e9", size = 47562811, upload-time = "2026-02-16T10:09:25.792Z" }, + { url = "https://files.pythonhosted.org/packages/7d/94/1170e235add1f5f45a954e26cd0e906e7e74e23392dcb560de471f7366ec/pyarrow-23.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c30143b17161310f151f4a2bcfe41b5ff744238c1039338779424e38579d701", size = 48183766, upload-time = "2026-02-16T10:09:34.645Z" }, + { url = "https://files.pythonhosted.org/packages/0e/2d/39a42af4570377b99774cdb47f63ee6c7da7616bd55b3d5001aa18edfe4f/pyarrow-23.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db2190fa79c80a23fdd29fef4b8992893f024ae7c17d2f5f4db7171fa30c2c78", size = 50607669, upload-time = "2026-02-16T10:09:44.153Z" }, + { url = "https://files.pythonhosted.org/packages/00/ca/db94101c187f3df742133ac837e93b1f269ebdac49427f8310ee40b6a58f/pyarrow-23.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:f00f993a8179e0e1c9713bcc0baf6d6c01326a406a9c23495ec1ba9c9ebf2919", size = 27527698, upload-time = "2026-02-16T10:09:50.263Z" }, + { url = "https://files.pythonhosted.org/packages/9a/4b/4166bb5abbfe6f750fc60ad337c43ecf61340fa52ab386da6e8dbf9e63c4/pyarrow-23.0.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f4b0dbfa124c0bb161f8b5ebb40f1a680b70279aa0c9901d44a2b5a20806039f", size = 34214575, upload-time = "2026-02-16T10:09:56.225Z" }, + { url = "https://files.pythonhosted.org/packages/e1/da/3f941e3734ac8088ea588b53e860baeddac8323ea40ce22e3d0baa865cc9/pyarrow-23.0.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:7707d2b6673f7de054e2e83d59f9e805939038eebe1763fe811ee8fa5c0cd1a7", size = 35832540, upload-time = "2026-02-16T10:10:03.428Z" }, + { url = "https://files.pythonhosted.org/packages/88/7c/3d841c366620e906d54430817531b877ba646310296df42ef697308c2705/pyarrow-23.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:86ff03fb9f1a320266e0de855dee4b17da6794c595d207f89bba40d16b5c78b9", size = 44470940, upload-time = "2026-02-16T10:10:10.704Z" }, + { url = "https://files.pythonhosted.org/packages/2c/a5/da83046273d990f256cb79796a190bbf7ec999269705ddc609403f8c6b06/pyarrow-23.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:813d99f31275919c383aab17f0f455a04f5a429c261cc411b1e9a8f5e4aaaa05", size = 47586063, upload-time = "2026-02-16T10:10:17.95Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3c/b7d2ebcff47a514f47f9da1e74b7949138c58cfeb108cdd4ee62f43f0cf3/pyarrow-23.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bf5842f960cddd2ef757d486041d57c96483efc295a8c4a0e20e704cbbf39c67", size = 48173045, upload-time = "2026-02-16T10:10:25.363Z" }, + { url = "https://files.pythonhosted.org/packages/43/b2/b40961262213beaba6acfc88698eb773dfce32ecdf34d19291db94c2bd73/pyarrow-23.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564baf97c858ecc03ec01a41062e8f4698abc3e6e2acd79c01c2e97880a19730", size = 50621741, upload-time = "2026-02-16T10:10:33.477Z" }, + { url = "https://files.pythonhosted.org/packages/f6/70/1fdda42d65b28b078e93d75d371b2185a61da89dda4def8ba6ba41ebdeb4/pyarrow-23.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:07deae7783782ac7250989a7b2ecde9b3c343a643f82e8a4df03d93b633006f0", size = 27620678, upload-time = "2026-02-16T10:10:39.31Z" }, + { url = "https://files.pythonhosted.org/packages/47/10/2cbe4c6f0fb83d2de37249567373d64327a5e4d8db72f486db42875b08f6/pyarrow-23.0.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6b8fda694640b00e8af3c824f99f789e836720aa8c9379fb435d4c4953a756b8", size = 34210066, upload-time = "2026-02-16T10:10:45.487Z" }, + { url = "https://files.pythonhosted.org/packages/cb/4f/679fa7e84dadbaca7a65f7cdba8d6c83febbd93ca12fa4adf40ba3b6362b/pyarrow-23.0.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:8ff51b1addc469b9444b7c6f3548e19dc931b172ab234e995a60aea9f6e6025f", size = 35825526, upload-time = "2026-02-16T10:10:52.266Z" }, + { url = "https://files.pythonhosted.org/packages/f9/63/d2747d930882c9d661e9398eefc54f15696547b8983aaaf11d4a2e8b5426/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:71c5be5cbf1e1cb6169d2a0980850bccb558ddc9b747b6206435313c47c37677", size = 44473279, upload-time = "2026-02-16T10:11:01.557Z" }, + { url = "https://files.pythonhosted.org/packages/b3/93/10a48b5e238de6d562a411af6467e71e7aedbc9b87f8d3a35f1560ae30fb/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:9b6f4f17b43bc39d56fec96e53fe89d94bac3eb134137964371b45352d40d0c2", size = 47585798, upload-time = "2026-02-16T10:11:09.401Z" }, + { url = "https://files.pythonhosted.org/packages/5c/20/476943001c54ef078dbf9542280e22741219a184a0632862bca4feccd666/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fc13fc6c403d1337acab46a2c4346ca6c9dec5780c3c697cf8abfd5e19b6b37", size = 48179446, upload-time = "2026-02-16T10:11:17.781Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b6/5dd0c47b335fcd8edba9bfab78ad961bd0fd55ebe53468cc393f45e0be60/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c16ed4f53247fa3ffb12a14d236de4213a4415d127fe9cebed33d51671113e2", size = 50623972, upload-time = "2026-02-16T10:11:26.185Z" }, + { url = "https://files.pythonhosted.org/packages/d5/09/a532297c9591a727d67760e2e756b83905dd89adb365a7f6e9c72578bcc1/pyarrow-23.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:cecfb12ef629cf6be0b1887f9f86463b0dd3dc3195ae6224e74006be4736035a", size = 27540749, upload-time = "2026-02-16T10:12:23.297Z" }, + { url = "https://files.pythonhosted.org/packages/a5/8e/38749c4b1303e6ae76b3c80618f84861ae0c55dd3c2273842ea6f8258233/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:29f7f7419a0e30264ea261fdc0e5fe63ce5a6095003db2945d7cd78df391a7e1", size = 34471544, upload-time = "2026-02-16T10:11:32.535Z" }, + { url = "https://files.pythonhosted.org/packages/a3/73/f237b2bc8c669212f842bcfd842b04fc8d936bfc9d471630569132dc920d/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:33d648dc25b51fd8055c19e4261e813dfc4d2427f068bcecc8b53d01b81b0500", size = 35949911, upload-time = "2026-02-16T10:11:39.813Z" }, + { url = "https://files.pythonhosted.org/packages/0c/86/b912195eee0903b5611bf596833def7d146ab2d301afeb4b722c57ffc966/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:cd395abf8f91c673dd3589cadc8cc1ee4e8674fa61b2e923c8dd215d9c7d1f41", size = 44520337, upload-time = "2026-02-16T10:11:47.764Z" }, + { url = "https://files.pythonhosted.org/packages/69/c2/f2a717fb824f62d0be952ea724b4f6f9372a17eed6f704b5c9526f12f2f1/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:00be9576d970c31defb5c32eb72ef585bf600ef6d0a82d5eccaae96639cf9d07", size = 47548944, upload-time = "2026-02-16T10:11:56.607Z" }, + { url = "https://files.pythonhosted.org/packages/84/a7/90007d476b9f0dc308e3bc57b832d004f848fd6c0da601375d20d92d1519/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c2139549494445609f35a5cda4eb94e2c9e4d704ce60a095b342f82460c73a83", size = 48236269, upload-time = "2026-02-16T10:12:04.47Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3f/b16fab3e77709856eb6ac328ce35f57a6d4a18462c7ca5186ef31b45e0e0/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7044b442f184d84e2351e5084600f0d7343d6117aabcbc1ac78eb1ae11eb4125", size = 50604794, upload-time = "2026-02-16T10:12:11.797Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a1/22df0620a9fac31d68397a75465c344e83c3dfe521f7612aea33e27ab6c0/pyarrow-23.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a35581e856a2fafa12f3f54fce4331862b1cfb0bef5758347a858a4aa9d6bae8", size = 27660642, upload-time = "2026-02-16T10:12:17.746Z" }, + { url = "https://files.pythonhosted.org/packages/8d/1b/6da9a89583ce7b23ac611f183ae4843cd3a6cf54f079549b0e8c14031e73/pyarrow-23.0.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:5df1161da23636a70838099d4aaa65142777185cc0cdba4037a18cee7d8db9ca", size = 34238755, upload-time = "2026-02-16T10:12:32.819Z" }, + { url = "https://files.pythonhosted.org/packages/ae/b5/d58a241fbe324dbaeb8df07be6af8752c846192d78d2272e551098f74e88/pyarrow-23.0.1-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:fa8e51cb04b9f8c9c5ace6bab63af9a1f88d35c0d6cbf53e8c17c098552285e1", size = 35847826, upload-time = "2026-02-16T10:12:38.949Z" }, + { url = "https://files.pythonhosted.org/packages/54/a5/8cbc83f04aba433ca7b331b38f39e000efd9f0c7ce47128670e737542996/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:0b95a3994f015be13c63148fef8832e8a23938128c185ee951c98908a696e0eb", size = 44536859, upload-time = "2026-02-16T10:12:45.467Z" }, + { url = "https://files.pythonhosted.org/packages/36/2e/c0f017c405fcdc252dbccafbe05e36b0d0eb1ea9a958f081e01c6972927f/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:4982d71350b1a6e5cfe1af742c53dfb759b11ce14141870d05d9e540d13bc5d1", size = 47614443, upload-time = "2026-02-16T10:12:55.525Z" }, + { url = "https://files.pythonhosted.org/packages/af/6b/2314a78057912f5627afa13ba43809d9d653e6630859618b0fd81a4e0759/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c250248f1fe266db627921c89b47b7c06fee0489ad95b04d50353537d74d6886", size = 48232991, upload-time = "2026-02-16T10:13:04.729Z" }, + { url = "https://files.pythonhosted.org/packages/40/f2/1bcb1d3be3460832ef3370d621142216e15a2c7c62602a4ea19ec240dd64/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5f4763b83c11c16e5f4c15601ba6dfa849e20723b46aa2617cb4bffe8768479f", size = 50645077, upload-time = "2026-02-16T10:13:14.147Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3f/b1da7b61cd66566a4d4c8383d376c606d1c34a906c3f1cb35c479f59d1aa/pyarrow-23.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:3a4c85ef66c134161987c17b147d6bffdca4566f9a4c1d81a0a01cdf08414ea5", size = 28234271, upload-time = "2026-02-16T10:14:09.397Z" }, + { url = "https://files.pythonhosted.org/packages/b5/78/07f67434e910a0f7323269be7bfbf58699bd0c1d080b18a1ab49ba943fe8/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:17cd28e906c18af486a499422740298c52d7c6795344ea5002a7720b4eadf16d", size = 34488692, upload-time = "2026-02-16T10:13:21.541Z" }, + { url = "https://files.pythonhosted.org/packages/50/76/34cf7ae93ece1f740a04910d9f7e80ba166b9b4ab9596a953e9e62b90fe1/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:76e823d0e86b4fb5e1cf4a58d293036e678b5a4b03539be933d3b31f9406859f", size = 35964383, upload-time = "2026-02-16T10:13:28.63Z" }, + { url = "https://files.pythonhosted.org/packages/46/90/459b827238936d4244214be7c684e1b366a63f8c78c380807ae25ed92199/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:a62e1899e3078bf65943078b3ad2a6ddcacf2373bc06379aac61b1e548a75814", size = 44538119, upload-time = "2026-02-16T10:13:35.506Z" }, + { url = "https://files.pythonhosted.org/packages/28/a1/93a71ae5881e99d1f9de1d4554a87be37da11cd6b152239fb5bd924fdc64/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:df088e8f640c9fae3b1f495b3c64755c4e719091caf250f3a74d095ddf3c836d", size = 47571199, upload-time = "2026-02-16T10:13:42.504Z" }, + { url = "https://files.pythonhosted.org/packages/88/a3/d2c462d4ef313521eaf2eff04d204ac60775263f1fb08c374b543f79f610/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:46718a220d64677c93bc243af1d44b55998255427588e400677d7192671845c7", size = 48259435, upload-time = "2026-02-16T10:13:49.226Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f1/11a544b8c3d38a759eb3fbb022039117fd633e9a7b19e4841cc3da091915/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a09f3876e87f48bc2f13583ab551f0379e5dfb83210391e68ace404181a20690", size = 50629149, upload-time = "2026-02-16T10:13:57.238Z" }, + { url = "https://files.pythonhosted.org/packages/50/f2/c0e76a0b451ffdf0cf788932e182758eb7558953f4f27f1aff8e2518b653/pyarrow-23.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:527e8d899f14bd15b740cd5a54ad56b7f98044955373a17179d5956ddb93d9ce", size = 28365807, upload-time = "2026-02-16T10:14:03.892Z" }, ] [[package]] @@ -6623,7 +6637,7 @@ requires-dist = [ { name = "pinecone", extras = ["asyncio", "grpc"], marker = "extra == 'pinecone'", specifier = "~=7.0" }, { name = "prance", specifier = ">=23.6.21,<25.4.9" }, { name = "psycopg", extras = ["binary", "pool"], marker = "extra == 'postgres'", specifier = "~=3.2" }, - { name = "pyarrow", marker = "extra == 'usearch'", specifier = ">=12.0,<22.0" }, + { name = "pyarrow", marker = "extra == 'usearch'", specifier = ">=12.0,<24.0" }, { name = "pybars4", specifier = "~=0.9" }, { name = "pydantic", specifier = ">=2.0,!=2.10.0,!=2.10.1,!=2.10.2,!=2.10.3,<2.14" }, { name = "pydantic-settings", specifier = "~=2.0" }, From 326ecbecd9b17a2e8bea9c6daee97bd3ad3d6057 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:45:30 +0200 Subject: [PATCH 16/33] Python: Bump idna from 3.11 to 3.15 in /python (#14024) Bumps [idna](https://github.com/kjd/idna) from 3.11 to 3.15.
Changelog

Sourced from idna's changelog.

3.15 (2026-05-12)

  • Enforce DNS-length cap on individual labels early in check_label, short-circuiting contextual-rule processing for oversized input while staying compatible with UTS 46 usage.
  • Tidy core helpers: hoist bidi category sets to module-level frozensets (avoiding per-codepoint list construction), simplify length checks, and reuse the shared _unicode_dots_re from idna.core in the codec module.
  • Use raise ... from err for proper exception chaining and switch internal string formatting to f-strings.
  • Allow flit_core 4.x in the build backend.
  • Expand the ruff lint set (flake8-bugbear, flake8-simplify, pyupgrade, perflint) and apply the surfaced fixes; pin lint CI to Python 3.14.
  • Add Dependabot configuration for GitHub Actions.
  • Convert README and HISTORY from reStructuredText to Markdown.
  • Reference CVE-2026-45409 for the 3.14 advisory in place of the initial GHSA identifier.

Thanks to Felix Yan, Stan Ulbrych, and metsw24-max for contributions to this release.

3.14 (2026-05-10)

  • Removed opportunity to process long inputs into quadratic time by rejecting oversize inputs up-front. Closes a bypass of the CVE-2024-3651 mitigation. [CVE-2026-45409]

Thanks to Stan Ulbrych for reporting the issue.

3.13 (2026-04-22)

  • Correct classification error for codepoint U+A7F1

3.12 (2026-04-21)

  • Update to Unicode 17.0.0.
  • Issue a deprecation warning for the transitional argument.
  • Added lazy-loading to provide some performance improvements.
  • Removed vestiges of code related to Python 2 support, including segmentation of data structures specific to Jython.

Thanks to Rodrigo Nogueira for contributions to this release.

Commits
  • af30a09 Release 3.15
  • 30314d4 Pre-release 3.15rc0
  • 05d4b21 Merge pull request #237 from kjd/convert-docs-to-markdown
  • 2987fdb Convert README and HISTORY from reStructuredText to Markdown
  • 59fa800 Merge pull request #236 from kjd/dependabot/github_actions/actions-f3e34333ea
  • def6983 Merge branch 'master' into dependabot/github_actions/actions-f3e34333ea
  • bbd8004 Merge pull request #234 from StanFromIreland/patch-1
  • edd07c0 Bump github/codeql-action from 3.35.2 to 4.35.2 in the actions group
  • 5557db0 Merge branch 'master' into patch-1
  • f11746c Merge pull request #235 from StanFromIreland/patch-2
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=idna&package-manager=uv&previous-version=3.11&new-version=3.15)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/semantic-kernel/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- python/uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/uv.lock b/python/uv.lock index 946e059380bc..24e6f5cb3332 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -2287,11 +2287,11 @@ wheels = [ [[package]] name = "idna" -version = "3.11" +version = "3.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/77/7b3966d0b9d1d31a36ddf1746926a11dface89a83409bf1483f0237aa758/idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc", size = 199245, upload-time = "2026-05-12T22:45:57.011Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, + { url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" }, ] [[package]] From 22ee3e00323fad1d27dccb6b1b1e67163e6c4416 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:47:04 +0200 Subject: [PATCH 17/33] Python: Bump authlib from 1.6.11 to 1.6.12 in /python (#14004) Bumps [authlib](https://github.com/authlib/authlib) from 1.6.11 to 1.6.12.
Release notes

Sourced from authlib's releases.

v1.6.12

Changelog

Sourced from authlib's changelog.

Version 1.6.12

Released on may 4, 2026

  • Fix redirecting to unvalidated redirect_uri on InvalidScopeError in OpenIDImplicitGrant and OpenIDHybridGrant.
Commits
  • e46e515 chore: bump to 1.6.12
  • 9babc13 fix: redirecting to unvalidated redirect_uri on InvalidScopeError in OIDC grants
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=authlib&package-manager=uv&previous-version=1.6.11&new-version=1.6.12)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/semantic-kernel/network/alerts).
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- python/uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/uv.lock b/python/uv.lock index 24e6f5cb3332..3dea4cf56575 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -319,14 +319,14 @@ wheels = [ [[package]] name = "authlib" -version = "1.6.11" +version = "1.6.12" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/28/10/b325d58ffe86815b399334a101e63bc6fa4e1953921cb23703b48a0a0220/authlib-1.6.11.tar.gz", hash = "sha256:64db35b9b01aeccb4715a6c9a6613a06f2bd7be2ab9d2eb89edd1dfc7580a38f", size = 165359, upload-time = "2026-04-16T07:22:50.279Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/30/6691fdc63b35f54a5a65e04fa1e59d827f4d4e8f4a39678ba7d3088ce0c8/authlib-1.6.12.tar.gz", hash = "sha256:0656d8482f28fc8221929d5f35b2bde5d13e10555ebc06b4561b0d622e83b1bd", size = 165368, upload-time = "2026-05-04T08:11:31.826Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/57/2f/55fca558f925a51db046e5b929deb317ddb05afed74b22d89f4eca578980/authlib-1.6.11-py2.py3-none-any.whl", hash = "sha256:c8687a9a26451c51a34a06fa17bb97cb15bba46a6a626755e2d7f50da8bff3e3", size = 244469, upload-time = "2026-04-16T07:22:48.413Z" }, + { url = "https://files.pythonhosted.org/packages/cd/51/9b0b5cd4cf683a02db937a6f9bbebcdc9c56558a7bb3763ce7d3512103c3/authlib-1.6.12-py2.py3-none-any.whl", hash = "sha256:e9229ad7fde610b139dd12f5edbe97eab9ee78bfb85691247e767727850b99ab", size = 244473, upload-time = "2026-05-04T08:11:30.354Z" }, ] [[package]] From 16085866f8f1d4688a9234a0099888642259dca8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:47:30 +0000 Subject: [PATCH 18/33] Bump urllib3 from 2.6.3 to 2.7.0 in /python (#13978) ### Motivation and Context Bumps urllib3 from 2.6.3 to 2.7.0 across the Python project, including the `mcp_with_oauth` demo, to pick up the latest security and bug fixes. ### Description - Bumps `urllib3` from 2.6.3 to 2.7.0 in `python/uv.lock` - Bumps `urllib3` from 2.5.0 to 2.7.0 in `python/samples/demos/mcp_with_oauth/uv.lock` so the demo no longer resolves an older urllib3 version ### Contribution Checklist - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone :smile: > **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com> --- python/samples/demos/mcp_with_oauth/uv.lock | 46 ++------------------- python/uv.lock | 6 +-- 2 files changed, 7 insertions(+), 45 deletions(-) diff --git a/python/samples/demos/mcp_with_oauth/uv.lock b/python/samples/demos/mcp_with_oauth/uv.lock index 93fed4032e44..275a70f1845c 100644 --- a/python/samples/demos/mcp_with_oauth/uv.lock +++ b/python/samples/demos/mcp_with_oauth/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.12'", @@ -194,44 +194,6 @@ name = "av" version = "14.4.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/86/f6/0b473dab52dfdea05f28f3578b1c56b6c796ce85e76951bab7c4e38d5a74/av-14.4.0.tar.gz", hash = "sha256:3ecbf803a7fdf67229c0edada0830d6bfaea4d10bfb24f0c3f4e607cd1064b42", size = 3892203, upload-time = "2025-05-16T19:13:35.737Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/34/0f/cf6b888747cd1e10eafc4a28942e5b666417c03c39853818900bdaa86116/av-14.4.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:10219620699a65b9829cfa08784da2ed38371f1a223ab8f3523f440a24c8381c", size = 19979523, upload-time = "2025-05-16T19:08:59.751Z" }, - { url = "https://files.pythonhosted.org/packages/45/30/8f09ac71ad23344ff247f16a9229b36b1e2a36214fd56ba55df885e9bf85/av-14.4.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:8bac981fde1c05e231df9f73a06ed9febce1f03fb0f1320707ac2861bba2567f", size = 23765838, upload-time = "2025-05-16T19:09:02.362Z" }, - { url = "https://files.pythonhosted.org/packages/a2/57/e0c30ceb1e59e7b2b88c9cd6bf79a0a979128de19a94b300a700d3a7ca52/av-14.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc634ed5bdeb362f0523b73693b079b540418d35d7f3003654f788ae6c317eef", size = 33122039, upload-time = "2025-05-16T19:09:04.729Z" }, - { url = "https://files.pythonhosted.org/packages/c6/a7/9b3064c49f2d2219ee1b895cc77fca18c84d6121b51c8ce6b7f618a2661b/av-14.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23973ed5c5bec9565094d2b3643f10a6996707ddffa5252e112d578ad34aa9ae", size = 31758563, upload-time = "2025-05-16T19:09:07.679Z" }, - { url = "https://files.pythonhosted.org/packages/23/42/0eafe0de75de6a0db71add8e4ea51ebf090482bad3068f4a874c90fbd110/av-14.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0655f7207db6a211d7cedb8ac6a2f7ccc9c4b62290130e393a3fd99425247311", size = 34750358, upload-time = "2025-05-16T19:09:10.932Z" }, - { url = "https://files.pythonhosted.org/packages/75/33/5430ba9ad73036f2d69395d36f3d57b261c51db6f6542bcfc60087640bb7/av-14.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1edaab73319bfefe53ee09c4b1cf7b141ea7e6678a0a1c62f7bac1e2c68ec4e7", size = 35793636, upload-time = "2025-05-16T19:09:13.726Z" }, - { url = "https://files.pythonhosted.org/packages/00/a9/d8c07f0ab69be05a4939719d7a31dc3e9fb112ee8ec6c9411a6c9c085f0a/av-14.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b54838fa17c031ffd780df07b9962fac1be05220f3c28468f7fe49474f1bf8d2", size = 34123666, upload-time = "2025-05-16T19:09:16.968Z" }, - { url = "https://files.pythonhosted.org/packages/48/e1/2f2f607553f2ac6369e5fc814e77b41f9ceb285ce9d8c02c9ee034b8b6db/av-14.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f4b59ac6c563b9b6197299944145958a8ec34710799fd851f1a889b0cbcd1059", size = 36756157, upload-time = "2025-05-16T19:09:21.447Z" }, - { url = "https://files.pythonhosted.org/packages/d7/f0/d653d4eaa7e68732f8c0013aee40f31ff0cd49e90fdec89cca6c193db207/av-14.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:a0192a584fae9f6cedfac03c06d5bf246517cdf00c8779bc33414404796a526e", size = 27931039, upload-time = "2025-05-16T19:09:24.739Z" }, - { url = "https://files.pythonhosted.org/packages/18/8a/d57418b686ffd05fabd5a0a9cfa97e63b38c35d7101af00e87c51c8cc43c/av-14.4.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5b21d5586a88b9fce0ab78e26bd1c38f8642f8e2aad5b35e619f4d202217c701", size = 19965048, upload-time = "2025-05-16T19:09:27.419Z" }, - { url = "https://files.pythonhosted.org/packages/f5/aa/3f878b0301efe587e9b07bb773dd6b47ef44ca09a3cffb4af50c08a170f3/av-14.4.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:cf8762d90b0f94a20c9f6e25a94f1757db5a256707964dfd0b1d4403e7a16835", size = 23750064, upload-time = "2025-05-16T19:09:30.012Z" }, - { url = "https://files.pythonhosted.org/packages/9a/b4/6fe94a31f9ed3a927daa72df67c7151968587106f30f9f8fcd792b186633/av-14.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0ac9f08920c7bbe0795319689d901e27cb3d7870b9a0acae3f26fc9daa801a6", size = 33648775, upload-time = "2025-05-16T19:09:33.811Z" }, - { url = "https://files.pythonhosted.org/packages/6c/f3/7f3130753521d779450c935aec3f4beefc8d4645471159f27b54e896470c/av-14.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a56d9ad2afdb638ec0404e962dc570960aae7e08ae331ad7ff70fbe99a6cf40e", size = 32216915, upload-time = "2025-05-16T19:09:36.99Z" }, - { url = "https://files.pythonhosted.org/packages/f8/9a/8ffabfcafb42154b4b3a67d63f9b69e68fa8c34cb39ddd5cb813dd049ed4/av-14.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bed513cbcb3437d0ae47743edc1f5b4a113c0b66cdd4e1aafc533abf5b2fbf2", size = 35287279, upload-time = "2025-05-16T19:09:39.711Z" }, - { url = "https://files.pythonhosted.org/packages/ad/11/7023ba0a2ca94a57aedf3114ab8cfcecb0819b50c30982a4c5be4d31df41/av-14.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d030c2d3647931e53d51f2f6e0fcf465263e7acf9ec6e4faa8dbfc77975318c3", size = 36294683, upload-time = "2025-05-16T19:09:42.668Z" }, - { url = "https://files.pythonhosted.org/packages/3d/fa/b8ac9636bd5034e2b899354468bef9f4dadb067420a16d8a493a514b7817/av-14.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1cc21582a4f606271d8c2036ec7a6247df0831050306c55cf8a905701d0f0474", size = 34552391, upload-time = "2025-05-16T19:09:46.852Z" }, - { url = "https://files.pythonhosted.org/packages/fb/29/0db48079c207d1cba7a2783896db5aec3816e17de55942262c244dffbc0f/av-14.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ce7c9cd452153d36f1b1478f904ed5f9ab191d76db873bdd3a597193290805d4", size = 37265250, upload-time = "2025-05-16T19:09:50.013Z" }, - { url = "https://files.pythonhosted.org/packages/1c/55/715858c3feb7efa4d667ce83a829c8e6ee3862e297fb2b568da3f968639d/av-14.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd261e31cc6b43ca722f80656c39934199d8f2eb391e0147e704b6226acebc29", size = 27925845, upload-time = "2025-05-16T19:09:52.663Z" }, - { url = "https://files.pythonhosted.org/packages/a6/75/b8641653780336c90ba89e5352cac0afa6256a86a150c7703c0b38851c6d/av-14.4.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:a53e682b239dd23b4e3bc9568cfb1168fc629ab01925fdb2e7556eb426339e94", size = 19954125, upload-time = "2025-05-16T19:09:54.909Z" }, - { url = "https://files.pythonhosted.org/packages/99/e6/37fe6fa5853a48d54d749526365780a63a4bc530be6abf2115e3a21e292a/av-14.4.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:5aa0b901751a32703fa938d2155d56ce3faf3630e4a48d238b35d2f7e49e5395", size = 23751479, upload-time = "2025-05-16T19:09:57.113Z" }, - { url = "https://files.pythonhosted.org/packages/f7/75/9a5f0e6bda5f513b62bafd1cff2b495441a8b07ab7fb7b8e62f0c0d1683f/av-14.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b316fed3597675fe2aacfed34e25fc9d5bb0196dc8c0b014ae5ed4adda48de", size = 33801401, upload-time = "2025-05-16T19:09:59.479Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c9/e4df32a2ad1cb7f3a112d0ed610c5e43c89da80b63c60d60e3dc23793ec0/av-14.4.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a587b5c5014c3c0e16143a0f8d99874e46b5d0c50db6111aa0b54206b5687c81", size = 32364330, upload-time = "2025-05-16T19:10:02.111Z" }, - { url = "https://files.pythonhosted.org/packages/ca/f0/64e7444a41817fde49a07d0239c033f7e9280bec4a4bb4784f5c79af95e6/av-14.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d53f75e8ac1ec8877a551c0db32a83c0aaeae719d05285281eaaba211bbc30", size = 35519508, upload-time = "2025-05-16T19:10:05.008Z" }, - { url = "https://files.pythonhosted.org/packages/c2/a8/a370099daa9033a3b6f9b9bd815304b3d8396907a14d09845f27467ba138/av-14.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c8558cfde79dd8fc92d97c70e0f0fa8c94c7a66f68ae73afdf58598f0fe5e10d", size = 36448593, upload-time = "2025-05-16T19:10:07.887Z" }, - { url = "https://files.pythonhosted.org/packages/27/bb/edb6ceff8fa7259cb6330c51dbfbc98dd1912bd6eb5f7bc05a4bb14a9d6e/av-14.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:455b6410dea0ab2d30234ffb28df7d62ca3cdf10708528e247bec3a4cdcced09", size = 34701485, upload-time = "2025-05-16T19:10:10.886Z" }, - { url = "https://files.pythonhosted.org/packages/a7/8a/957da1f581aa1faa9a5dfa8b47ca955edb47f2b76b949950933b457bfa1d/av-14.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1661efbe9d975f927b8512d654704223d936f39016fad2ddab00aee7c40f412c", size = 37521981, upload-time = "2025-05-16T19:10:13.678Z" }, - { url = "https://files.pythonhosted.org/packages/28/76/3f1cf0568592f100fd68eb40ed8c491ce95ca3c1378cc2d4c1f6d1bd295d/av-14.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:fbbeef1f421a3461086853d6464ad5526b56ffe8ccb0ab3fd0a1f121dfbf26ad", size = 27925944, upload-time = "2025-05-16T19:10:16.485Z" }, - { url = "https://files.pythonhosted.org/packages/12/4c/b0205f77352312ff457ecdf31723dbf4403b7a03fc1659075d6d32f23ef7/av-14.4.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:3d2aea7c602b105363903e4017103bc4b60336e7aff80e1c22e8b4ec09fd125f", size = 19917341, upload-time = "2025-05-16T19:10:18.826Z" }, - { url = "https://files.pythonhosted.org/packages/e1/c4/9e783bd7d47828e9c67f9c773c99de45c5ae01b3e942f1abf6cbaf530267/av-14.4.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:38c18f036aeb6dc9abf5e867d998c867f9ec93a5f722b60721fdffc123bbb2ae", size = 23715363, upload-time = "2025-05-16T19:10:21.42Z" }, - { url = "https://files.pythonhosted.org/packages/b5/26/b2b406a676864d06b1c591205782d8527e7c99e5bc51a09862c3576e0087/av-14.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58c1e18c8be73b6eada2d9ec397852ec74ebe51938451bdf83644a807189d6c8", size = 33496968, upload-time = "2025-05-16T19:10:24.178Z" }, - { url = "https://files.pythonhosted.org/packages/89/09/0a032bbe30c7049fca243ec8cf01f4be49dd6e7f7b9c3c7f0cc13f83c9d3/av-14.4.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4c32ff03a357feb030634f093089a73cb474b04efe7fbfba31f229cb2fab115", size = 32075498, upload-time = "2025-05-16T19:10:27.384Z" }, - { url = "https://files.pythonhosted.org/packages/0b/1f/0fee20f74c1f48086366e59dbd37fa0684cd0f3c782a65cbb719d26c7acd/av-14.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af31d16ae25964a6a02e09cc132b9decd5ee493c5dcb21bcdf0d71b2d6adbd59", size = 35224910, upload-time = "2025-05-16T19:10:30.104Z" }, - { url = "https://files.pythonhosted.org/packages/9e/19/1c4a201c75a2a431a85a43fd15d1fad55a28c22d596461d861c8d70f9b92/av-14.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e9fb297009e528f4851d25f3bb2781b2db18b59b10aed10240e947b77c582fb7", size = 36172918, upload-time = "2025-05-16T19:10:32.789Z" }, - { url = "https://files.pythonhosted.org/packages/00/48/26b7e5d911c807f5f017a285362470ba16f44e8ea46f8b09ab5e348dd15b/av-14.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:573314cb9eafec2827dc98c416c965330dc7508193adbccd281700d8673b9f0a", size = 34414492, upload-time = "2025-05-16T19:10:36.023Z" }, - { url = "https://files.pythonhosted.org/packages/6d/26/2f4badfa5b5b7b8f5f83d562b143a83ed940fa458eea4cad495ce95c9741/av-14.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f82ab27ee57c3b80eb50a5293222307dfdc02f810ea41119078cfc85ea3cf9a8", size = 37245826, upload-time = "2025-05-16T19:10:39.562Z" }, - { url = "https://files.pythonhosted.org/packages/f4/02/88dbb6f5a05998b730d2e695b05060297af127ac4250efbe0739daa446d5/av-14.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f682003bbcaac620b52f68ff0e85830fff165dea53949e217483a615993ca20", size = 27898395, upload-time = "2025-05-16T19:13:02.653Z" }, -] [[package]] name = "azure-ai-agents" @@ -2412,11 +2374,11 @@ wheels = [ [[package]] name = "urllib3" -version = "2.5.0" +version = "2.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, ] [[package]] diff --git a/python/uv.lock b/python/uv.lock index 3dea4cf56575..506ada015643 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -7305,11 +7305,11 @@ wheels = [ [[package]] name = "urllib3" -version = "2.6.3" +version = "2.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, ] [[package]] From 00bad6fed1437a202f742e06d06b20edf1cb4aa6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:47:54 +0000 Subject: [PATCH 19/33] Bump mistune from 3.2.0 to 3.2.1 in /python (#13965) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [mistune](https://github.com/lepture/mistune) from 3.2.0 to 3.2.1.
Release notes

Sourced from mistune's releases.

v3.2.1

   🐞 Bug Fixes

    View changes on GitHub
Changelog

Sourced from mistune's changelog.

Version 3.2.1

Released on May 3, 2026

  • Escape link in render_toc_ul.
  • Escape text in math plugin.
  • Fix regex for math plugin.
  • Escape heading's ID attribute.
  • Fix LINK_TITLE_RE to prevent DoS.
  • Escape class attribute for admonition directive.
  • Remove double-encoding of image alt text.
  • Escape class attribute for image directive.
  • Fix width/height attribute for image directive.
Commits
  • 067f908 chore: release 3.2.1
  • bf55030 Merge pull request #438 from saschabuehrle/fix/issue-370
  • 8d0cb75 fix: use strict regex for image's height and width
  • 5fa092e fix: escape xml for math plugin
  • 71ec947 Merge pull request #440 from lawrence3699/fix/image-alt-double-encoding
  • 0d6f3d8 fix: remove double-encoding of image alt text
  • 2855622 fix: escape id of headings
  • 04880a0 fix: escape id of toc
  • 7bd5709 fix: handle escaped dollar signs in inline math (fixes #370)
  • 85eb54f fix: update link reference
  • Additional commits viewable in compare view

> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- python/uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/uv.lock b/python/uv.lock index 506ada015643..4b8789a28b87 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -3128,14 +3128,14 @@ wheels = [ [[package]] name = "mistune" -version = "3.2.0" +version = "3.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9d/55/d01f0c4b45ade6536c51170b9043db8b2ec6ddf4a35c7ea3f5f559ac935b/mistune-3.2.0.tar.gz", hash = "sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a", size = 95467, upload-time = "2025-12-23T11:36:34.994Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/84/620cc3f7e3adf6f5067e10f4dbae71295d8f9e16d5d3f9ef97c40f2f592c/mistune-3.2.1.tar.gz", hash = "sha256:7c8e5501d38bac1582e067e46c8343f17d57ea1aaa735823f3aba1fd59c88a28", size = 98003, upload-time = "2026-05-03T14:33:22.312Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598, upload-time = "2025-12-23T11:36:33.211Z" }, + { url = "https://files.pythonhosted.org/packages/2a/7f/a946aa4f8752b37102b41e64dca18a1976ac705c3a0d1dfe74d820a02552/mistune-3.2.1-py3-none-any.whl", hash = "sha256:78cdb0ba5e938053ccf63651b352508d2efa9411dc8810bfb05f2dc5140c0048", size = 53749, upload-time = "2026-05-03T14:33:20.551Z" }, ] [[package]] From 83bffe197b91f60e8bc7c2c1f3c651652f7703ce Mon Sep 17 00:00:00 2001 From: Eduard van Valkenburg Date: Sat, 20 Jun 2026 00:31:54 +0200 Subject: [PATCH 20/33] Python: Add OpenAPI server URL validation (#14097) ## Summary - Add server URL validation for Python OpenAPI operation execution before outbound requests are made - Add execution settings for trusted allowed base URLs and private-network access - Pass operation arguments into server variable resolution and add regression coverage for substituted server hosts ## Testing - `uv run pytest tests/unit/connectors/openapi_plugin/test_server_url_validator.py tests/unit/connectors/openapi_plugin/test_openapi_runner.py tests/unit/connectors/openapi_plugin/test_openapi_manager.py tests/unit/connectors/openapi_plugin/test_sk_openapi.py` - `uv run pytest tests/integration/cross_language/test_cross_language.py -k openapi` - `uv run ruff check ...` - `uv run ruff format --check ...` --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../connectors/openapi_plugin/__init__.py | 8 +- .../models/rest_api_operation.py | 6 +- .../openapi_function_execution_parameters.py | 25 +- .../openapi_plugin/openapi_manager.py | 7 + .../openapi_plugin/openapi_runner.py | 7 + .../openapi_plugin/server_url_validator.py | 241 ++++++++++++++++++ .../cross_language/test_cross_language.py | 1 + .../openapi_plugin/test_openapi_manager.py | 37 ++- .../openapi_plugin/test_openapi_runner.py | 42 ++- .../test_server_url_validator.py | 170 ++++++++++++ .../openapi_plugin/test_sk_openapi.py | 33 +++ 11 files changed, 570 insertions(+), 7 deletions(-) create mode 100644 python/semantic_kernel/connectors/openapi_plugin/server_url_validator.py create mode 100644 python/tests/unit/connectors/openapi_plugin/test_server_url_validator.py diff --git a/python/semantic_kernel/connectors/openapi_plugin/__init__.py b/python/semantic_kernel/connectors/openapi_plugin/__init__.py index 875c5155d301..a8501d4b6ee5 100644 --- a/python/semantic_kernel/connectors/openapi_plugin/__init__.py +++ b/python/semantic_kernel/connectors/openapi_plugin/__init__.py @@ -7,5 +7,11 @@ from semantic_kernel.connectors.openapi_plugin.operation_selection_predicate_context import ( OperationSelectionPredicateContext, ) +from semantic_kernel.connectors.openapi_plugin.server_url_validator import ServerUrlValidationOptions -__all__ = ["OpenAPIFunctionExecutionParameters", "OpenApiParser", "OperationSelectionPredicateContext"] +__all__ = [ + "OpenAPIFunctionExecutionParameters", + "OpenApiParser", + "OperationSelectionPredicateContext", + "ServerUrlValidationOptions", +] diff --git a/python/semantic_kernel/connectors/openapi_plugin/models/rest_api_operation.py b/python/semantic_kernel/connectors/openapi_plugin/models/rest_api_operation.py index 52e1c8aac59f..94480a81ae43 100644 --- a/python/semantic_kernel/connectors/openapi_plugin/models/rest_api_operation.py +++ b/python/semantic_kernel/connectors/openapi_plugin/models/rest_api_operation.py @@ -221,7 +221,7 @@ def build_headers(self, arguments: dict[str, Any]) -> dict[str, str]: def build_operation_url(self, arguments, server_url_override=None, api_host_url=None): """Build the URL for the operation.""" - server_url = self.get_server_url(server_url_override, api_host_url) + server_url = self.get_server_url(server_url_override, api_host_url, arguments) path = self.build_path(self.path, arguments) try: return urljoin(server_url, path.lstrip("/")) @@ -253,11 +253,11 @@ def get_server_url(self, server_url_override=None, api_host_url=None, arguments= argument_name = variable_def.get("argument_name", variable_name) if argument_name in arguments: value = arguments[argument_name] - server_url_string = server_url_string.replace(f"{{{variable_name}}}", value) + server_url_string = server_url_string.replace(f"{{{variable_name}}}", str(value)) elif "default" in variable_def and variable_def["default"] is not None: # Use the default value if no argument is provided value = variable_def["default"] - server_url_string = server_url_string.replace(f"{{{variable_name}}}", value) + server_url_string = server_url_string.replace(f"{{{variable_name}}}", str(value)) else: # Raise an exception if no value is available raise FunctionExecutionException( diff --git a/python/semantic_kernel/connectors/openapi_plugin/openapi_function_execution_parameters.py b/python/semantic_kernel/connectors/openapi_plugin/openapi_function_execution_parameters.py index 2d1ac19df68b..d22a0fd44faa 100644 --- a/python/semantic_kernel/connectors/openapi_plugin/openapi_function_execution_parameters.py +++ b/python/semantic_kernel/connectors/openapi_plugin/openapi_function_execution_parameters.py @@ -16,7 +16,13 @@ class OpenAPIFunctionExecutionParameters(KernelBaseModel): - """OpenAPI function execution parameters.""" + """OpenAPI function execution parameters. + + OpenAPI operation request URLs are validated by default to reduce SSRF risk. Requests must use HTTPS + and must not resolve to private, loopback, link-local, or otherwise non-public IP addresses unless the + target is explicitly trusted through `server_url_validation_allowed_base_urls` or + `allow_private_network_access`. + """ http_client: httpx.AsyncClient | None = None auth_callback: AuthCallbackType | None = None @@ -47,9 +53,24 @@ class OpenAPIFunctionExecutionParameters(KernelBaseModel): "and need external HTTP $ref resolution." ), ) + server_url_validation_allowed_base_urls: list[str] = Field( + default_factory=list, + description=( + "Base URLs that are explicitly allowed for OpenAPI operation requests. Matching URLs bypass " + "the default HTTPS-only and private-network validation gates. Set only for trusted endpoints." + ), + ) + allow_private_network_access: bool = Field( + False, + description=( + "Whether OpenAPI operation requests may target private, loopback, link-local, or otherwise " + "non-public IP addresses. Disabled by default to prevent SSRF." + ), + ) def model_post_init(self, __context: Any) -> None: """Post initialization method for the model.""" + from semantic_kernel.connectors.openapi_plugin.server_url_validator import ServerUrlValidationOptions from semantic_kernel.utils.telemetry.user_agent import HTTP_USER_AGENT if self.server_url_override: @@ -57,5 +78,7 @@ def model_post_init(self, __context: Any) -> None: if not parsed_url.scheme or not parsed_url.netloc: raise ValueError(f"Invalid server_url_override: {self.server_url_override}") + ServerUrlValidationOptions(allowed_base_urls=self.server_url_validation_allowed_base_urls) + if not self.user_agent: self.user_agent = HTTP_USER_AGENT diff --git a/python/semantic_kernel/connectors/openapi_plugin/openapi_manager.py b/python/semantic_kernel/connectors/openapi_plugin/openapi_manager.py index b825a1635cae..a715dac6b9a4 100644 --- a/python/semantic_kernel/connectors/openapi_plugin/openapi_manager.py +++ b/python/semantic_kernel/connectors/openapi_plugin/openapi_manager.py @@ -11,6 +11,7 @@ from semantic_kernel.connectors.openapi_plugin.models.rest_api_uri import Uri from semantic_kernel.connectors.openapi_plugin.openapi_parser import OpenApiParser from semantic_kernel.connectors.openapi_plugin.openapi_runner import OpenApiRunner +from semantic_kernel.connectors.openapi_plugin.server_url_validator import ServerUrlValidationOptions from semantic_kernel.exceptions.function_exceptions import FunctionExecutionException from semantic_kernel.functions.kernel_arguments import KernelArguments from semantic_kernel.functions.kernel_function_decorator import kernel_function @@ -79,6 +80,12 @@ def create_functions_from_openapi( http_client=execution_settings.http_client if execution_settings else None, enable_dynamic_payload=execution_settings.enable_dynamic_payload if execution_settings else True, enable_payload_namespacing=execution_settings.enable_payload_namespacing if execution_settings else False, + server_url_validation_options=ServerUrlValidationOptions( + allowed_base_urls=execution_settings.server_url_validation_allowed_base_urls, + allow_private_network_access=execution_settings.allow_private_network_access, + ) + if execution_settings + else None, ) functions = [] diff --git a/python/semantic_kernel/connectors/openapi_plugin/openapi_runner.py b/python/semantic_kernel/connectors/openapi_plugin/openapi_runner.py index d1d2db141b2b..ee88d4111ffb 100644 --- a/python/semantic_kernel/connectors/openapi_plugin/openapi_runner.py +++ b/python/semantic_kernel/connectors/openapi_plugin/openapi_runner.py @@ -17,6 +17,10 @@ from semantic_kernel.connectors.openapi_plugin.models.rest_api_operation import RestApiOperation from semantic_kernel.connectors.openapi_plugin.models.rest_api_payload import RestApiPayload from semantic_kernel.connectors.openapi_plugin.models.rest_api_run_options import RestApiRunOptions +from semantic_kernel.connectors.openapi_plugin.server_url_validator import ( + ServerUrlValidationOptions, + validate_server_url, +) from semantic_kernel.exceptions.function_exceptions import FunctionExecutionException from semantic_kernel.functions.kernel_arguments import KernelArguments from semantic_kernel.utils.feature_stage_decorator import experimental @@ -39,6 +43,7 @@ def __init__( http_client: httpx.AsyncClient | None = None, enable_dynamic_payload: bool = True, enable_payload_namespacing: bool = False, + server_url_validation_options: ServerUrlValidationOptions | None = None, ): """Initialize the OpenApiRunner.""" self.spec = Spec.from_dict(parsed_openapi_document) # type: ignore @@ -46,6 +51,7 @@ def __init__( self.http_client = http_client self.enable_dynamic_payload = enable_dynamic_payload self.enable_payload_namespacing = enable_payload_namespacing + self.server_url_validation_options = server_url_validation_options or ServerUrlValidationOptions() def build_full_url(self, base_url, query_string): """Build the full URL.""" @@ -137,6 +143,7 @@ async def run_operation( server_url_override=options.server_url_override if options else None, api_host_url=options.api_host_url if options else None, ) + await validate_server_url(url, self.server_url_validation_options) headers = operation.build_headers(arguments=arguments) payload, _ = self.build_operation_payload(operation=operation, arguments=arguments) diff --git a/python/semantic_kernel/connectors/openapi_plugin/server_url_validator.py b/python/semantic_kernel/connectors/openapi_plugin/server_url_validator.py new file mode 100644 index 000000000000..a3ede15f0f3c --- /dev/null +++ b/python/semantic_kernel/connectors/openapi_plugin/server_url_validator.py @@ -0,0 +1,241 @@ +# Copyright (c) Microsoft. All rights reserved. + +import asyncio +import ipaddress +import socket +from collections.abc import Awaitable, Callable, Sequence +from typing import Any +from urllib.parse import ParseResult, urlparse + +from pydantic import Field + +from semantic_kernel.exceptions.function_exceptions import FunctionExecutionException +from semantic_kernel.kernel_pydantic import KernelBaseModel + +DnsResolver = Callable[[str], Awaitable[Sequence[str | ipaddress.IPv4Address | ipaddress.IPv6Address]]] + +DEFAULT_ALLOWED_SCHEME = "https" + + +class ServerUrlValidationOptions(KernelBaseModel): + """Options for validating OpenAPI operation request URLs.""" + + allowed_base_urls: list[str] = Field(default_factory=list) + allow_private_network_access: bool = False + + def model_post_init(self, __context: Any) -> None: + """Validate configured allowed base URLs.""" + for allowed_base_url in self.allowed_base_urls: + _parse_absolute_url(allowed_base_url, option_name="allowed_base_urls") + + +async def validate_server_url( + url: str, + options: ServerUrlValidationOptions | None = None, + dns_resolver: DnsResolver | None = None, +) -> None: + """Validate a fully resolved OpenAPI operation URL against the supplied policy.""" + options = options or ServerUrlValidationOptions() + try: + parsed_url = _parse_absolute_url(url) + except ValueError as exc: + raise FunctionExecutionException( + f"The request URI '{url}' is not allowed because it is not a valid absolute URI." + ) from exc + + if _matches_allowed_base_url(parsed_url, options.allowed_base_urls): + return + + if options.allowed_base_urls: + raise FunctionExecutionException( + f"The request URI '{url}' is not allowed. It does not match any of the allowed base URLs." + ) + + if parsed_url.scheme.lower() != DEFAULT_ALLOWED_SCHEME: + raise FunctionExecutionException( + f"The request URI scheme '{parsed_url.scheme}' is not allowed. " + f"Only '{DEFAULT_ALLOWED_SCHEME}' is permitted by default. " + "To allow this URL, add it to server_url_validation_allowed_base_urls." + ) + + if options.allow_private_network_access: + return + + await _ensure_public_host(parsed_url, dns_resolver) + + +def try_categorize_non_public_address( + address: str | ipaddress.IPv4Address | ipaddress.IPv6Address, +) -> tuple[bool, str]: + """Return whether an IP address is non-public and the category when blocked.""" + ip_address = ipaddress.ip_address(address) + + if isinstance(ip_address, ipaddress.IPv6Address) and ip_address.ipv4_mapped: + ip_address = ip_address.ipv4_mapped + + if isinstance(ip_address, ipaddress.IPv4Address): + return _try_classify_ipv4(ip_address) + + return _try_classify_ipv6(ip_address) + + +def _parse_absolute_url(url: str, option_name: str = "url") -> ParseResult: + parsed_url = urlparse(url) + try: + parsed_url.port + except ValueError as exc: + raise ValueError(f"Invalid {option_name}: {url}") from exc + + if not parsed_url.scheme or not parsed_url.netloc or not parsed_url.hostname: + raise ValueError(f"Invalid {option_name}: {url}") + return parsed_url + + +def _matches_allowed_base_url(url: ParseResult, allowed_base_urls: list[str]) -> bool: + for allowed_base_url in allowed_base_urls: + base_url = _parse_absolute_url(allowed_base_url, option_name="allowed_base_urls") + if url.scheme.lower() != base_url.scheme.lower(): + continue + if (url.hostname or "").lower() != (base_url.hostname or "").lower(): + continue + if _effective_port(url) != _effective_port(base_url): + continue + if _matches_path_prefix(url.path, base_url.path): + return True + + return False + + +def _effective_port(url: ParseResult) -> int | None: + if url.port is not None: + return url.port + if url.scheme.lower() == "https": + return 443 + if url.scheme.lower() == "http": + return 80 + return None + + +def _matches_path_prefix(url_path: str, base_path: str) -> bool: + url_path = url_path or "/" + base_path = base_path or "/" + + if url_path.lower() == base_path.lower(): + return True + + base_path_with_slash = base_path if base_path.endswith("/") else f"{base_path}/" + return url_path.lower().startswith(base_path_with_slash.lower()) + + +async def _ensure_public_host(parsed_url: ParseResult, dns_resolver: DnsResolver | None) -> None: + host = parsed_url.hostname + if host is None: + raise FunctionExecutionException(f"The request URI '{parsed_url.geturl()}' does not contain a valid host.") + + try: + ip_address = ipaddress.ip_address(host) + except ValueError: + addresses = await _resolve_host(host, dns_resolver) + else: + _ensure_public_address(parsed_url.geturl(), ip_address) + return + + if not addresses: + raise FunctionExecutionException( + f"The request URI '{parsed_url.geturl()}' is not allowed: DNS resolution for host " + f"'{host}' returned no addresses. The request is blocked as a precaution." + ) + + for address in addresses: + _ensure_public_address(parsed_url.geturl(), address) + + +async def _resolve_host( + host: str, + dns_resolver: DnsResolver | None, +) -> list[ipaddress.IPv4Address | ipaddress.IPv6Address]: + try: + if dns_resolver: + resolved_addresses = await dns_resolver(host) + return [ipaddress.ip_address(address) for address in resolved_addresses] + + loop = asyncio.get_running_loop() + addr_info = await loop.getaddrinfo(host, None, type=socket.SOCK_STREAM) + except (OSError, ValueError) as exc: + raise FunctionExecutionException( + f"The request URI host '{host}' is not allowed: DNS resolution failed. " + "The request is blocked as a precaution to prevent potential access to private network addresses." + ) from exc + + addresses: list[ipaddress.IPv4Address | ipaddress.IPv6Address] = [] + seen_addresses: set[str] = set() + for family, _, _, _, sockaddr in addr_info: + if family not in (socket.AF_INET, socket.AF_INET6): + continue + address = ipaddress.ip_address(sockaddr[0]) + address_string = str(address) + if address_string not in seen_addresses: + addresses.append(address) + seen_addresses.add(address_string) + return addresses + + +def _ensure_public_address(url: str, address: ipaddress.IPv4Address | ipaddress.IPv6Address) -> None: + blocked, category = try_categorize_non_public_address(address) + if blocked: + raise FunctionExecutionException( + f"The request URI '{url}' is not allowed: host resolves to a {category} address ({address}), " + "which is blocked by default to prevent Server-Side Request Forgery (SSRF). " + "To allow this URL, add it to server_url_validation_allowed_base_urls or set " + "allow_private_network_access=True." + ) + + +def _try_classify_ipv4(address: ipaddress.IPv4Address) -> tuple[bool, str]: + b0, b1, b2, _ = address.packed + + if b0 == 0: + return True, "unspecified" + if b0 == 10: + return True, "private (RFC1918)" + if b0 == 127: + return True, "loopback" + if b0 == 169 and b1 == 254: + return True, "link-local" + if b0 == 172 and 16 <= b1 <= 31: + return True, "private (RFC1918)" + if b0 == 192 and b1 == 168: + return True, "private (RFC1918)" + if b0 == 100 and 64 <= b1 <= 127: + return True, "carrier-grade NAT" + if b0 == 198 and b1 in (18, 19): + return True, "benchmarking" + if b0 == 192 and b1 == 0 and b2 in (0, 2): + return True, "reserved" + if b0 == 198 and b1 == 51 and b2 == 100: + return True, "reserved" + if b0 == 203 and b1 == 0 and b2 == 113: + return True, "reserved" + if 224 <= b0 <= 239: + return True, "multicast" + if b0 >= 240: + return True, "reserved" + + return False, "" + + +def _try_classify_ipv6(address: ipaddress.IPv6Address) -> tuple[bool, str]: + if address.is_loopback: + return True, "loopback" + if address.is_unspecified: + return True, "unspecified" + if address.is_link_local: + return True, "link-local" + if address in ipaddress.ip_network("fc00::/7"): + return True, "private (IPv6 ULA)" + if address.is_multicast: + return True, "multicast" + if address in ipaddress.ip_network("2001:db8::/32"): + return True, "reserved" + + return False, "" diff --git a/python/tests/integration/cross_language/test_cross_language.py b/python/tests/integration/cross_language/test_cross_language.py index ee86e8888d64..72aa0a16bac0 100644 --- a/python/tests/integration/cross_language/test_cross_language.py +++ b/python/tests/integration/cross_language/test_cross_language.py @@ -762,6 +762,7 @@ async def mock_request(request: httpx.Request): openapi_document_path=openapi_spec_file, execution_settings=OpenAPIFunctionExecutionParameters( http_client=client, + server_url_validation_allowed_base_urls=["https://127.0.0.1"], ), ) diff --git a/python/tests/unit/connectors/openapi_plugin/test_openapi_manager.py b/python/tests/unit/connectors/openapi_plugin/test_openapi_manager.py index 37bd6b324d77..dd32f70998dd 100644 --- a/python/tests/unit/connectors/openapi_plugin/test_openapi_manager.py +++ b/python/tests/unit/connectors/openapi_plugin/test_openapi_manager.py @@ -9,11 +9,15 @@ RestApiParameterLocation, ) from semantic_kernel.connectors.openapi_plugin.models.rest_api_run_options import RestApiRunOptions +from semantic_kernel.connectors.openapi_plugin.openapi_function_execution_parameters import ( + OpenAPIFunctionExecutionParameters, +) from semantic_kernel.connectors.openapi_plugin.openapi_manager import ( _create_function_from_operation, create_functions_from_openapi, ) from semantic_kernel.connectors.openapi_plugin.openapi_runner import OpenApiRunner +from semantic_kernel.connectors.openapi_plugin.server_url_validator import ServerUrlValidationOptions from semantic_kernel.exceptions import FunctionExecutionException from semantic_kernel.functions.kernel_function_decorator import kernel_function from semantic_kernel.functions.kernel_parameter_metadata import KernelParameterMetadata @@ -236,7 +240,10 @@ async def test_run_operation_uses_timeout_from_run_options(): "info": {"title": "Test", "version": "1.0.0"}, "paths": {}, } - runner = OpenApiRunner(parsed_openapi_document=minimal_openapi_spec) + runner = OpenApiRunner( + parsed_openapi_document=minimal_openapi_spec, + server_url_validation_options=ServerUrlValidationOptions(allowed_base_urls=["https://api.example.com"]), + ) operation = MagicMock() operation.method = "GET" operation.build_headers.return_value = {} @@ -274,3 +281,31 @@ async def test_run_operation_uses_timeout_from_run_options(): found = True break assert found, f"httpx.AsyncClient was not called with timeout={desired_timeout}" + + +@patch("semantic_kernel.connectors.openapi_plugin.openapi_manager.OpenApiRunner") +@patch("semantic_kernel.connectors.openapi_plugin.openapi_manager.OpenApiParser") +def test_create_functions_from_openapi_propagates_server_url_validation_settings(mock_parser_class, mock_runner_class): + parsed_doc = { + "openapi": "3.0.0", + "info": {"title": "Test", "version": "1.0.0"}, + "paths": {}, + } + mock_parser = MagicMock() + mock_parser.parse.return_value = parsed_doc + mock_parser.create_rest_api_operations.return_value = {} + mock_parser_class.return_value = mock_parser + execution_settings = OpenAPIFunctionExecutionParameters( + server_url_validation_allowed_base_urls=["http://192.168.1.100/v1"], + allow_private_network_access=True, + ) + + create_functions_from_openapi( + plugin_name="test_plugin", + openapi_document_path="test_openapi_document_path", + execution_settings=execution_settings, + ) + + validation_options = mock_runner_class.call_args.kwargs["server_url_validation_options"] + assert validation_options.allowed_base_urls == ["http://192.168.1.100/v1"] + assert validation_options.allow_private_network_access is True diff --git a/python/tests/unit/connectors/openapi_plugin/test_openapi_runner.py b/python/tests/unit/connectors/openapi_plugin/test_openapi_runner.py index 1665314a903a..b990ebfb834e 100644 --- a/python/tests/unit/connectors/openapi_plugin/test_openapi_runner.py +++ b/python/tests/unit/connectors/openapi_plugin/test_openapi_runner.py @@ -8,6 +8,7 @@ from semantic_kernel.connectors.openapi_plugin.models.rest_api_operation import RestApiOperation from semantic_kernel.connectors.openapi_plugin.models.rest_api_payload import RestApiPayload from semantic_kernel.connectors.openapi_plugin.openapi_manager import OpenApiRunner +from semantic_kernel.connectors.openapi_plugin.server_url_validator import ServerUrlValidationOptions from semantic_kernel.exceptions import FunctionExecutionException @@ -294,7 +295,9 @@ def test_get_first_response_media_type_default(): async def test_run_operation(): - runner = OpenApiRunner({}) + runner = OpenApiRunner( + {}, server_url_validation_options=ServerUrlValidationOptions(allowed_base_urls=["http://example.com"]) + ) operation = MagicMock() arguments = {} options = MagicMock() @@ -323,3 +326,40 @@ async def mock_request(*args, **kwargs): result = await runner.run_operation(operation, arguments, options) assert result == "response text" + + +async def test_run_operation_blocks_disallowed_url_before_request(): + runner = OpenApiRunner({}) + operation = MagicMock() + operation.method = "GET" + runner.build_operation_url = MagicMock(return_value="https://127.0.0.1/latest/meta-data/") + runner.http_client = AsyncMock() + runner.http_client.request = AsyncMock() + + with pytest.raises(FunctionExecutionException, match="loopback"): + await runner.run_operation(operation, {}, None) + + operation.build_headers.assert_not_called() + runner.http_client.request.assert_not_called() + + +async def test_run_operation_blocks_server_variable_ssrf_before_request(): + runner = OpenApiRunner({}) + operation = RestApiOperation( + id="getCloudMetadata", + method="GET", + servers=[ + { + "url": "https://{api_server}/", + "variables": {"api_server": {"default": "api.example.com"}}, + } + ], + path="latest/meta-data/", + ) + runner.http_client = AsyncMock() + runner.http_client.request = AsyncMock() + + with pytest.raises(FunctionExecutionException, match="link-local"): + await runner.run_operation(operation, {"api_server": "169.254.169.254"}, None) + + runner.http_client.request.assert_not_called() diff --git a/python/tests/unit/connectors/openapi_plugin/test_server_url_validator.py b/python/tests/unit/connectors/openapi_plugin/test_server_url_validator.py new file mode 100644 index 000000000000..177ff15cb2c6 --- /dev/null +++ b/python/tests/unit/connectors/openapi_plugin/test_server_url_validator.py @@ -0,0 +1,170 @@ +# Copyright (c) Microsoft. All rights reserved. + +import socket + +import pytest + +from semantic_kernel.connectors.openapi_plugin.server_url_validator import ( + ServerUrlValidationOptions, + try_categorize_non_public_address, + validate_server_url, +) +from semantic_kernel.exceptions import FunctionExecutionException + + +@pytest.mark.parametrize( + ("address", "expected_category"), + [ + ("127.0.0.1", "loopback"), + ("127.255.255.254", "loopback"), + ("169.254.169.254", "link-local"), + ("169.254.0.1", "link-local"), + ("10.0.0.1", "private (RFC1918)"), + ("172.16.0.1", "private (RFC1918)"), + ("172.31.255.255", "private (RFC1918)"), + ("192.168.0.1", "private (RFC1918)"), + ("100.64.0.1", "carrier-grade NAT"), + ("100.127.255.254", "carrier-grade NAT"), + ("0.0.0.0", "unspecified"), + ("224.0.0.1", "multicast"), + ("239.255.255.255", "multicast"), + ("240.0.0.1", "reserved"), + ("255.255.255.255", "reserved"), + ("198.18.0.1", "benchmarking"), + ("192.0.2.1", "reserved"), + ("198.51.100.1", "reserved"), + ("203.0.113.1", "reserved"), + ("::1", "loopback"), + ("::", "unspecified"), + ("fe80::1", "link-local"), + ("fc00::1", "private (IPv6 ULA)"), + ("fd00::1", "private (IPv6 ULA)"), + ("ff02::1", "multicast"), + ("2001:db8::1", "reserved"), + ("::ffff:127.0.0.1", "loopback"), + ("::ffff:169.254.169.254", "link-local"), + ], +) +def test_try_categorize_non_public_address(address: str, expected_category: str): + blocked, category = try_categorize_non_public_address(address) + + assert blocked is True + assert category == expected_category + + +@pytest.mark.parametrize( + "address", + [ + "8.8.8.8", + "1.1.1.1", + "93.184.216.34", + "172.15.255.255", + "172.32.0.1", + "11.0.0.1", + "192.169.0.1", + "100.63.255.255", + "100.128.0.1", + "2606:4700:4700::1111", + ], +) +def test_try_categorize_non_public_address_allows_public_addresses(address: str): + blocked, category = try_categorize_non_public_address(address) + + assert blocked is False + assert category == "" + + +async def test_validate_server_url_rejects_literal_link_local_ipv4(): + with pytest.raises(FunctionExecutionException, match="link-local"): + await validate_server_url("https://169.254.169.254/latest/meta-data/") + + +async def test_validate_server_url_rejects_literal_loopback_ipv6(): + with pytest.raises(FunctionExecutionException, match="loopback"): + await validate_server_url("https://[::1]/") + + +async def test_validate_server_url_rejects_http_scheme_by_default(): + with pytest.raises(FunctionExecutionException, match="scheme"): + await validate_server_url("http://api.example.com/") + + +async def test_validate_server_url_allows_public_https_literal_by_default(): + await validate_server_url("https://1.1.1.1/") + + +async def test_validate_server_url_rejects_invalid_uri_with_function_execution_exception(): + with pytest.raises(FunctionExecutionException, match="not a valid absolute URI"): + await validate_server_url("invalid_url") + + +async def test_validate_server_url_allows_explicit_base_url_for_private_http_address(): + options = ServerUrlValidationOptions(allowed_base_urls=["http://192.168.1.100/v1"]) + + await validate_server_url("http://192.168.1.100/v1/orders", options) + + +async def test_validate_server_url_rejects_when_allowed_base_urls_do_not_match(): + options = ServerUrlValidationOptions(allowed_base_urls=["https://api.example.com/v1"]) + + with pytest.raises(FunctionExecutionException, match="allowed base URLs"): + await validate_server_url("https://api.example.com/v2/orders", options) + + +async def test_validate_server_url_allows_private_network_access_after_scheme_gate(): + options = ServerUrlValidationOptions(allow_private_network_access=True) + + await validate_server_url("https://10.0.0.5/", options) + + +async def test_validate_server_url_blocks_hostname_resolving_to_link_local(): + async def fake_resolver(host: str): + assert host == "evil.example.com" + return ["169.254.169.254"] + + with pytest.raises(FunctionExecutionException, match="link-local"): + await validate_server_url("https://evil.example.com/latest/meta-data/", dns_resolver=fake_resolver) + + +async def test_validate_server_url_blocks_hostname_resolving_to_loopback(): + async def fake_resolver(host: str): + assert host == "attacker.example.com" + return ["127.0.0.1"] + + with pytest.raises(FunctionExecutionException, match="loopback"): + await validate_server_url("https://attacker.example.com/api", dns_resolver=fake_resolver) + + +async def test_validate_server_url_blocks_when_any_resolved_address_is_private(): + async def fake_resolver(host: str): + assert host == "rebind.example.com" + return ["93.184.216.34", "10.0.0.1"] + + with pytest.raises(FunctionExecutionException, match="private"): + await validate_server_url("https://rebind.example.com/", dns_resolver=fake_resolver) + + +async def test_validate_server_url_allows_hostname_resolving_to_public_ip(): + async def fake_resolver(host: str): + assert host == "api.example.com" + return ["93.184.216.34"] + + await validate_server_url("https://api.example.com/", dns_resolver=fake_resolver) + + +async def test_validate_server_url_blocks_dns_resolution_failure(): + async def fake_resolver(host: str): + assert host == "unreachable.example.com" + raise socket.gaierror() + + with pytest.raises(FunctionExecutionException, match="DNS resolution"): + await validate_server_url("https://unreachable.example.com/", dns_resolver=fake_resolver) + + +async def test_validate_server_url_blocks_empty_dns_response(): + async def fake_resolver(host: str): + assert host == "empty-dns.example.com" + return [] + + with pytest.raises(FunctionExecutionException, match="returned no addresses"): + await validate_server_url("https://empty-dns.example.com/", dns_resolver=fake_resolver) diff --git a/python/tests/unit/connectors/openapi_plugin/test_sk_openapi.py b/python/tests/unit/connectors/openapi_plugin/test_sk_openapi.py index c59be28e9c55..1b44733562c9 100644 --- a/python/tests/unit/connectors/openapi_plugin/test_sk_openapi.py +++ b/python/tests/unit/connectors/openapi_plugin/test_sk_openapi.py @@ -342,6 +342,23 @@ def test_get_server_url_with_servers_and_variables(): assert operation.get_server_url(arguments=arguments) == expected_url +def test_get_server_url_with_servers_coerces_variable_argument_to_string(): + operation = RestApiOperation( + id="test", + method="GET", + servers=[ + { + "url": "https://example.com/{version}", + "variables": {"version": {"default": "v1", "argument_name": "api_version"}}, + } + ], + path="/resource/{id}", + ) + arguments = {"api_version": 2} + expected_url = "https://example.com/2/" + assert operation.get_server_url(arguments=arguments) == expected_url + + def test_get_server_url_with_servers_and_default_variable(): operation = RestApiOperation( id="test", @@ -353,6 +370,17 @@ def test_get_server_url_with_servers_and_default_variable(): assert operation.get_server_url() == expected_url +def test_get_server_url_with_servers_coerces_default_variable_to_string(): + operation = RestApiOperation( + id="test", + method="GET", + servers=[{"url": "https://example.com/{version}", "variables": {"version": {"default": 1}}}], + path="/resource/{id}", + ) + expected_url = "https://example.com/1/" + assert operation.get_server_url() == expected_url + + def test_get_server_url_with_override(): operation = RestApiOperation( id="test", @@ -896,3 +924,8 @@ def test_invalid_server_url_override(): with pytest.raises(ValueError, match="Invalid server_url_override: invalid_url"): params = OpenAPIFunctionExecutionParameters(server_url_override="invalid_url") params.model_post_init(None) + + +def test_invalid_server_url_validation_allowed_base_url(): + with pytest.raises(ValueError, match="Invalid allowed_base_urls: invalid_url"): + OpenAPIFunctionExecutionParameters(server_url_validation_allowed_base_urls=["invalid_url"]) From 88e1060b99d9a5ee419cb3f62f805ccb86d0f445 Mon Sep 17 00:00:00 2001 From: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> Date: Tue, 23 Jun 2026 22:02:17 +0100 Subject: [PATCH 21/33] Python: Adjust request validation (#14114) Updates request validation behavior and related tests. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../core_plugins/http_plugin.py | 42 ++++++++++++++++--- .../unit/core_plugins/test_http_plugin.py | 40 ++++++++++++++++-- 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/python/semantic_kernel/core_plugins/http_plugin.py b/python/semantic_kernel/core_plugins/http_plugin.py index 8a554410fb44..c461deccbf8c 100644 --- a/python/semantic_kernel/core_plugins/http_plugin.py +++ b/python/semantic_kernel/core_plugins/http_plugin.py @@ -1,7 +1,7 @@ # Copyright (c) Microsoft. All rights reserved. import json -from typing import Annotated, Any +from typing import Annotated, Any, ClassVar from urllib.parse import urlparse import aiohttp @@ -35,6 +35,9 @@ class HttpPlugin(KernelBaseModel): - When ``allow_all_domains`` is True, redirects are allowed regardless of whether ``allowed_domains`` is also set. - Only ``http`` and ``https`` URL schemes are permitted. + - Only standard ports (80, 443) are permitted by default. Set ``allowed_ports`` + to permit additional ports. Port validation is skipped when + ``allow_all_domains`` is True. """ allowed_domains: set[str] | None = None @@ -43,7 +46,16 @@ class HttpPlugin(KernelBaseModel): allow_all_domains: bool = False """When True, requests to any domain are allowed. Must be explicitly set.""" - _ALLOWED_SCHEMES: frozenset[str] = frozenset({"http", "https"}) + allowed_ports: set[int] | None = None + """Set of ports permitted for outbound requests. Defaults to ``{80, 443}`` when not set. + + Ignored when ``allow_all_domains`` is True. Set explicitly to permit non-standard ports + (e.g. ``allowed_ports={443, 8443}``). + """ + + _ALLOWED_SCHEMES: ClassVar[frozenset[str]] = frozenset({"http", "https"}) + _DEFAULT_SCHEME_PORTS: ClassVar[dict[str, int]] = {"http": 80, "https": 443} + _DEFAULT_ALLOWED_PORTS: ClassVar[frozenset[int]] = frozenset({80, 443}) @property def _allow_redirects(self) -> bool: @@ -74,10 +86,25 @@ def _is_uri_allowed(self, url: str) -> bool: if not host: return False - # If allow_all_domains is set, skip domain check + # Validate that the port component is syntactically valid, regardless of + # allow_all_domains. Accessing parsed.port raises ValueError for a malformed + # or out-of-range port. + try: + port = parsed.port + except ValueError: + return False + + # If allow_all_domains is set, skip the domain and port allow-list checks. if self.allow_all_domains: return True + # Enforce the port allow-list (deny-by-default to non-standard ports). + if port is None: + port = self._DEFAULT_SCHEME_PORTS.get(parsed.scheme.lower()) + allowed_ports = self.allowed_ports if self.allowed_ports is not None else self._DEFAULT_ALLOWED_PORTS + if port not in allowed_ports: + return False + # If allowed_domains is set, check against it if self.allowed_domains is not None: return host.lower() in {domain.lower() for domain in self.allowed_domains} @@ -86,14 +113,19 @@ def _is_uri_allowed(self, url: str) -> bool: return False def _validate_url(self, url: str) -> None: - """Validate the URL, checking scheme, emptiness, and allowed domains. + """Validate the URL before sending a request. + + Always checks that the URL is non-empty, uses an allowed scheme, and has a + syntactically valid port. When ``allow_all_domains`` is False, additionally + enforces the port and domain allow-lists. Args: url: The URL to validate. Raises: FunctionExecutionException: If the URL is empty, uses a disallowed scheme, - or targets a domain that is not allowed. + has a malformed port, or (unless ``allow_all_domains`` is True) targets + a port or domain that is not allowed. """ if not url: raise FunctionExecutionException("url cannot be `None` or empty") diff --git a/python/tests/unit/core_plugins/test_http_plugin.py b/python/tests/unit/core_plugins/test_http_plugin.py index 216967ffaee9..c0c8211b1d78 100644 --- a/python/tests/unit/core_plugins/test_http_plugin.py +++ b/python/tests/unit/core_plugins/test_http_plugin.py @@ -195,10 +195,44 @@ async def test_allowed_domains_multiple_domains(): async def test_allowed_domains_with_port(): - """Test that domain matching works with URLs containing ports.""" + """Test that non-standard ports are rejected by default, even on an allowed domain.""" plugin = HttpPlugin(allowed_domains={"example.com"}) - # Port is not part of the host/hostname in urlparse - assert plugin._is_uri_allowed("https://example.com:8080/path") is True + # Standard ports on an allowed domain are permitted. + assert plugin._is_uri_allowed("https://example.com/path") is True + assert plugin._is_uri_allowed("https://example.com:443/path") is True + assert plugin._is_uri_allowed("http://example.com:80/path") is True + # Non-standard ports are rejected even though the host is allowed (SSRF hardening). + assert plugin._is_uri_allowed("https://example.com:8080/path") is False + assert plugin._is_uri_allowed("https://example.com:9200/_cat/indices") is False + assert plugin._is_uri_allowed("https://example.com:6379/") is False + + +async def test_allowed_ports_custom(): + """Test that custom allowed_ports permit additional ports.""" + plugin = HttpPlugin(allowed_domains={"example.com"}, allowed_ports={443, 8443}) + assert plugin._is_uri_allowed("https://example.com:8443/path") is True + assert plugin._is_uri_allowed("https://example.com/path") is True + # A port not in the custom set is still rejected. + assert plugin._is_uri_allowed("https://example.com:9200/path") is False + + +async def test_allow_all_domains_ignores_port(): + """Test that port validation is skipped when allow_all_domains is True.""" + plugin = HttpPlugin(allow_all_domains=True) + assert plugin._is_uri_allowed("https://any-domain.com:9200/path") is True + assert plugin._is_uri_allowed("https://any-domain.com:6379/path") is True + + +async def test_malformed_port_rejected(): + """Test that a malformed/out-of-range port is rejected.""" + plugin = HttpPlugin(allowed_domains={"example.com"}) + assert plugin._is_uri_allowed("https://example.com:99999/path") is False + + +async def test_malformed_port_rejected_with_allow_all_domains(): + """Test that a malformed/out-of-range port is rejected even when allow_all_domains is True.""" + plugin = HttpPlugin(allow_all_domains=True) + assert plugin._is_uri_allowed("https://example.com:99999/path") is False async def test_allowed_domains_subdomain_not_matched(): From 82f244233b89d38bf5e424ca409caa46f14490e6 Mon Sep 17 00:00:00 2001 From: westey <164392973+westey-m@users.noreply.github.com> Date: Wed, 24 Jun 2026 17:51:21 +0100 Subject: [PATCH 22/33] .Net: Update SK to use MEVD packages and move MEVD projects out of main solution (#14117) ### Motivation and Context - The MEVD packages are not shipped from this repo anymore. ### Description - Moving the packages out of the main SK solution - Update all projects to use MEVD.Abstractions package directly - Revert some previous code changes to make the MEVD implementations compatible with the last MEVD.Abstractions package released from this repo. ### Contribution Checklist - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone :smile: --- .github/workflows/dotnet-build-and-test.yml | 6 +- dotnet/Directory.Packages.props | 11 + dotnet/MEVD.slnf | 50 -- dotnet/MEVD.slnx | 66 ++ dotnet/SK-dotnet.slnx | 47 -- dotnet/samples/Concepts/Concepts.csproj | 20 +- ...gingFace_TextEmbeddingCustomHttpHandler.cs | 7 +- .../ChatWithAgent.ApiService.csproj | 2 +- .../MCPServer/MCPServer.csproj | 2 +- .../Demos/OnnxSimpleRAG/OnnxSimpleRAG.csproj | 2 +- .../VectorStoreRAG/VectorStoreRAG.csproj | 16 +- .../GettingStartedWithTextSearch.csproj | 2 +- .../GettingStartedWithVectorStores.csproj | 7 +- .../IntegrationTests/IntegrationTests.csproj | 12 - .../Memory/MongoDB/MongoModelBuilder.cs | 13 +- .../SemanticKernel.Abstractions.csproj | 5 +- .../SemanticKernel.UnitTests.csproj | 2 +- .../AzureAISearch/AzureAISearch.csproj | 5 +- .../CosmosMongoDB/CosmosMongoDB.csproj | 5 +- .../VectorData/CosmosNoSql/CosmosNoSql.csproj | 5 +- .../CosmosNoSql/CosmosNoSqlMapper.cs | 6 +- .../src/VectorData/InMemory/InMemory.csproj | 5 +- dotnet/src/VectorData/MongoDB/MongoDB.csproj | 5 +- .../src/VectorData/PgVector/PgVector.csproj | 5 +- .../src/VectorData/Pinecone/Pinecone.csproj | 5 +- dotnet/src/VectorData/Qdrant/Qdrant.csproj | 5 +- dotnet/src/VectorData/Redis/Redis.csproj | 5 +- .../src/VectorData/SqlServer/SqlServer.csproj | 5 +- .../src/VectorData/SqliteVec/SqliteVec.csproj | 5 +- .../VectorData.Abstractions/.editorconfig | 3 - .../AnyTagEqualToFilterClause.cs | 33 - .../FilterClauses/EqualToFilterClause.cs | 33 - .../FilterClauses/FilterClause.cs | 23 - .../VectorData.Abstractions/PACKAGE.md | 51 -- .../Properties/AssemblyInfo.cs | 3 - .../CollectionJsonModelBuilder.cs | 104 --- .../ProviderServices/CollectionModel.cs | 243 ------- .../CollectionModelBuilder.cs | 609 ------------------ .../CollectionModelBuildingOptions.cs | 34 - .../ProviderServices/DataPropertyModel.cs | 34 - .../EmbeddingGenerationDispatcher.cs | 86 --- .../Filter/FilterPreprocessingOptions.cs | 22 - .../Filter/FilterTranslatorBase.cs | 403 ------------ .../Filter/QueryParameterExpression.cs | 33 - .../ProviderServices/IRecordCreator.cs | 8 - .../ProviderServices/KeyPropertyModel.cs | 31 - .../ProviderServices/PropertyModel.cs | 162 ----- .../ProviderServices/VectorDataStrings.cs | 79 --- .../ProviderServices/VectorPropertyModel.cs | 198 ------ .../VectorPropertyModel{TInput}.cs | 70 -- .../VectorData.Abstractions/README.md | 1 + .../VectorStoreDataAttribute.cs | 41 -- .../VectorStoreKeyAttribute.cs | 46 -- .../VectorStoreVectorAttribute.cs | 68 -- .../RecordDefinition/DistanceFunction.cs | 80 --- .../RecordDefinition/IndexKind.cs | 60 -- .../VectorStoreCollectionDefinition.cs | 33 - .../VectorStoreDataProperty.cs | 40 -- .../VectorStoreKeyProperty.cs | 32 - .../RecordDefinition/VectorStoreProperty.cs | 71 -- .../VectorStoreVectorProperty.cs | 105 --- .../VectorStoreVectorProperty{TInput}.cs | 36 -- .../FilteredRecordRetrievalOptions.cs | 117 ---- .../RecordOptions/RecordRetrievalOptions.cs | 18 - .../VectorData.Abstractions/Throw.cs | 14 - .../VectorData.Abstractions.csproj | 71 -- .../VectorSearch/HybridSearchOptions.cs | 77 --- .../VectorSearch/IKeywordHybridSearchable.cs | 74 --- .../VectorSearch/IVectorSearchable.cs | 72 --- .../KeywordHybridSearchExtensions.cs | 31 - .../VectorSearch/RecordSearchOptions.cs | 70 -- .../VectorSearch/VectorSearchExtensions.cs | 31 - .../VectorSearch/VectorSearchResult.cs | 31 - .../VectorStorage/VectorStore.cs | 98 --- .../VectorStorage/VectorStoreCollection.cs | 202 ------ .../VectorStoreCollectionMetadata.cs | 25 - .../VectorStoreCollectionOptions.cs | 40 -- .../VectorStorage/VectorStoreException.cs | 58 -- .../VectorStorage/VectorStoreExtensions.cs | 31 - .../VectorStorage/VectorStoreMetadata.cs | 20 - .../VectorData.Abstractions/neticon.png | Bin 7006 -> 0 bytes .../src/VectorData/Weaviate/Weaviate.csproj | 5 +- .../VectorData.ConformanceTests.csproj | 5 +- .../CollectionModelBuilderTests.cs | 525 --------------- .../PropertyModelTests.cs | 139 ---- .../VectorData.UnitTests.csproj | 43 -- 86 files changed, 135 insertions(+), 4868 deletions(-) delete mode 100644 dotnet/MEVD.slnf create mode 100644 dotnet/MEVD.slnx delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/.editorconfig delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/AnyTagEqualToFilterClause.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/EqualToFilterClause.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/FilterClause.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/PACKAGE.md delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/Properties/AssemblyInfo.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionJsonModelBuilder.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModel.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModelBuilder.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModelBuildingOptions.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/DataPropertyModel.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/EmbeddingGenerationDispatcher.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/FilterPreprocessingOptions.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/FilterTranslatorBase.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/QueryParameterExpression.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/IRecordCreator.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/KeyPropertyModel.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/PropertyModel.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorDataStrings.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorPropertyModel.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorPropertyModel{TInput}.cs create mode 100644 dotnet/src/VectorData/VectorData.Abstractions/README.md delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreDataAttribute.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreKeyAttribute.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreVectorAttribute.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/DistanceFunction.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/IndexKind.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreCollectionDefinition.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreDataProperty.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreKeyProperty.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreProperty.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreVectorProperty.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreVectorProperty{TInput}.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordOptions/FilteredRecordRetrievalOptions.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/RecordOptions/RecordRetrievalOptions.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/Throw.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorData.Abstractions.csproj delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/HybridSearchOptions.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/IKeywordHybridSearchable.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/IVectorSearchable.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/KeywordHybridSearchExtensions.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/RecordSearchOptions.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/VectorSearchExtensions.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/VectorSearchResult.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStore.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollection.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollectionMetadata.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollectionOptions.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreException.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreExtensions.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreMetadata.cs delete mode 100644 dotnet/src/VectorData/VectorData.Abstractions/neticon.png delete mode 100644 dotnet/test/VectorData/VectorData.UnitTests/CollectionModelBuilderTests.cs delete mode 100644 dotnet/test/VectorData/VectorData.UnitTests/PropertyModelTests.cs delete mode 100644 dotnet/test/VectorData/VectorData.UnitTests/VectorData.UnitTests.csproj diff --git a/.github/workflows/dotnet-build-and-test.yml b/.github/workflows/dotnet-build-and-test.yml index 8987c2f48e42..d7277dcdb76d 100644 --- a/.github/workflows/dotnet-build-and-test.yml +++ b/.github/workflows/dotnet-build-and-test.yml @@ -81,7 +81,7 @@ jobs: - name: Build dotnet solutions shell: bash run: | - export SOLUTIONS=$(find ./dotnet/ -type f -name "*.slnx" | tr '\n' ' ') + export SOLUTIONS=$(find ./dotnet/ -type f -name "*.slnx" | grep -v "MEVD.slnx" | tr '\n' ' ') for solution in $SOLUTIONS; do dotnet build $solution -c ${{ matrix.configuration }} --warnaserror done @@ -89,7 +89,7 @@ jobs: - name: Package install check shell: bash run: | - export SOLUTIONS=$(find ./dotnet/ -type f -name "*.slnx" | tr '\n' ' ') + export SOLUTIONS=$(find ./dotnet/ -type f -name "*.slnx" | grep -v "MEVD.slnx" | tr '\n' ' ') for solution in $SOLUTIONS; do dotnet pack $solution -c ${{ matrix.configuration }} --no-build --no-restore --output ./artifacts done @@ -115,7 +115,7 @@ jobs: - name: Run Unit Tests shell: bash run: | - export UT_PROJECTS=$(find ./dotnet -type f -name "*.UnitTests.csproj" | grep -v -E "(Experimental.Orchestration.Flow.UnitTests.csproj|Experimental.Assistants.UnitTests.csproj)" | tr '\n' ' ') + export UT_PROJECTS=$(find ./dotnet -type f -name "*.UnitTests.csproj" | grep -v -E "(Experimental.Orchestration.Flow.UnitTests.csproj|Experimental.Assistants.UnitTests.csproj)" | grep -v "test/VectorData/" | tr '\n' ' ') for project in $UT_PROJECTS; do dotnet test -c ${{ matrix.configuration }} $project --no-build -v Normal --logger trx --collect:"XPlat Code Coverage" --results-directory:"TestResults/Coverage/" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.ExcludeByAttribute=GeneratedCodeAttribute,CompilerGeneratedAttribute,ExcludeFromCodeCoverageAttribute done diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 871f35361f2e..4dcc213ea1f1 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -152,6 +152,7 @@ + @@ -200,6 +201,16 @@ + + + + + + + + + + diff --git a/dotnet/MEVD.slnf b/dotnet/MEVD.slnf deleted file mode 100644 index 2a2273ba7f88..000000000000 --- a/dotnet/MEVD.slnf +++ /dev/null @@ -1,50 +0,0 @@ -{ - "solution": { - "path": "SK-dotnet.slnx", - "projects": - [ - "src/VectorData/AzureAISearch/AzureAISearch.csproj", - "src/VectorData/CosmosMongoDB/CosmosMongoDB.csproj", - "src/VectorData/CosmosNoSql/CosmosNoSql.csproj", - "src/VectorData/Chroma/Chroma.csproj", - "src/VectorData/InMemory/InMemory.csproj", - "src/VectorData/Milvus/Milvus.csproj", - "src/VectorData/MongoDB/MongoDB.csproj", - "src/VectorData/Pinecone/Pinecone.csproj", - "src/VectorData/PgVector/PgVector.csproj", - "src/VectorData/Qdrant/Qdrant.csproj", - "src/VectorData/Redis/Redis.csproj", - "src/VectorData/SqliteVec/SqliteVec.csproj", - "src/VectorData/SqlServer/SqlServer.csproj", - "src/VectorData/Weaviate/Weaviate.csproj", - - "src/VectorData/VectorData.Abstractions/VectorData.Abstractions.csproj", - - "test/VectorData/AzureAISearch.UnitTests/AzureAISearch.UnitTests.csproj", - "test/VectorData/AzureAISearch.ConformanceTests/AzureAISearch.ConformanceTests.csproj", - "test/VectorData/CosmosMongoDB.UnitTests/CosmosMongoDB.UnitTests.csproj", - "test/VectorData/CosmosMongoDB.ConformanceTests/CosmosMongoDB.ConformanceTests.csproj", - "test/VectorData/CosmosNoSql.UnitTests/CosmosNoSql.UnitTests.csproj", - "test/VectorData/CosmosNoSql.ConformanceTests/CosmosNoSql.ConformanceTests.csproj", - "test/VectorData/InMemory.UnitTests/InMemory.UnitTests.csproj", - "test/VectorData/InMemory.ConformanceTests/InMemory.ConformanceTests.csproj", - "test/VectorData/MongoDB.UnitTests/MongoDB.UnitTests.csproj", - "test/VectorData/MongoDB.ConformanceTests/MongoDB.ConformanceTests.csproj", - "test/VectorData/Pinecone.UnitTests/Pinecone.UnitTests.csproj", - "test/VectorData/Pinecone.ConformanceTests/Pinecone.ConformanceTests.csproj", - "test/VectorData/PgVector.UnitTests/PgVector.UnitTests.csproj", - "test/VectorData/PgVector.ConformanceTests/PgVector.ConformanceTests.csproj", - "test/VectorData/Qdrant.UnitTests/Qdrant.UnitTests.csproj", - "test/VectorData/Qdrant.ConformanceTests/Qdrant.ConformanceTests.csproj", - "test/VectorData/Redis.UnitTests/Redis.UnitTests.csproj", - "test/VectorData/Redis.ConformanceTests/Redis.ConformanceTests.csproj", - "test/VectorData/SqliteVec.UnitTests/SqliteVec.UnitTests.csproj", - "test/VectorData/SqliteVec.ConformanceTests/SqliteVec.ConformanceTests.csproj", - "test/VectorData/SqlServer.ConformanceTests/SqlServer.ConformanceTests.csproj", - "test/VectorData/Weaviate.UnitTests/Weaviate.UnitTests.csproj", - "test/VectorData/Weaviate.ConformanceTests/Weaviate.ConformanceTests.csproj", - - "test/VectorData/VectorData.ConformanceTests/VectorData.ConformanceTests.csproj" - ] - } -} \ No newline at end of file diff --git a/dotnet/MEVD.slnx b/dotnet/MEVD.slnx new file mode 100644 index 000000000000..9f782e02e062 --- /dev/null +++ b/dotnet/MEVD.slnx @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet/SK-dotnet.slnx b/dotnet/SK-dotnet.slnx index b2ff323d726c..966fbcb713a3 100644 --- a/dotnet/SK-dotnet.slnx +++ b/dotnet/SK-dotnet.slnx @@ -121,24 +121,6 @@ - - - - - - - - - - - - - - - - - - @@ -292,33 +274,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dotnet/samples/Concepts/Concepts.csproj b/dotnet/samples/Concepts/Concepts.csproj index 2aa832dc868c..ad6b3fe12a59 100644 --- a/dotnet/samples/Concepts/Concepts.csproj +++ b/dotnet/samples/Concepts/Concepts.csproj @@ -49,6 +49,15 @@ + + + + + + + + +
@@ -71,17 +80,6 @@ - - - - - - - - - - - diff --git a/dotnet/samples/Concepts/Memory/HuggingFace_TextEmbeddingCustomHttpHandler.cs b/dotnet/samples/Concepts/Memory/HuggingFace_TextEmbeddingCustomHttpHandler.cs index db956debca35..7e27f0a25bc3 100644 --- a/dotnet/samples/Concepts/Memory/HuggingFace_TextEmbeddingCustomHttpHandler.cs +++ b/dotnet/samples/Concepts/Memory/HuggingFace_TextEmbeddingCustomHttpHandler.cs @@ -3,7 +3,7 @@ using System.Text.Json; using Microsoft.Extensions.VectorData; using Microsoft.SemanticKernel.Connectors.HuggingFace; -using Microsoft.SemanticKernel.Connectors.SqliteVec; +using Microsoft.SemanticKernel.Connectors.InMemory; using Microsoft.SemanticKernel.Embeddings; #pragma warning disable CS8602 // Dereference of a possibly null reference. @@ -32,12 +32,11 @@ public async Task RunInferenceApiEmbeddingCustomHttpHandlerAsync() }) ); - var sqliteCollection = new SqliteCollection( - "Data Source=./../../../Sqlite.sqlite", + var inMemoryCollection = new InMemoryCollection( name: "Test", new() { EmbeddingGenerator = hf.AsEmbeddingGenerator() }); - await sqliteCollection.UpsertAsync(new Record + await inMemoryCollection.UpsertAsync(new Record { Id = "1", Text = "THIS IS A SAMPLE", diff --git a/dotnet/samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.ApiService/ChatWithAgent.ApiService.csproj b/dotnet/samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.ApiService/ChatWithAgent.ApiService.csproj index e2a7b7725f0f..09abe013258f 100644 --- a/dotnet/samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.ApiService/ChatWithAgent.ApiService.csproj +++ b/dotnet/samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.ApiService/ChatWithAgent.ApiService.csproj @@ -14,13 +14,13 @@ + - diff --git a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/MCPServer.csproj b/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/MCPServer.csproj index 042eb196402f..55b4a187a65e 100644 --- a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/MCPServer.csproj +++ b/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/MCPServer.csproj @@ -32,11 +32,11 @@ + - diff --git a/dotnet/samples/Demos/OnnxSimpleRAG/OnnxSimpleRAG.csproj b/dotnet/samples/Demos/OnnxSimpleRAG/OnnxSimpleRAG.csproj index 0f5162c8af6a..9507fd81365c 100644 --- a/dotnet/samples/Demos/OnnxSimpleRAG/OnnxSimpleRAG.csproj +++ b/dotnet/samples/Demos/OnnxSimpleRAG/OnnxSimpleRAG.csproj @@ -8,7 +8,6 @@ - @@ -17,6 +16,7 @@ + diff --git a/dotnet/samples/Demos/VectorStoreRAG/VectorStoreRAG.csproj b/dotnet/samples/Demos/VectorStoreRAG/VectorStoreRAG.csproj index 23fd288e7b97..97b89013fef8 100644 --- a/dotnet/samples/Demos/VectorStoreRAG/VectorStoreRAG.csproj +++ b/dotnet/samples/Demos/VectorStoreRAG/VectorStoreRAG.csproj @@ -15,17 +15,19 @@ + + + + + + + + + - - - - - - - diff --git a/dotnet/samples/GettingStartedWithTextSearch/GettingStartedWithTextSearch.csproj b/dotnet/samples/GettingStartedWithTextSearch/GettingStartedWithTextSearch.csproj index a4ebfd31ac80..9eab7a6c81d7 100644 --- a/dotnet/samples/GettingStartedWithTextSearch/GettingStartedWithTextSearch.csproj +++ b/dotnet/samples/GettingStartedWithTextSearch/GettingStartedWithTextSearch.csproj @@ -35,6 +35,7 @@ + @@ -42,7 +43,6 @@ - diff --git a/dotnet/samples/GettingStartedWithVectorStores/GettingStartedWithVectorStores.csproj b/dotnet/samples/GettingStartedWithVectorStores/GettingStartedWithVectorStores.csproj index 2b8c52498767..b08f7cf0ce95 100644 --- a/dotnet/samples/GettingStartedWithVectorStores/GettingStartedWithVectorStores.csproj +++ b/dotnet/samples/GettingStartedWithVectorStores/GettingStartedWithVectorStores.csproj @@ -32,16 +32,15 @@ + + + - - - - diff --git a/dotnet/src/IntegrationTests/IntegrationTests.csproj b/dotnet/src/IntegrationTests/IntegrationTests.csproj index 575a75a0f28a..7ed606ec711d 100644 --- a/dotnet/src/IntegrationTests/IntegrationTests.csproj +++ b/dotnet/src/IntegrationTests/IntegrationTests.csproj @@ -72,18 +72,6 @@ - - - - - - - - - - - - diff --git a/dotnet/src/InternalUtilities/connectors/Memory/MongoDB/MongoModelBuilder.cs b/dotnet/src/InternalUtilities/connectors/Memory/MongoDB/MongoModelBuilder.cs index 25b77f90839b..69f974cffd19 100644 --- a/dotnet/src/InternalUtilities/connectors/Memory/MongoDB/MongoModelBuilder.cs +++ b/dotnet/src/InternalUtilities/connectors/Memory/MongoDB/MongoModelBuilder.cs @@ -27,14 +27,17 @@ internal class MongoModelBuilder() : CollectionModelBuilder(s_validationOptions) UsesExternalSerializer = true, }; - protected override void ProcessProperty(PropertyInfo? clrProperty, VectorStoreProperty? definitionProperty, Type? type) + [RequiresUnreferencedCode("Traverses the CLR type's properties with reflection, so not compatible with trimming")] + protected override void ProcessTypeProperties(Type type, VectorStoreCollectionDefinition? definition) { - base.ProcessProperty(clrProperty, definitionProperty, type); + base.ProcessTypeProperties(type, definition); - if (clrProperty?.GetCustomAttribute() is { } bsonElementAttribute - && this.PropertyMap.TryGetValue(clrProperty.Name, out var property)) + foreach (var property in this.Properties) { - property.StorageName = bsonElementAttribute.ElementName; + if (property.PropertyInfo?.GetCustomAttribute() is { } bsonElementAttribute) + { + property.StorageName = bsonElementAttribute.ElementName; + } } } diff --git a/dotnet/src/SemanticKernel.Abstractions/SemanticKernel.Abstractions.csproj b/dotnet/src/SemanticKernel.Abstractions/SemanticKernel.Abstractions.csproj index 02b5009b6194..d6254b9fd51d 100644 --- a/dotnet/src/SemanticKernel.Abstractions/SemanticKernel.Abstractions.csproj +++ b/dotnet/src/SemanticKernel.Abstractions/SemanticKernel.Abstractions.csproj @@ -23,13 +23,10 @@ Semantic Kernel interfaces and abstractions. This package is automatically installed by Semantic Kernel packages if needed. - - - - + diff --git a/dotnet/src/SemanticKernel.UnitTests/SemanticKernel.UnitTests.csproj b/dotnet/src/SemanticKernel.UnitTests/SemanticKernel.UnitTests.csproj index f3e9dff4ab9c..1bc01dd5df06 100644 --- a/dotnet/src/SemanticKernel.UnitTests/SemanticKernel.UnitTests.csproj +++ b/dotnet/src/SemanticKernel.UnitTests/SemanticKernel.UnitTests.csproj @@ -25,11 +25,11 @@ +
- diff --git a/dotnet/src/VectorData/AzureAISearch/AzureAISearch.csproj b/dotnet/src/VectorData/AzureAISearch/AzureAISearch.csproj index d43078f48cee..54258372dc2a 100644 --- a/dotnet/src/VectorData/AzureAISearch/AzureAISearch.csproj +++ b/dotnet/src/VectorData/AzureAISearch/AzureAISearch.csproj @@ -26,6 +26,7 @@ + @@ -37,8 +38,4 @@ - - - - diff --git a/dotnet/src/VectorData/CosmosMongoDB/CosmosMongoDB.csproj b/dotnet/src/VectorData/CosmosMongoDB/CosmosMongoDB.csproj index 0d6bca948aaf..23f8e0cba2db 100644 --- a/dotnet/src/VectorData/CosmosMongoDB/CosmosMongoDB.csproj +++ b/dotnet/src/VectorData/CosmosMongoDB/CosmosMongoDB.csproj @@ -42,10 +42,7 @@ - - - - + diff --git a/dotnet/src/VectorData/CosmosNoSql/CosmosNoSql.csproj b/dotnet/src/VectorData/CosmosNoSql/CosmosNoSql.csproj index 2849a25f118e..05a0574e03c4 100644 --- a/dotnet/src/VectorData/CosmosNoSql/CosmosNoSql.csproj +++ b/dotnet/src/VectorData/CosmosNoSql/CosmosNoSql.csproj @@ -32,13 +32,10 @@ + - - - - diff --git a/dotnet/src/VectorData/CosmosNoSql/CosmosNoSqlMapper.cs b/dotnet/src/VectorData/CosmosNoSql/CosmosNoSqlMapper.cs index 6f0ffdaea91b..8a8644b80198 100644 --- a/dotnet/src/VectorData/CosmosNoSql/CosmosNoSqlMapper.cs +++ b/dotnet/src/VectorData/CosmosNoSql/CosmosNoSqlMapper.cs @@ -41,8 +41,8 @@ public JsonObject MapFromDataToStorageModel(TRecord dataModel, int recordIndex, // The key property in Azure CosmosDB NoSQL is always named 'id'. // But the external JSON serializer used just above isn't aware of that, and will produce a JSON object with another name, taking into - // account e.g. naming policies. SerializedKeyName gets populated in the model builder - containing that name - once VectorStoreModelBuildingOptions.ReservedKeyPropertyName is set - RenameJsonProperty(jsonObject, this._keyProperty.SerializedKeyName!, CosmosNoSqlConstants.ReservedKeyPropertyName); + // account e.g. naming policies. TemporaryStorageName gets populated in the model builder - containing that name - once VectorStoreModelBuildingOptions.ReservedKeyPropertyName is set + RenameJsonProperty(jsonObject, this._keyProperty.TemporaryStorageName!, CosmosNoSqlConstants.ReservedKeyPropertyName); // Go over the vector properties; inject any generated embeddings to overwrite the JSON serialized above. // Also, for Embedding properties we also need to overwrite with a simple array (since Embedding gets serialized as a complex object). @@ -116,7 +116,7 @@ public JsonObject MapFromDataToStorageModel(TRecord dataModel, int recordIndex, public TRecord MapFromStorageToDataModel(JsonObject storageModel, bool includeVectors) { // See above comment. - RenameJsonProperty(storageModel, CosmosNoSqlConstants.ReservedKeyPropertyName, this._keyProperty.SerializedKeyName!); + RenameJsonProperty(storageModel, CosmosNoSqlConstants.ReservedKeyPropertyName, this._keyProperty.TemporaryStorageName!); foreach (var vectorProperty in this._model.VectorProperties) { diff --git a/dotnet/src/VectorData/InMemory/InMemory.csproj b/dotnet/src/VectorData/InMemory/InMemory.csproj index aa8cbb340f55..dcd70c709db2 100644 --- a/dotnet/src/VectorData/InMemory/InMemory.csproj +++ b/dotnet/src/VectorData/InMemory/InMemory.csproj @@ -34,11 +34,8 @@ + - - - - diff --git a/dotnet/src/VectorData/MongoDB/MongoDB.csproj b/dotnet/src/VectorData/MongoDB/MongoDB.csproj index 4bc2786c1161..6196ba1c4fee 100644 --- a/dotnet/src/VectorData/MongoDB/MongoDB.csproj +++ b/dotnet/src/VectorData/MongoDB/MongoDB.csproj @@ -37,10 +37,7 @@ - - - - + diff --git a/dotnet/src/VectorData/PgVector/PgVector.csproj b/dotnet/src/VectorData/PgVector/PgVector.csproj index b171819ce395..8b33c42e99f6 100644 --- a/dotnet/src/VectorData/PgVector/PgVector.csproj +++ b/dotnet/src/VectorData/PgVector/PgVector.csproj @@ -32,16 +32,13 @@ + 8.0.7 - - - - diff --git a/dotnet/src/VectorData/Pinecone/Pinecone.csproj b/dotnet/src/VectorData/Pinecone/Pinecone.csproj index d5c5847327a2..f065a03f1462 100644 --- a/dotnet/src/VectorData/Pinecone/Pinecone.csproj +++ b/dotnet/src/VectorData/Pinecone/Pinecone.csproj @@ -28,6 +28,7 @@ + @@ -39,8 +40,4 @@ - - - - diff --git a/dotnet/src/VectorData/Qdrant/Qdrant.csproj b/dotnet/src/VectorData/Qdrant/Qdrant.csproj index 86e2503a2056..248a0a2c0b22 100644 --- a/dotnet/src/VectorData/Qdrant/Qdrant.csproj +++ b/dotnet/src/VectorData/Qdrant/Qdrant.csproj @@ -27,6 +27,7 @@ + @@ -40,8 +41,4 @@ - - - - \ No newline at end of file diff --git a/dotnet/src/VectorData/Redis/Redis.csproj b/dotnet/src/VectorData/Redis/Redis.csproj index 41e673ad61a5..d463c09b373d 100644 --- a/dotnet/src/VectorData/Redis/Redis.csproj +++ b/dotnet/src/VectorData/Redis/Redis.csproj @@ -26,6 +26,7 @@ + @@ -33,8 +34,4 @@ - - - - \ No newline at end of file diff --git a/dotnet/src/VectorData/SqlServer/SqlServer.csproj b/dotnet/src/VectorData/SqlServer/SqlServer.csproj index 7896ffcb03f5..c6075692aa84 100644 --- a/dotnet/src/VectorData/SqlServer/SqlServer.csproj +++ b/dotnet/src/VectorData/SqlServer/SqlServer.csproj @@ -30,13 +30,10 @@ + - - - - diff --git a/dotnet/src/VectorData/SqliteVec/SqliteVec.csproj b/dotnet/src/VectorData/SqliteVec/SqliteVec.csproj index ab5a3f4798dd..d3e2062b157b 100644 --- a/dotnet/src/VectorData/SqliteVec/SqliteVec.csproj +++ b/dotnet/src/VectorData/SqliteVec/SqliteVec.csproj @@ -31,16 +31,13 @@ + - - - - diff --git a/dotnet/src/VectorData/VectorData.Abstractions/.editorconfig b/dotnet/src/VectorData/VectorData.Abstractions/.editorconfig deleted file mode 100644 index acb2cb62caf4..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/.editorconfig +++ /dev/null @@ -1,3 +0,0 @@ -# Suppress missing documentation warnings for generated code (strings) -[*.Designer.cs] -dotnet_diagnostic.CS1591.severity = none diff --git a/dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/AnyTagEqualToFilterClause.cs b/dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/AnyTagEqualToFilterClause.cs deleted file mode 100644 index c9419d087732..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/AnyTagEqualToFilterClause.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Represents a filter clause that filters by checking if a field consisting of a list of values contains a specific value. -/// -[Obsolete("Use LINQ expressions via VectorSearchOptions.Filter instead. This type will be removed in a future version.")] -public sealed class AnyTagEqualToFilterClause : FilterClause -{ - /// - /// Initializes a new instance of the class. - /// - /// The name of the field with the list of values. - /// The value that the list should contain. - public AnyTagEqualToFilterClause(string fieldName, string value) - { - this.FieldName = fieldName; - this.Value = value; - } - - /// - /// Gets the name of the field with the list of values. - /// - public string FieldName { get; private set; } - - /// - /// Gets the value that the list should contain. - /// - public string Value { get; private set; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/EqualToFilterClause.cs b/dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/EqualToFilterClause.cs deleted file mode 100644 index 03fc678abc8b..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/EqualToFilterClause.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Represents a filter clause that filters using equality of a field value. -/// -[Obsolete("Use LINQ expressions via VectorSearchOptions.Filter instead. This type will be removed in a future version.")] -public sealed class EqualToFilterClause : FilterClause -{ - /// - /// Initializes a new instance of the class. - /// - /// Field name. - /// Field value. - public EqualToFilterClause(string fieldName, object value) - { - this.FieldName = fieldName; - this.Value = value; - } - - /// - /// Gets the field name to match. - /// - public string FieldName { get; private set; } - - /// - /// Gets the field value to match. - /// - public object Value { get; private set; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/FilterClause.cs b/dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/FilterClause.cs deleted file mode 100644 index 97c8869a27ea..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/FilterClauses/FilterClause.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines a base class for filter clauses. -/// -/// -/// A is used to request that the underlying search service should -/// filter search results based on the specified criteria. -/// -[Obsolete("Use LINQ expressions via VectorSearchOptions.Filter instead. This type will be removed in a future version.")] -public abstract class FilterClause -{ - /// - /// Initializes a new instance of the class. - /// - protected FilterClause() - { - } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/PACKAGE.md b/dotnet/src/VectorData/VectorData.Abstractions/PACKAGE.md deleted file mode 100644 index 948b8527c6a8..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/PACKAGE.md +++ /dev/null @@ -1,51 +0,0 @@ -## About - -Contains abstractions for accessing Vector Databases and Vector Indexes. - -## Key Features - -- Base abstract classes and interfaces for Vector Database implementation. Vector Database implementations are provided separately in other packages, for example `Microsoft.SemanticKernel.Connectors.AzureAISearch`. -- Abstractions include: - - Creating, listing and deleting collections with custom schema support. - - Creating, retrieving, updating and deleting records. - - Similarty search using vector embeddings. - - Search using filters. - - Hybrid search combining vector similarity and keyword search. - - Built-in embedding generation using `Microsoft.Extensions.AI`. - -## How to Use - -This package is typically used with an implementation of the vector database abstractions such as `Microsoft.SemanticKernel.Connectors.AzureAISearch`. - -## Main Types - -The main types provided by this library are: - -- [Microsoft.Extensions.VectorData.VectorStore](https://learn.microsoft.com/dotnet/api/microsoft.extensions.vectordata.vectorstore) -- [Microsoft.Extensions.VectorData.VectorStoreCollection](https://learn.microsoft.com/dotnet/api/microsoft.extensions.vectordata.vectorstorecollection-2) - -## Additional Documentation - -- [Conceptual documentation](https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors) - -## Related Packages - -Vector Database implementations: - -- [Microsoft.SemanticKernel.Connectors.AzureAISearch](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.AzureAISearch) -- [Microsoft.SemanticKernel.Connectors.CosmosMongoDB](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.CosmosMongoDB) -- [Microsoft.SemanticKernel.Connectors.CosmosNoSQL](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.CosmosNoSQL) -- [Elastic.SemanticKernel.Connectors.Elasticsearch](https://www.nuget.org/packages/Elastic.SemanticKernel.Connectors.Elasticsearch) -- [Microsoft.SemanticKernel.Connectors.InMemory](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.InMemory) -- [Microsoft.SemanticKernel.Connectors.MongoDB](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.MongoDB) -- [Microsoft.SemanticKernel.Connectors.PgVector](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.PgVector) -- [Microsoft.SemanticKernel.Connectors.Pinecone](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.Pinecone) -- [Microsoft.SemanticKernel.Connectors.Qdrant](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.Qdrant) -- [Microsoft.SemanticKernel.Connectors.Redis](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.Redis) -- [Microsoft.SemanticKernel.Connectors.SqliteVec](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.SqliteVec) -- [Microsoft.SemanticKernel.Connectors.SqlServer](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.SqlServer) -- [Microsoft.SemanticKernel.Connectors.Weaviate](https://www.nuget.org/packages/Microsoft.SemanticKernel.Connectors.Weaviate) - -## Feedback & Contributing - -Microsoft.Extensions.VectorData.Abstractions is released as open source under the [MIT license](https://licenses.nuget.org/MIT). Bug reports and contributions are welcome at [the GitHub repository](https://github.com/microsoft/semantic-kernel). diff --git a/dotnet/src/VectorData/VectorData.Abstractions/Properties/AssemblyInfo.cs b/dotnet/src/VectorData/VectorData.Abstractions/Properties/AssemblyInfo.cs deleted file mode 100644 index 09647faa37af..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -[assembly: System.Resources.NeutralResourcesLanguage("en-US")] diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionJsonModelBuilder.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionJsonModelBuilder.cs deleted file mode 100644 index 90a2db9433f3..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionJsonModelBuilder.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Reflection; -using System.Text.Json; -using System.Text.Json.Serialization; -using Microsoft.Extensions.AI; - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -/// -/// Represents a model builder that performs logic specific to connectors that use System.Text.Json for serialization. -/// This is an internal support type meant for use by connectors only and not by applications. -/// -[Experimental("MEVD9001")] -public abstract class CollectionJsonModelBuilder : CollectionModelBuilder -{ - private JsonSerializerOptions? _jsonSerializerOptions; - - /// - /// Constructs a new . - /// - protected CollectionJsonModelBuilder(CollectionModelBuildingOptions options) - : base(options) - { - } - - /// - /// Builds and returns a from the given and . - /// - [RequiresDynamicCode("This model building variant is not compatible with NativeAOT. See BuildDynamic() for dynamic mapping, and a third variant accepting source-generated delegates will be introduced in the future.")] - [RequiresUnreferencedCode("This model building variant is not compatible with trimming. See BuildDynamic() for dynamic mapping, and a third variant accepting source-generated delegates will be introduced in the future.")] - public virtual CollectionModel Build( - Type recordType, - Type keyType, - VectorStoreCollectionDefinition? definition, - IEmbeddingGenerator? defaultEmbeddingGenerator, - JsonSerializerOptions jsonSerializerOptions) - { - this._jsonSerializerOptions = jsonSerializerOptions; - - return this.Build(recordType, keyType, definition, defaultEmbeddingGenerator); - } - - /// - /// Builds and returns a for dynamic mapping scenarios from the given . - /// - public virtual CollectionModel BuildDynamic( - VectorStoreCollectionDefinition definition, - IEmbeddingGenerator? defaultEmbeddingGenerator, - JsonSerializerOptions jsonSerializerOptions) - { - this._jsonSerializerOptions = jsonSerializerOptions; - - return this.BuildDynamic(definition, defaultEmbeddingGenerator); - } - - /// - protected override void Customize() - { - // This mimics the naming behavior of the System.Text.Json serializer, which we use for serialization/deserialization. - // The property storage names in the model must in sync with the serializer configuration, since the model is used e.g. for filtering - // even if serialization/deserialization doesn't use the model. - var namingPolicy = this._jsonSerializerOptions?.PropertyNamingPolicy; - - foreach (var property in this.Properties) - { - var keyPropertyWithReservedName = this.Options.ReservedKeyStorageName is not null && property is KeyPropertyModel; - string storageName; - - if (property.PropertyInfo?.GetCustomAttribute() is { } jsonPropertyNameAttribute) - { - if (keyPropertyWithReservedName && jsonPropertyNameAttribute.Name != this.Options.ReservedKeyStorageName) - { - throw new InvalidOperationException($"The key property for your connector must always have the reserved name '{this.Options.ReservedKeyStorageName}' and cannot be changed."); - } - - storageName = jsonPropertyNameAttribute.Name; - } - else if (namingPolicy is not null) - { - storageName = namingPolicy.ConvertName(property.ModelName); - } - else - { - storageName = property.ModelName; - } - - if (keyPropertyWithReservedName) - { - // Some providers (Weaviate, Cosmos NoSQL) have a fixed, reserved storage name for keys (id), and at the same time use an external - // JSON serializer to serialize the entire user POCO. Since the serializer is unaware of the reserved storage name, it will produce - // a storage name as usual, based on the .NET property's name, possibly with a naming policy applied to it. The connector then needs - // to look that up and replace with the reserved name. - ((KeyPropertyModel)property).SerializedKeyName = storageName; - } - else - { - property.StorageName = storageName; - } - } - } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModel.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModel.cs deleted file mode 100644 index 7f837038dfa6..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModel.cs +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using System.Runtime.CompilerServices; - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -/// -/// Represents a record in a vector store collection. -/// This is an internal support type meant for use by connectors only and not by applications. -/// -[Experimental("MEVD9001")] -public sealed class CollectionModel -{ - private readonly Type _recordType; - private readonly Func _recordFactory; - - private KeyPropertyModel? _singleKeyProperty; - private VectorPropertyModel? _singleVectorProperty; - private DataPropertyModel? _singleFullTextSearchProperty; - - /// - /// Gets the key properties of the record. - /// - public IReadOnlyList KeyProperties { get; } - - /// - /// Gets the data properties of the record. - /// - public IReadOnlyList DataProperties { get; } - - /// - /// Gets the vector properties of the record. - /// - public IReadOnlyList VectorProperties { get; } - - /// - /// Gets all properties of the record, of all types. - /// - public IReadOnlyList Properties { get; } - - /// - /// Gets all properties of the record, of all types, indexed by their model name. - /// - public IReadOnlyDictionary PropertyMap { get; } - - /// - /// Gets a value that indicates whether any of the vector properties in the model require embedding generation. - /// - public bool EmbeddingGenerationRequired { get; } - - internal CollectionModel( - Type recordType, - Func recordFactory, - IReadOnlyList keyProperties, - IReadOnlyList dataProperties, - IReadOnlyList vectorProperties, - IReadOnlyDictionary propertyMap) - { - this._recordType = recordType; - this._recordFactory = recordFactory; - - this.KeyProperties = keyProperties; - this.DataProperties = dataProperties; - this.VectorProperties = vectorProperties; - this.PropertyMap = propertyMap; - this.Properties = propertyMap.Values.ToList(); - - this.EmbeddingGenerationRequired = vectorProperties.Any(p => p.EmbeddingType != p.Type); - } - - /// - /// Returns the single key property in the model, and throws if there are multiple key properties. - /// - public KeyPropertyModel KeyProperty => this._singleKeyProperty ??= this.KeyProperties.Single(); - - /// - /// Returns the single vector property in the model, and throws if there are multiple vector properties. - /// Suitable for connectors where validation is in place for single vectors only (). - /// - public VectorPropertyModel VectorProperty => this._singleVectorProperty ??= this.VectorProperties.Single(); - - /// - /// Instantiates a new record of the specified type. - /// - // TODO: the pattern of first instantiating via parameterless constructor and then populating the properties isn't compatible - // with read-only types, where properties have no setters. Supporting those would be problematic given the that different - // connectors have completely different representations of the data coming back from the database, and which needs to be - // populated. - public TRecord CreateRecord() - { - Debug.Assert(typeof(TRecord) == this._recordType, "Type mismatch between record type and model type."); - - return (TRecord)this._recordFactory(); - } - - /// - /// Gets the vector property with the provided name if a name is provided, and falls back - /// to a vector property in the schema if not. - /// - /// The search options, which defines the vector property name. - /// The provided property name is not a valid text data property name.ORNo name was provided and there's more than one vector property. - public VectorPropertyModel GetVectorPropertyOrSingle(VectorSearchOptions searchOptions) - { - if (searchOptions.VectorProperty is not null) - { - return this.GetMatchingProperty(searchOptions.VectorProperty, data: false); - } - - // If vector property name is not provided, check if there is a single vector property, or throw if there are no vectors or more than one. - // TODO: Make a single switch expression + coalesce from the following - dotnet format fails on it for now - if (this._singleVectorProperty is null) - { - switch (this.VectorProperties) - { - case [var singleProperty]: - this._singleVectorProperty = singleProperty; - break; - - case { Count: 0 }: - throw new InvalidOperationException($"The '{this._recordType.Name}' type does not have any vector properties."); - - default: - throw new InvalidOperationException($"The '{this._recordType.Name}' type has multiple vector properties, please specify your chosen property via options."); - } - } - - return this._singleVectorProperty; - } - - /// - /// Gets the text data property with the provided name that has full text search indexing enabled, or falls back - /// to a text data property in the schema if no name is provided. - /// - /// The full text search property selector. - /// The provided property name is not a valid text data property name.ORNo name was provided and there's more than one text data property with full text search indexing enabled. - public DataPropertyModel GetFullTextDataPropertyOrSingle(Expression>? expression) - { - if (expression is not null) - { - var property = this.GetMatchingProperty(expression, data: true); - - return property.IsFullTextIndexed - ? property - : throw new InvalidOperationException($"The property '{property.ModelName}' on '{this._recordType.Name}' must have full text search indexing enabled."); - } - - if (this._singleFullTextSearchProperty is null) - { - // If text data property name is not provided, check if a single full text indexed text property exists or throw otherwise. - var fullTextStringProperties = this.DataProperties - .Where(l => l.Type == typeof(string) && l.IsFullTextIndexed) - .ToList(); - - // If text data property name is not provided, check if a single full text indexed text property exists or throw otherwise. - switch (fullTextStringProperties) - { - // If there is a single property, use it. - // If there are no properties, throw. - // If there are multiple properties, throw. - case [var singleProperty]: - this._singleFullTextSearchProperty = singleProperty; - break; - - case { Count: 0 }: - throw new InvalidOperationException($"The '{this._recordType.Name}' type does not have any text data properties that have full text indexing enabled."); - - default: - throw new InvalidOperationException($"The '{this._recordType.Name}' type has multiple text data properties that have full text indexing enabled, please specify your chosen property via options."); - } - } - - return this._singleFullTextSearchProperty; - } - - /// - /// Gets the data or key property selected by the provided expression. - /// - /// The property selector. - /// The provided property name is not a valid data or key property name. - public PropertyModel GetDataOrKeyProperty(Expression> expression) - => this.GetMatchingProperty(expression, data: true); - - private TProperty GetMatchingProperty(Expression> expression, bool data) - where TProperty : PropertyModel - { - var node = expression.Body; - - // First, unwrap any object convert node: r => (object)r.PropertyName becomes r => r.PropertyName - if (expression.Body is UnaryExpression { NodeType: ExpressionType.Convert } convert - && convert.Type == typeof(object)) - { - node = convert.Operand; - } - - var propertyName = node switch - { - // Simple member expression over the lambda parameter (r => r.PropertyName) - MemberExpression { Member: PropertyInfo clrProperty } member when member.Expression == expression.Parameters[0] - => clrProperty.Name, - - // Dictionary access over the lambda parameter, in dynamic mapping (r => r["PropertyName"]) - MethodCallExpression { Method.Name: "get_Item", Arguments: [var keyExpression] } methodCall - => keyExpression switch - { - ConstantExpression { Value: string text } => text, - MemberExpression field when TryGetCapturedValue(field, out object? capturedValue) && capturedValue is string text => text, - _ => throw new InvalidOperationException("Invalid dictionary key expression") - }, - - _ => throw new InvalidOperationException("Property selector lambda is invalid") - }; - - if (!this.PropertyMap.TryGetValue(propertyName, out var property)) - { - throw new InvalidOperationException($"Property '{propertyName}' could not be found."); - } - - return property is TProperty typedProperty - ? typedProperty - : throw new InvalidOperationException($"Property '{propertyName}' isn't of type '{typeof(TProperty).Name}'."); - - static bool TryGetCapturedValue(Expression expression, out object? capturedValue) - { - if (expression is MemberExpression { Expression: ConstantExpression constant, Member: FieldInfo fieldInfo } - && constant.Type.Attributes.HasFlag(TypeAttributes.NestedPrivate) - && Attribute.IsDefined(constant.Type, typeof(CompilerGeneratedAttribute), inherit: true)) - { - capturedValue = fieldInfo.GetValue(constant.Value); - return true; - } - - capturedValue = null; - return false; - } - } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModelBuilder.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModelBuilder.cs deleted file mode 100644 index 3b6f6ccc6b51..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModelBuilder.cs +++ /dev/null @@ -1,609 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Reflection; -using Microsoft.Extensions.AI; - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -/// -/// Represents a builder for a . -/// This is an internal support type meant for use by connectors only and not by applications. -/// -/// This class is single-use only, and not thread-safe. -[Experimental("MEVD9001")] -public abstract class CollectionModelBuilder -{ - /// - /// Gets the options for building the model. - /// - protected CollectionModelBuildingOptions Options { get; } - - /// - /// Gets the key properties of the record. - /// - protected List KeyProperties { get; } = []; - - /// - /// Gets the data properties of the record. - /// - protected List DataProperties { get; } = []; - - /// - /// Gets the vector properties of the record. - /// - protected List VectorProperties { get; } = []; - - /// - /// Gets all properties of the record, of all types. - /// - protected IEnumerable Properties => this.PropertyMap.Values; - - /// - /// Gets all properties of the record, of all types, indexed by their model name. - /// - protected Dictionary PropertyMap { get; } = []; - - /// - /// Gets the default embedding generator to use for vector properties, when none is specified at the property or collection level. - /// - protected IEmbeddingGenerator? DefaultEmbeddingGenerator { get; private set; } - - /// - /// Gets the collection's generic key type parameter (TKey), if provided. - /// Used by to validate that TKey corresponds to the key property type on the model. - /// - protected Type? KeyType { get; private set; } - - /// - /// Constructs a new . - /// - protected CollectionModelBuilder(CollectionModelBuildingOptions options) - => this.Options = options; - - /// - /// Builds and returns an from the given and . - /// - /// The CLR type of the record. - /// The collection's generic key type parameter (TKey), used to validate correspondence with the key property type. - /// An optional record definition that overrides attribute-based configuration. - /// An optional default embedding generator for vector properties. - [RequiresDynamicCode("This model building variant is not compatible with NativeAOT. See BuildDynamic() for dynamic mapping, and a third variant accepting source-generated delegates will be introduced in the future.")] - [RequiresUnreferencedCode("This model building variant is not compatible with trimming. See BuildDynamic() for dynamic mapping, and a third variant accepting source-generated delegates will be introduced in the future.")] - public virtual CollectionModel Build(Type recordType, Type keyType, VectorStoreCollectionDefinition? definition, IEmbeddingGenerator? defaultEmbeddingGenerator) - { - this.KeyType = keyType; - - if (recordType == typeof(Dictionary)) - { - throw new ArgumentException("Dynamic mapping with Dictionary requires calling BuildDynamic()."); - } - - this.DefaultEmbeddingGenerator = definition?.EmbeddingGenerator ?? defaultEmbeddingGenerator; - - // Build a lookup of definition properties by name for matching with CLR properties. - Dictionary? definitionByName = null; - if (definition is not null) - { - definitionByName = []; - foreach (var p in definition.Properties) - { - definitionByName[p.Name] = p; - } - } - - // Process CLR properties, matching to definition properties where available. - // TODO: This traverses the CLR type's properties, making it incompatible with trimming (and NativeAOT). - // TODO: We could put [DynamicallyAccessedMembers] to preserve all properties, but that approach wouldn't - // TODO: work with hierarchical data models (#10957). - foreach (var clrProperty in recordType.GetProperties()) - { - VectorStoreProperty? definitionProperty = null; - _ = definitionByName?.TryGetValue(clrProperty.Name, out definitionProperty); - - this.ProcessProperty(clrProperty, definitionProperty, recordType); - } - - // Go over the properties, configure POCO accessors and validate type compatibility. - foreach (var property in this.Properties) - { - var clrProperty = recordType.GetProperty(property.ModelName) - ?? throw new InvalidOperationException($"Property '{property.ModelName}' not found on CLR type '{recordType.FullName}'."); - - var clrPropertyType = clrProperty.PropertyType; - if ((Nullable.GetUnderlyingType(clrPropertyType) ?? clrPropertyType) != (Nullable.GetUnderlyingType(property.Type) ?? property.Type)) - { - throw new InvalidOperationException( - $"Property '{property.ModelName}' has a different CLR type in the record definition ('{property.Type.Name}') and on the .NET property ('{clrProperty.PropertyType}')."); - } - - property.ConfigurePocoAccessors(clrProperty); - } - - this.Customize(); - this.Validate(recordType, definition); - - // Extra validation for non-dynamic mapping scenarios: ensure the type has a parameterless constructor. - if (!this.Options.UsesExternalSerializer && recordType.GetConstructor(Type.EmptyTypes) is null) - { - throw new NotSupportedException($"Type '{recordType.Name}' must have a parameterless constructor."); - } - - return new(recordType, () => Activator.CreateInstance(recordType)!, this.KeyProperties, this.DataProperties, this.VectorProperties, this.PropertyMap); - } - - /// - /// Builds and returns an for dynamic mapping scenarios from the given . - /// - /// The record definition describing the collection's schema. - /// An optional default embedding generator for vector properties. - public virtual CollectionModel BuildDynamic(VectorStoreCollectionDefinition definition, IEmbeddingGenerator? defaultEmbeddingGenerator) - { - if (definition is null) - { - throw new ArgumentException("Vector store record definition must be provided for dynamic mapping."); - } - - this.DefaultEmbeddingGenerator = defaultEmbeddingGenerator; - - foreach (var defProp in definition.Properties) - { - this.ProcessProperty(clrProperty: null, defProp, type: null); - } - - this.Customize(); - this.Validate(type: null, definition); - - foreach (var property in this.Properties) - { - property.ConfigureDynamicAccessors(); - } - - return new(typeof(Dictionary), static () => new Dictionary(), this.KeyProperties, this.DataProperties, this.VectorProperties, this.PropertyMap); - } - - /// - /// As part of building the model, this method processes a single property, accepting both a CLR - /// (from which attributes are read) and a from the user-provided record definition. - /// Either may be , but not both. - /// When both are provided, the record definition values override attribute-configured values. - /// - protected virtual void ProcessProperty(PropertyInfo? clrProperty, VectorStoreProperty? definitionProperty, Type? type) - { - Debug.Assert(clrProperty is not null || definitionProperty is not null); - - VectorStoreKeyAttribute? keyAttribute = null; - VectorStoreDataAttribute? dataAttribute = null; - VectorStoreVectorAttribute? vectorAttribute = null; - - if (clrProperty is not null) - { - // Read attributes from CLR property. - keyAttribute = clrProperty.GetCustomAttribute(); - dataAttribute = clrProperty.GetCustomAttribute(); - vectorAttribute = clrProperty.GetCustomAttribute(); - - // Validate that at most one mapping attribute is present. - if ((keyAttribute is not null ? 1 : 0) + (dataAttribute is not null ? 1 : 0) + (vectorAttribute is not null ? 1 : 0) > 1) - { - throw new InvalidOperationException( - $"Property '{type!.Name}.{clrProperty.Name}' has multiple of {nameof(VectorStoreKeyAttribute)}, {nameof(VectorStoreDataAttribute)} or {nameof(VectorStoreVectorAttribute)}. Only one of these attributes can be specified on a property."); - } - - // If no mapping attribute and no definition, skip this property. - if (keyAttribute is null && dataAttribute is null && vectorAttribute is null && definitionProperty is null) - { - return; - } - - // Validate kind compatibility between attribute and definition. - if (definitionProperty is not null - && ((keyAttribute is not null && definitionProperty is not VectorStoreKeyProperty) - || (dataAttribute is not null && definitionProperty is not VectorStoreDataProperty) - || (vectorAttribute is not null && definitionProperty is not VectorStoreVectorProperty))) - { - string definitionKind = definitionProperty switch - { - VectorStoreKeyProperty => "key", - VectorStoreDataProperty => "data", - VectorStoreVectorProperty => "vector", - _ => throw new ArgumentException($"Unknown type '{definitionProperty.GetType().FullName}' in vector store record definition.") - }; - - throw new InvalidOperationException( - $"Property '{clrProperty.Name}' is present in the {nameof(VectorStoreCollectionDefinition)} as a {definitionKind} property, but the .NET property on type '{type?.Name}' has an incompatible attribute."); - } - } - - string propertyName = clrProperty?.Name ?? definitionProperty!.Name; - Type propertyType = clrProperty?.PropertyType - ?? definitionProperty!.Type - ?? throw new InvalidOperationException(VectorDataStrings.MissingTypeOnPropertyDefinition(definitionProperty!)); - - PropertyModel property; - string? attributeStorageName = null; - - if (keyAttribute is not null || definitionProperty is VectorStoreKeyProperty) - { - var keyProperty = new KeyPropertyModel(propertyName, propertyType); - - if (keyAttribute is not null) - { - keyProperty.IsAutoGenerated = keyAttribute.IsAutoGeneratedNullable ?? this.SupportsKeyAutoGeneration(keyProperty.Type); - attributeStorageName = keyAttribute.StorageName; - } - - // Definition values override attribute values. - if (definitionProperty is VectorStoreKeyProperty defKey) - { - keyProperty.IsAutoGenerated = defKey.IsAutoGenerated ?? this.SupportsKeyAutoGeneration(keyProperty.Type); - } - - this.KeyProperties.Add(keyProperty); - property = keyProperty; - } - else if (dataAttribute is not null || definitionProperty is VectorStoreDataProperty) - { - var dataProperty = new DataPropertyModel(propertyName, propertyType); - - if (dataAttribute is not null) - { - dataProperty.IsIndexed = dataAttribute.IsIndexed; - dataProperty.IsFullTextIndexed = dataAttribute.IsFullTextIndexed; - attributeStorageName = dataAttribute.StorageName; - } - - // Definition values override attribute values. - if (definitionProperty is VectorStoreDataProperty defData) - { - dataProperty.IsIndexed = defData.IsIndexed; - dataProperty.IsFullTextIndexed = defData.IsFullTextIndexed; - } - - this.DataProperties.Add(dataProperty); - property = dataProperty; - } - else if (vectorAttribute is not null || definitionProperty is VectorStoreVectorProperty) - { - // If a definition exists, create via the definition to preserve generic type info (VectorStoreVectorProperty). - var vectorProperty = definitionProperty is VectorStoreVectorProperty defVec - ? defVec.CreatePropertyModel() - : new VectorPropertyModel(propertyName, propertyType); - - if (vectorAttribute is not null) - { - vectorProperty.Dimensions = vectorAttribute.Dimensions; - vectorProperty.IndexKind = vectorAttribute.IndexKind; - vectorProperty.DistanceFunction = vectorAttribute.DistanceFunction; - attributeStorageName = vectorAttribute.StorageName; - } - - // Definition values override attribute values. - if (definitionProperty is VectorStoreVectorProperty defVectorProp) - { - vectorProperty.Dimensions = defVectorProp.Dimensions; - - if (defVectorProp.IndexKind is not null) - { - vectorProperty.IndexKind = defVectorProp.IndexKind; - } - - if (defVectorProp.DistanceFunction is not null) - { - vectorProperty.DistanceFunction = defVectorProp.DistanceFunction; - } - } - - this.ConfigureVectorPropertyEmbedding( - vectorProperty, - (definitionProperty as VectorStoreVectorProperty)?.EmbeddingGenerator ?? this.DefaultEmbeddingGenerator, - (definitionProperty as VectorStoreVectorProperty)?.EmbeddingType); - - this.VectorProperties.Add(vectorProperty); - property = vectorProperty; - } - else - { - throw new UnreachableException(); - } - - // Apply storage name: attribute first, then definition (which takes precedence). - this.SetPropertyStorageName(property, attributeStorageName, type); - if (definitionProperty is not null) - { - this.SetPropertyStorageName(property, definitionProperty.StorageName, type); - } - - if (definitionProperty?.ProviderAnnotations is not null) - { - property.ProviderAnnotations = new Dictionary(definitionProperty.ProviderAnnotations); - } - - if (clrProperty is not null) - { - property.PropertyInfo = clrProperty; - } - - this.PropertyMap.Add(propertyName, property); - } - - private void SetPropertyStorageName(PropertyModel property, string? storageName, Type? type) - { - if (property is KeyPropertyModel && this.Options.ReservedKeyStorageName is not null) - { - // If we have ReservedKeyStorageName, there can only be a single key property (validated in the constructor) - property.StorageName = this.Options.ReservedKeyStorageName; - return; - } - - if (storageName is null) - { - return; - } - - // If a custom serializer is used (e.g. JsonSerializer), it would ignore our own attributes/config, and - // our model needs to be in sync with the serializer's behavior (for e.g. storage names in filters). - // So we ignore the config here as well. - // TODO: Consider throwing here instead of ignoring - if (this.Options.UsesExternalSerializer && type != null) - { - return; - } - - property.StorageName = storageName; - } - - /// - /// Gets the embedding types supported by this provider, in priority order. - /// The first type whose embedding generator is compatible with the input type will be used. - /// - /// - /// Override this property in connectors that support additional embedding types beyond of . - /// - protected virtual IReadOnlyList EmbeddingGenerationDispatchers { get; } - = [EmbeddingGenerationDispatcher.Create>()]; - - /// - /// Attempts to resolve the embedding type for the given vector property, iterating over in priority order. - /// - private (Type? EmbeddingType, EmbeddingGenerationDispatcher? Handler) ResolveEmbeddingType( - VectorPropertyModel vectorProperty, - IEmbeddingGenerator embeddingGenerator, - Type? userRequestedEmbeddingType) - { - foreach (var supported in this.EmbeddingGenerationDispatchers) - { - if (supported.ResolveEmbeddingType(vectorProperty, embeddingGenerator, userRequestedEmbeddingType) is { } resolved) - { - return (resolved, supported); - } - } - - return (null, null); - } - - /// - /// Resolves the embedding handler for a native vector property type, where embedding generation is only needed for search. - /// Since the property type is already a valid native type, we only check if the generator can produce the - /// embedding output type (regardless of input type, which is only known at search time). - /// - private EmbeddingGenerationDispatcher? ResolveSearchOnlyEmbeddingHandler(VectorPropertyModel vectorProperty, IEmbeddingGenerator embeddingGenerator) - { - foreach (var supported in this.EmbeddingGenerationDispatchers) - { - if (supported.CanGenerateEmbedding(vectorProperty, embeddingGenerator)) - { - return supported; - } - } - - return null; - } - - /// - /// Configures embedding generation for a vector property. Sets the embedding generator, resolves the embedding type, - /// and assigns the appropriate . - /// - /// - /// If the property's type is natively supported (e.g. of ), the embedding type - /// is set to the property's type; if a generator is also configured, a search-only dispatcher is resolved so that search can convert - /// arbitrary inputs (e.g. string) to embeddings. - /// Otherwise, if a generator is configured, the embedding type is resolved from it. If resolution fails, the embedding type remains - /// and an error is deferred to the validation phase. - /// - private void ConfigureVectorPropertyEmbedding( - VectorPropertyModel vectorProperty, - IEmbeddingGenerator? embeddingGenerator, - Type? userRequestedEmbeddingType) - { - vectorProperty.EmbeddingGenerator = embeddingGenerator; - - if (this.IsVectorPropertyTypeValid(vectorProperty.Type, out _)) - { - if (userRequestedEmbeddingType is not null && userRequestedEmbeddingType != vectorProperty.Type) - { - throw new InvalidOperationException(VectorDataStrings.DifferentEmbeddingTypeSpecifiedForNativelySupportedType(vectorProperty, userRequestedEmbeddingType)); - } - - vectorProperty.EmbeddingType = vectorProperty.Type; - - // Even for native types, if an embedding generator is configured, resolve the dispatcher - // so that search can convert arbitrary inputs (e.g. string) to embeddings. - if (embeddingGenerator is not null) - { - vectorProperty.EmbeddingGenerationDispatcher = this.ResolveSearchOnlyEmbeddingHandler(vectorProperty, embeddingGenerator); - } - } - else if (embeddingGenerator is not null) - { - // The property type isn't a valid embedding type, but an embedding generator is configured. - // Try to resolve the embedding type from it: if the configured generator supports translating the input type (e.g. string) to - // an output type supported by the provider, we set that as the embedding type. - // If this fails, EmbeddingType remains null and we defer the error to the validation phase. - var (embeddingType, handler) = this.ResolveEmbeddingType(vectorProperty, embeddingGenerator, userRequestedEmbeddingType); - vectorProperty.EmbeddingType = embeddingType; - vectorProperty.EmbeddingGenerationDispatcher = handler; - } - - // If the property type isn't valid and there's no embedding generator, that's an error. - // But we throw later, in validation, to allow for provider customization to correct this invalid state after this step. - } - - /// - /// Extension hook for connectors to be able to customize the model. - /// - protected virtual void Customize() - { - } - - /// - /// Validates the model after all properties have been processed. - /// - protected virtual void Validate(Type? type, VectorStoreCollectionDefinition? definition) - { - if (this.KeyProperties.Count > 1) - { - throw new NotSupportedException($"Multiple key properties found on {TypeMessage()}the provided {nameof(VectorStoreCollectionDefinition)} while only one is supported."); - } - - if (this.KeyProperties.Count == 0) - { - throw new NotSupportedException($"No key property found on {TypeMessage()}the provided {nameof(VectorStoreCollectionDefinition)} while at least one is required."); - } - - if (this.Options.RequiresAtLeastOneVector && this.VectorProperties.Count == 0) - { - throw new NotSupportedException($"No vector property found on {TypeMessage()}the provided {nameof(VectorStoreCollectionDefinition)} while at least one is required."); - } - - if (!this.Options.SupportsMultipleVectors && this.VectorProperties.Count > 1) - { - throw new NotSupportedException($"Multiple vector properties found on {TypeMessage()}the provided {nameof(VectorStoreCollectionDefinition)} while only one is supported."); - } - - var storageNameMap = new Dictionary(); - - foreach (var property in this.PropertyMap.Values) - { - this.ValidateProperty(property, definition); - - if (storageNameMap.TryGetValue(property.StorageName, out var otherproperty)) - { - throw new InvalidOperationException($"Property '{property.ModelName}' is being mapped to storage name '{property.StorageName}', but property '{otherproperty.ModelName}' is already mapped to the same storage name."); - } - - storageNameMap[property.StorageName] = property; - } - - string TypeMessage() => type is null ? "" : $"type '{type.Name}' or "; - } - - /// - /// Validates a single property, performing validation on it. - /// - protected virtual void ValidateProperty(PropertyModel propertyModel, VectorStoreCollectionDefinition? definition) - { - var type = propertyModel.Type; - - Debug.Assert(propertyModel.Type is not null); - - switch (propertyModel) - { - case KeyPropertyModel keyProperty: - if (keyProperty.IsAutoGenerated && !this.SupportsKeyAutoGeneration(keyProperty.Type)) - { - throw new NotSupportedException( - $"Property '{keyProperty.ModelName}' is configured for auto-generation, but key properties of type '{keyProperty.Type.Name}' do not support auto-generation."); - } - - this.ValidateKeyProperty(keyProperty); - break; - - case DataPropertyModel dataProperty: - if (!this.IsDataPropertyTypeValid(dataProperty.Type, out var supportedTypes)) - { - throw new NotSupportedException( - $"Property '{dataProperty.ModelName}' has unsupported type '{type.Name}'. Data properties must be one of the supported types: {supportedTypes}."); - } - break; - - case VectorPropertyModel vectorProperty: - if (vectorProperty.EmbeddingType is null) - { - if (this.IsVectorPropertyTypeValid(vectorProperty.Type, out string? supportedVectorTypes)) - { - throw new UnreachableException("EmbeddingType cannot be null when the property type is supported."); - } - - if (vectorProperty.EmbeddingGenerator is null) - { - throw new InvalidOperationException(VectorDataStrings.UnsupportedVectorPropertyWithoutEmbeddingGenerator(vectorProperty)); - } - - // If the user has configured a desired embedding type (done to use en embedding type other than the provider's default one), throw errors tailored to that. - // Throw errors related to that. - var userRequestedEmbeddingType = definition?.Properties.OfType().SingleOrDefault(p => p.Name == vectorProperty.ModelName)?.EmbeddingType; - if (userRequestedEmbeddingType is not null) - { - throw new InvalidOperationException(this.IsVectorPropertyTypeValid(userRequestedEmbeddingType, out _) - ? VectorDataStrings.ConfiguredEmbeddingTypeIsUnsupportedByTheGenerator(vectorProperty, userRequestedEmbeddingType, supportedVectorTypes) - : VectorDataStrings.ConfiguredEmbeddingTypeIsUnsupportedByTheProvider(vectorProperty, userRequestedEmbeddingType, supportedVectorTypes)); - } - - throw new InvalidOperationException(VectorDataStrings.IncompatibleEmbeddingGenerator(vectorProperty, vectorProperty.EmbeddingGenerator, supportedVectorTypes)); - } - - if (!this.IsVectorPropertyTypeValid(vectorProperty.EmbeddingType, out string? supportedVectorTypes2)) - { - // Should in principle never happen, only with incorrect provider customization. - throw new InvalidOperationException($"Property '{vectorProperty.ModelName}' has unsupported embedding type '{vectorProperty.EmbeddingType.Name}'. Vector properties must be one of the supported types: {supportedVectorTypes2}."); - } - - if (vectorProperty.Dimensions <= 0) - { - throw new InvalidOperationException($"Vector property '{propertyModel.ModelName}' must have a positive number of dimensions."); - } - - break; - - default: - throw new UnreachableException(); - } - } - - /// - /// Configures auto-generation for the given key property. - /// Defaults to configuring key properties as auto-generated, and throwing if auto-generation is requested for - /// any other type. - /// - protected virtual bool SupportsKeyAutoGeneration(Type keyPropertyType) - => keyPropertyType == typeof(Guid); - - /// - /// Validates the key property. The default implementation validates that the collection's generic key type () - /// corresponds to the key property type on the model, if was provided. - /// Provider overrides should call the base implementation. - /// - protected virtual void ValidateKeyProperty(KeyPropertyModel keyProperty) - { - if (this.KeyType is not null && this.KeyType != typeof(object) && this.KeyType != keyProperty.Type) - { - throw new InvalidOperationException( - $"The collection's generic key type is '{this.KeyType.Name}', but the key property '{keyProperty.ModelName}' has type '{keyProperty.Type.Name}'. The generic key type must match the key property type."); - } - } - - /// - /// Validates that the .NET type for a data property is supported by the provider. - /// - protected abstract bool IsDataPropertyTypeValid(Type type, [NotNullWhen(false)] out string? supportedTypes); - - /// - /// Validates that the .NET type for a vector property is supported by the provider. - /// - protected abstract bool IsVectorPropertyTypeValid(Type type, [NotNullWhen(false)] out string? supportedTypes); -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModelBuildingOptions.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModelBuildingOptions.cs deleted file mode 100644 index 28ae1f026af0..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModelBuildingOptions.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System.Diagnostics.CodeAnalysis; - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -/// -/// Contains options affecting model building; passed to . -/// This is an internal support type meant for use by connectors only and not by applications. -/// -[Experimental("MEVD9001")] -public sealed class CollectionModelBuildingOptions -{ - /// - /// Gets a value that indicates whether multiple vector properties are supported. - /// - public required bool SupportsMultipleVectors { get; init; } - - /// - /// Gets a value that indicates whether at least one vector property is required. - /// - public required bool RequiresAtLeastOneVector { get; init; } - - /// - /// Gets a value that indicates whether an external serializer will be used (for example, System.Text.Json). - /// - public bool UsesExternalSerializer { get; init; } - - /// - /// Gets the special, reserved name for the key property of the database. - /// When set, the model builder manages the key storage name, and users cannot customize it. - /// - public string? ReservedKeyStorageName { get; init; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/DataPropertyModel.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/DataPropertyModel.cs deleted file mode 100644 index b2d800245054..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/DataPropertyModel.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Diagnostics.CodeAnalysis; - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -/// -/// Represents a data property on a vector store record. -/// This is an internal support type meant for use by connectors only and not by applications. -/// -[Experimental("MEVD9001")] -public class DataPropertyModel(string modelName, Type type) : PropertyModel(modelName, type) -{ - /// - /// Gets or sets a value indicating whether this data property is indexed. - /// - /// - /// The default is . - /// - public bool IsIndexed { get; set; } - - /// - /// Gets or sets a value indicating whether this data property is indexed for full-text search. - /// - /// - /// The default is . - /// - public bool IsFullTextIndexed { get; set; } - - /// - public override string ToString() - => $"{this.ModelName} (Data, {this.Type.Name})"; -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/EmbeddingGenerationDispatcher.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/EmbeddingGenerationDispatcher.cs deleted file mode 100644 index b1825cda295a..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/EmbeddingGenerationDispatcher.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.AI; - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -/// -/// Represents a supported embedding type for a vector store provider. -/// This is an internal support type meant for use by connectors only and not by applications. -/// -/// -/// Each instance encapsulates both build-time embedding type resolution and runtime embedding generation -/// for a specific subtype. -/// -[Experimental("MEVD9001")] -public abstract class EmbeddingGenerationDispatcher -{ - /// - /// Gets the type that this instance supports. - /// - public abstract Type EmbeddingType { get; } - - /// - /// Attempts to resolve the embedding type for the given , using the given . - /// - /// The resolved embedding type, or if the generator does not support this embedding type. - public abstract Type? ResolveEmbeddingType(VectorPropertyModel vectorProperty, IEmbeddingGenerator embeddingGenerator, Type? userRequestedEmbeddingType); - - /// - /// Generates embeddings of this type from the given , using the embedding generator configured on the . - /// - public abstract Task> GenerateEmbeddingsAsync(VectorPropertyModel vectorProperty, IEnumerable values, CancellationToken cancellationToken); - - /// - /// Generates a single embedding of this type from the given , using the embedding generator configured on the . - /// - public abstract Task GenerateEmbeddingAsync(VectorPropertyModel vectorProperty, object? value, CancellationToken cancellationToken); - - /// - /// Checks whether the given can produce embeddings of this type for any of the input types - /// supported by the given . - /// This is used for native vector property types (e.g., of ), where embedding generation - /// is only needed for search and the input type is not known at model-build time. - /// - public abstract bool CanGenerateEmbedding(VectorPropertyModel vectorProperty, IEmbeddingGenerator embeddingGenerator); - - /// - /// Creates a new for the given type. - /// - public static EmbeddingGenerationDispatcher Create() - where TEmbedding : Embedding - => new EmbeddingGenerationDispatcher(); -} - -/// -/// A implementation for a specific type. -/// This is an internal support type meant for use by connectors only and not by applications. -/// -[Experimental("MEVD9001")] -public sealed class EmbeddingGenerationDispatcher : EmbeddingGenerationDispatcher - where TEmbedding : Embedding -{ - /// - public override Type EmbeddingType => typeof(TEmbedding); - - /// - public override Type? ResolveEmbeddingType(VectorPropertyModel vectorProperty, IEmbeddingGenerator embeddingGenerator, Type? userRequestedEmbeddingType) - => vectorProperty.ResolveEmbeddingType(embeddingGenerator, userRequestedEmbeddingType); - - /// - public override bool CanGenerateEmbedding(VectorPropertyModel vectorProperty, IEmbeddingGenerator embeddingGenerator) - => vectorProperty.CanGenerateEmbedding(embeddingGenerator); - - /// - public override Task> GenerateEmbeddingsAsync(VectorPropertyModel vectorProperty, IEnumerable values, CancellationToken cancellationToken) - => vectorProperty.GenerateEmbeddingsCoreAsync(values, cancellationToken); - - /// - public override Task GenerateEmbeddingAsync(VectorPropertyModel vectorProperty, object? value, CancellationToken cancellationToken) - => vectorProperty.GenerateEmbeddingCoreAsync(value, cancellationToken); -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/FilterPreprocessingOptions.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/FilterPreprocessingOptions.cs deleted file mode 100644 index 4b0cc8f07e2b..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/FilterPreprocessingOptions.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System.Diagnostics.CodeAnalysis; - -namespace Microsoft.Extensions.VectorData.ProviderServices.Filter; - -/// -/// Options for filter expression preprocessing. -/// This is an internal support type meant for use by connectors only and not by applications. -/// -[Experimental("MEVD9001")] -public class FilterPreprocessingOptions -{ - /// - /// Whether the connector supports parameterization. - /// - /// - /// If , the visitor will inline captured variables and constant member accesses as simple constant nodes. - /// If , these will instead be replaced with nodes. - /// - public bool SupportsParameterization { get; init; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/FilterTranslatorBase.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/FilterTranslatorBase.cs deleted file mode 100644 index ad847b34b1d1..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/FilterTranslatorBase.cs +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; - -namespace Microsoft.Extensions.VectorData.ProviderServices.Filter; - -/// -/// Base class for filter translators used by vector data connectors. -/// Provides common functionality for preprocessing filter expressions and matching common patterns. -/// This is an internal support type meant for use by connectors only and not by applications. -/// -[Experimental("MEVD9001")] -public abstract class FilterTranslatorBase -{ - /// - /// The collection model for the current translation operation. - /// - protected CollectionModel Model { get; private set; } = null!; - - /// - /// The parameter expression representing the record in the filter lambda. - /// - protected ParameterExpression RecordParameter { get; private set; } = null!; - - /// - /// Preprocesses the filter expression before translation. - /// Sets and , runs the preprocessing visitor, - /// and returns the preprocessed expression. - /// - /// The filter lambda expression to preprocess. - /// The collection model containing property information. - /// Options controlling the preprocessing behavior. - /// The preprocessed expression ready for translation. - protected Expression PreprocessFilter(LambdaExpression lambdaExpression, CollectionModel model, FilterPreprocessingOptions options) - { - this.Model = model; - this.RecordParameter = lambdaExpression.Parameters[0]; - - var preprocessor = new FilterTranslationPreprocessor(options.SupportsParameterization); - return preprocessor.Preprocess(lambdaExpression.Body); - } - - /// - /// Tries to match a Contains method call expression and extract the source collection and item expressions. - /// - /// The method call expression to match. - /// When successful, the source collection expression. - /// When successful, the item expression being searched for. - /// if the expression is a recognized Contains pattern; otherwise, . - protected static bool TryMatchContains( - MethodCallExpression methodCall, - [NotNullWhen(true)] out Expression? source, - [NotNullWhen(true)] out Expression? item) - { - switch (methodCall) - { - // Enumerable.Contains() - case { Method.Name: nameof(Enumerable.Contains), Arguments: [var src, var itm] } - when methodCall.Method.DeclaringType == typeof(Enumerable): - source = src; - item = itm; - return true; - - // List.Contains() - case - { - Method: - { - Name: nameof(Enumerable.Contains), - DeclaringType: { IsGenericType: true } declaringType - }, - Object: Expression src, - Arguments: [var itm] - } when declaringType.GetGenericTypeDefinition() == typeof(List<>): - source = src; - item = itm; - return true; - - // C# 14 made changes to overload resolution to prefer Span-based overloads when those exist ("first-class spans"); - // this makes MemoryExtensions.Contains() be resolved rather than Enumerable.Contains() (see above). - // MemoryExtensions.Contains() also accepts a Span argument for the source, adding an implicit cast we need to remove. - // See https://github.com/dotnet/runtime/issues/109757 for more context. - // Note that MemoryExtensions.Contains has an optional 3rd ComparisonType parameter; we only match when - // it's null. - case { Method.Name: nameof(MemoryExtensions.Contains), Arguments: [var spanArg, var itm, ..] } - when methodCall.Method.DeclaringType == typeof(MemoryExtensions) - && (methodCall.Arguments.Count is 2 - || (methodCall.Arguments.Count is 3 && methodCall.Arguments[2] is ConstantExpression { Value: null })) - && TryUnwrapSpanImplicitCast(spanArg, out var src): - source = src; - item = itm; - return true; - - default: - source = null; - item = null; - return false; - } - } - - /// - /// Tries to bind an expression to a property in the collection model. - /// - /// The expression to bind. - /// When successful, the property model that was bound. - /// if the expression was successfully bound to a property; otherwise, . - protected virtual bool TryBindProperty(Expression expression, [NotNullWhen(true)] out PropertyModel? propertyModel) - { - var unwrappedExpression = expression; - while (unwrappedExpression is UnaryExpression { NodeType: ExpressionType.Convert } convert) - { - unwrappedExpression = convert.Operand; - } - - var modelName = unwrappedExpression switch - { - // Regular member access for strongly-typed POCO binding (e.g. r => r.SomeInt == 8) - MemberExpression memberExpression when memberExpression.Expression == this.RecordParameter - => memberExpression.Member.Name, - - // Dictionary lookup for weakly-typed dynamic binding (e.g. r => r["SomeInt"] == 8) - MethodCallExpression - { - Method: { Name: "get_Item", DeclaringType: var declaringType }, - Arguments: [ConstantExpression { Value: string keyName }] - } methodCall when methodCall.Object == this.RecordParameter && declaringType == typeof(Dictionary) - => keyName, - - _ => null - }; - - if (modelName is null) - { - propertyModel = null; - return false; - } - - if (!this.Model.PropertyMap.TryGetValue(modelName, out propertyModel)) - { - throw new InvalidOperationException($"Property name '{modelName}' provided as part of the filter clause is not a valid property name."); - } - - // Now that we have the property, go over all wrapping Convert nodes again to ensure that they're compatible with the property type - var unwrappedPropertyType = Nullable.GetUnderlyingType(propertyModel.Type) ?? propertyModel.Type; - unwrappedExpression = expression; - while (unwrappedExpression is UnaryExpression { NodeType: ExpressionType.Convert } convert) - { - var convertType = Nullable.GetUnderlyingType(convert.Type) ?? convert.Type; - if (convertType != unwrappedPropertyType && convertType != typeof(object)) - { - throw new InvalidCastException($"Property '{propertyModel.ModelName}' is being cast to type '{convert.Type.Name}', but its configured type is '{propertyModel.Type.Name}'."); - } - - unwrappedExpression = convert.Operand; - } - - return true; - } - - /// - /// Tries to unwrap an implicit cast to Span or ReadOnlySpan that may be present in expressions - /// when C# 14's first-class span support causes MemoryExtensions methods to be resolved. - /// - /// The expression to unwrap. - /// When successful, the unwrapped expression. - /// if a span implicit cast was unwrapped; otherwise, . - protected static bool TryUnwrapSpanImplicitCast(Expression expression, [NotNullWhen(true)] out Expression? result) - { - // Different versions of the compiler seem to generate slightly different expression tree representations for this - // implicit cast: - var (unwrapped, castDeclaringType) = expression switch - { - UnaryExpression - { - NodeType: ExpressionType.Convert, - Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType }, - Operand: var operand - } => (operand, implicitCastDeclaringType), - - MethodCallExpression - { - Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType }, - Arguments: [var firstArgument] - } => (firstArgument, implicitCastDeclaringType), - - // After the preprocessor runs, the Convert node may have Method: null because the visitor - // recreates the UnaryExpression with a different operand type (QueryParameterExpression). - // Handle this case by checking if the target type is Span or ReadOnlySpan. - UnaryExpression - { - NodeType: ExpressionType.Convert, - Method: null, - Type: { IsGenericType: true } targetType, - Operand: var operand - } when targetType.GetGenericTypeDefinition() is var gtd - && (gtd == typeof(Span<>) || gtd == typeof(ReadOnlySpan<>)) - => (operand, targetType), - - _ => (null, null) - }; - - // For the dynamic case, there's a Convert node representing an up-cast to object[]; unwrap that too. - // Also handle cases where the preprocessor adds a Convert node back to the array type. - while (unwrapped is UnaryExpression - { - NodeType: ExpressionType.Convert, - Method: null, - Operand: var innerOperand - }) - { - unwrapped = innerOperand; - } - - if (unwrapped is not null - && castDeclaringType?.GetGenericTypeDefinition() is var genericTypeDefinition - && (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>))) - { - result = unwrapped; - return true; - } - - result = null; - return false; - } - - #region FilterTranslationPreprocessor - - /// - /// A processor for user-provided filter expressions which performs various common transformations before actual translation takes place. - /// - private sealed class FilterTranslationPreprocessor : ExpressionVisitor - { - private readonly bool _supportsParameterization; - private List? _parameterNames; - - internal FilterTranslationPreprocessor(bool supportsParameterization) - { - this._supportsParameterization = supportsParameterization; - } - - internal Expression Preprocess(Expression node) - { - if (this._supportsParameterization) - { - this._parameterNames = []; - } - - return this.Visit(node); - } - - /// - protected override Expression VisitMember(MemberExpression node) - { - var visited = (MemberExpression)base.VisitMember(node); - - // This identifies field and property access over constants, which can be evaluated immediately. - // This covers captured variables, since those are actually member accesses over compiled-generated closure types: - // var x = 8; - // _ = await collection.SearchAsync(vector, top: 3, new() { Filter = r => r.Int == x }); - // - // This also covers member variables: - // _ = await collection.SearchAsync(vector, top: 3, new() { Filter = r => r.Int == this._x }); - // ... as "this" here is represented by a ConstantExpression node in the tree. - // - // Some databases - mostly relational ones - support out-of-band parameters which can be referenced via placeholders - // from the query itself. For those databases, we transform the member access to QueryParameterExpression (this simplifies things for those - // connectors, and centralizes the pattern matching in a single centralized place). - // For databases which don't support parameters, we simply inline the evaluated member access as a constant in the tree, so that translators don't - // even need to be aware of it. - - // Evaluate the MemberExpression to get the actual value, either for instance members (expression is a ConstantExpression) or for - // static members (expression is null). - object? baseValue; - switch (visited.Expression) - { - // Member access over constant (i.e. instance members) - case ConstantExpression { Value: var v }: - baseValue = v; - break; - - // Member constant over null (i.e. static members) - case null: - baseValue = null; - break; - - // Member constant over something that has already been parameterized (i.e. nested member access, e.g. r=> r.Int == this.SomeWrapper.Something) - case QueryParameterExpression p: - baseValue = p.Value; - - // The previous parameter is getting replaced by the new one we're creating here, so remove its name from the list of parameter names. - this._parameterNames!.Remove(p.Name); - break; - - default: - return visited; - } - - object? evaluatedValue; - - var memberInfo = visited.Member; - - switch (memberInfo) - { - case FieldInfo fieldInfo: - evaluatedValue = fieldInfo.GetValue(baseValue); - break; - - case PropertyInfo { GetMethod.IsStatic: false } propertyInfo when baseValue is null: - throw new InvalidOperationException($"Cannot access member '{propertyInfo.Name}' on null object."); - - case PropertyInfo propertyInfo: - evaluatedValue = propertyInfo.GetValue(baseValue); - break; - default: - return visited; - } - - // Inline the evaluated value (if the connector doesn't support parameterization, or if the field is readonly), - if (!this._supportsParameterization) - { - return Expression.Constant(evaluatedValue, visited.Type); - } - - // Otherwise, transform the node to a QueryParameterExpression which the connector will then translate to a parameter (e.g. SqlParameter). - - // TODO: Share the same parameter when it references the same captured value - - // Make sure parameter names are unique. - var origName = memberInfo.Name; - var name = origName; - for (var i = 0; this._parameterNames!.Contains(name); i++) - { - name = $"{origName}_{i}"; - } - this._parameterNames.Add(name); - - return new QueryParameterExpression(name, evaluatedValue, visited.Type); - } - - /// - protected override Expression VisitNew(NewExpression node) - { - var visited = (NewExpression)base.VisitNew(node); - - // Recognize certain well-known constructors where we can evaluate immediately, converting the NewExpression to a ConstantExpression. - // This is particularly useful for converting inline instantiation of DateTime, DateTimeOffset, DateOnly, and TimeOnly to constants, which can then be easily translated. - switch (visited.Constructor) - { - case ConstructorInfo constructor when constructor.DeclaringType == typeof(DateTimeOffset) || constructor.DeclaringType == typeof(DateTime) -#if NET - || constructor.DeclaringType == typeof(DateOnly) || constructor.DeclaringType == typeof(TimeOnly) -#endif - : - var constantArguments = new object?[visited.Arguments.Count]; - - // We first do a fast path to check if all arguments are constants; this catches the common case of e.g. new DateTime(2023, 10, 1). - // If an argument isn't a constant (e.g. new DateTimeOffset(..., TimeSpan.FromHours(2))), we fall back to trying the LINQ interpreter - // as a general-purpose expression evaluator - but note that this is considerably slower. - for (var i = 0; i < visited.Arguments.Count; i++) - { - if (visited.Arguments[i] is ConstantExpression constantArgument) - { - constantArguments[i] = constantArgument.Value; - } - else - { - // There's a non-constant argument - try the LINQ interpreter. -#pragma warning disable CA1031 // Do not catch general exception types - try - { - var evaluated = Expression.Lambda>(Expression.Convert(visited, typeof(object))) -#if NET - .Compile(preferInterpretation: true) -#else - .Compile() -#endif - .Invoke(); - - return Expression.Constant(evaluated, constructor.DeclaringType); - } - catch - { - return visited; - } -#pragma warning restore CA1031 - } - } - - var constantValue = constructor.Invoke(constantArguments); - return Expression.Constant(constantValue, constructor.DeclaringType); - } - - return visited; - } - } - - #endregion FilterTranslationPreprocessor -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/QueryParameterExpression.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/QueryParameterExpression.cs deleted file mode 100644 index 0c37722a3bcc..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/Filter/QueryParameterExpression.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Linq.Expressions; - -namespace Microsoft.Extensions.VectorData.ProviderServices.Filter; - -/// -/// An expression representation a query parameter (captured variable) in the filter expression. -/// -[Experimental("MEVD9001")] -public class QueryParameterExpression(string name, object? value, Type type) : Expression -{ - /// - /// The name of the parameter. - /// - public string Name { get; } = name; - - /// - /// The value of the parameter. - /// - public object? Value { get; } = value; - - /// - public override ExpressionType NodeType => ExpressionType.Extension; - - /// - public override Type Type => type; - - /// - protected override Expression VisitChildren(ExpressionVisitor visitor) => this; -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/IRecordCreator.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/IRecordCreator.cs deleted file mode 100644 index 079659ce5bcb..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/IRecordCreator.cs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -internal interface IRecordCreator -{ - TRecord Create(); -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/KeyPropertyModel.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/KeyPropertyModel.cs deleted file mode 100644 index 2b31e56a3d9d..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/KeyPropertyModel.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Diagnostics.CodeAnalysis; - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -/// -/// Represents a key property on a vector store record. -/// This is an internal support type meant for use by connectors only and not by applications. -/// -[Experimental("MEVD9001")] -public class KeyPropertyModel(string modelName, Type type) : PropertyModel(modelName, type) -{ - /// - /// Gets or sets whether this key property's value is auto-generated or not. - /// - public bool IsAutoGenerated { get; set; } - - /// - /// Gets or sets the name that the JSON serializer will produce for this key property. - /// This is needed for connectors that use an external JSON serializer combined with a reserved key storage name - /// (e.g. CosmosDB NoSQL uses "id"): the serializer produces a JSON object with the policy-transformed name, and - /// the connector needs to find and replace it with the reserved storage name. - /// - public string? SerializedKeyName { get; set; } - - /// - public override string ToString() - => $"{this.ModelName} (Key, {this.Type.Name}{(this.IsAutoGenerated ? ", auto-generated" : "")})"; -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/PropertyModel.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/PropertyModel.cs deleted file mode 100644 index 7b3635911e95..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/PropertyModel.cs +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Reflection; - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -/// -/// Represents a property on a vector store record. -/// This is an internal support type meant for use by connectors only and not by applications. -/// -[Experimental("MEVD9001")] -public abstract class PropertyModel(string modelName, Type type) -{ - private string? _storageName; - private Func? _getter; - private Action? _setter; - - /// - /// Gets or sets the model name of the property. If the property corresponds to a .NET property, this name is the name of that property. - /// - public string ModelName { get; set; } = modelName; - - /// - /// Gets or sets the storage name of the property. This is the name to which the property is mapped in the vector store. - /// - public string StorageName - { - get => this._storageName ?? this.ModelName; - set => this._storageName = value; - } - - /// - /// Gets or sets the CLR type of the property. - /// - public Type Type { get; set; } = type; - - /// - /// Gets or sets the reflection for the .NET property. - /// - /// - /// The reflection for the .NET property. - /// when using dynamic mapping. - /// - public PropertyInfo? PropertyInfo { get; set; } - - /// - /// Gets or sets a dictionary of provider-specific annotations for this property. - /// - /// - /// This allows setting database-specific configuration options that aren't universal across all vector stores. - /// - public Dictionary? ProviderAnnotations { get; set; } - - /// - /// Gets whether the property type is nullable. For value types, this is when the type is - /// . For reference types on .NET 6+, this uses NRT annotations via - /// NullabilityInfoContext when a is available - /// (i.e., POCO mapping); otherwise, reference types are assumed nullable. - /// - public bool IsNullable - { - get - { - // Value types: nullable only if Nullable - if (this.Type.IsValueType) - { - return Nullable.GetUnderlyingType(this.Type) is not null; - } - - // Reference types: check NRT annotation via NullabilityInfoContext when available -#if NET - if (this.PropertyInfo is { } propertyInfo) - { - var nullabilityInfo = new NullabilityInfoContext().Create(propertyInfo); - return nullabilityInfo.ReadState != NullabilityState.NotNull; - } -#endif - - // Dynamic mapping or old framework: assume nullable for reference types - return true; - } - } - - /// - /// Configures the property accessors using a CLR for POCO mapping. - /// - // TODO: Implement compiled delegates for better performance, #11122 - // TODO: Implement source-generated accessors for NativeAOT, #10256 - internal void ConfigurePocoAccessors(PropertyInfo propertyInfo) - { - this.PropertyInfo = propertyInfo; - this._getter = propertyInfo.GetValue; - this._setter = (record, value) => - { - // If the value is null, no need to set the property (it's the CLR default) - if (value is not null) - { - propertyInfo.SetValue(record, value); - } - }; - } - - /// - /// Configures the property accessors for dynamic mapping using . - /// - internal void ConfigureDynamicAccessors() - { - var modelName = this.ModelName; - var propertyType = this.Type; - - this._getter = record => - { - var dictionary = (Dictionary)record; - var value = dictionary.TryGetValue(modelName, out var tempValue) ? tempValue : null; - - if (value is not null && value.GetType() != (Nullable.GetUnderlyingType(propertyType) ?? propertyType)) - { - throw new InvalidCastException($"Property '{modelName}' has a value of type '{value.GetType().Name}', but its configured type is '{propertyType.Name}'."); - } - - return value; - }; - - this._setter = (record, value) => ((Dictionary)record)[modelName] = value; - } - - /// - /// Reads the property from the given , returning the value as an . - /// - public object? GetValueAsObject(object record) - { - Debug.Assert(this._getter is not null, "Property accessors have not been configured."); - return this._getter!(record); - } - - /// - /// Writes the property from the given , accepting the value to write as an . - /// - public void SetValueAsObject(object record, object? value) - { - Debug.Assert(this._setter is not null, "Property accessors have not been configured."); - this._setter!(record, value); - } - - /// - /// Reads the property from the given . - /// - // TODO: actually implement the generic accessors to avoid boxing, and make use of them in connectors - public T GetValue(object record) - => (T)(object)this.GetValueAsObject(record)!; - - /// - /// Writes the property from the given . - /// - // TODO: actually implement the generic accessors to avoid boxing, and make use of them in connectors - public void SetValue(object record, T value) - => this.SetValueAsObject(record, value); -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorDataStrings.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorDataStrings.cs deleted file mode 100644 index 22a65a732f8b..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorDataStrings.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using Microsoft.Extensions.AI; - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member - -/// -/// Exposes methods for constructing strings that should be used by providers when throwing exceptions. -/// -[Experimental("MEVD9001")] -public static class VectorDataStrings -{ - public static string ConfiguredEmbeddingTypeIsUnsupportedByTheGenerator(VectorPropertyModel vectorProperty, Type userRequestedEmbeddingType, string supportedVectorTypes) - => $"Vector property '{vectorProperty.ModelName}' has embedding type '{TypeName(userRequestedEmbeddingType)}' configured, but that type isn't supported by your embedding generator."; - - public static string ConfiguredEmbeddingTypeIsUnsupportedByTheProvider(VectorPropertyModel vectorProperty, Type userRequestedEmbeddingType, string supportedVectorTypes) - => $"Vector property '{vectorProperty.ModelName}' has embedding type '{TypeName(userRequestedEmbeddingType)}' configured, but that type isn't supported by your provider. Supported types are {supportedVectorTypes}."; - - public static string EmbeddingGeneratorWithInvalidEmbeddingType(VectorPropertyModel vectorProperty) - => $"An embedding generator was configured on property '{vectorProperty.ModelName}', but output embedding type '{vectorProperty.EmbeddingType.Name}' isn't supported by the connector."; - - public static string EmbeddingPropertyTypeIncompatibleWithEmbeddingGenerator(VectorPropertyModel vectorProperty) - => $"Property '{vectorProperty.ModelName}' has embedding type '{TypeName(vectorProperty.Type)}', but an embedding generator is configured on the property. Remove the embedding generator or change the property's .NET type to a non-embedding input type to the generator (e.g. string)."; - - public static string DifferentEmbeddingTypeSpecifiedForNativelySupportedType(VectorPropertyModel vectorProperty, Type embeddingType) - => $"Property '{vectorProperty.ModelName}' has {nameof(VectorStoreVectorProperty.EmbeddingType)} configured to '{TypeName(embeddingType)}', but the property already has natively supported '{TypeName(vectorProperty.Type)}'. {nameof(VectorStoreVectorProperty.EmbeddingType)} only needs to be specified for properties that require embedding generation."; - - public static string GetCollectionWithDictionaryNotSupported - => "Dynamic mapping via Dictionary is not supported via this method, call GetDynamicCollection() instead."; - - public static string IncludeVectorsNotSupportedWithEmbeddingGeneration - => "When an embedding generator is configured, `Include Vectors` cannot be enabled."; - - public static string IncompatibleEmbeddingGenerator(VectorPropertyModel vectorProperty, IEmbeddingGenerator embeddingGenerator, string supportedOutputTypes) - => $"Embedding generator '{TypeName(embeddingGenerator.GetType())}' on vector property '{vectorProperty.ModelName}' cannot convert the input type '{TypeName(vectorProperty.Type)}' to a supported vector type (one of: {supportedOutputTypes})."; - - public static string IncompatibleEmbeddingGeneratorWasConfiguredForInputType(Type inputType, Type embeddingGeneratorType) - => $"An input of type '{TypeName(inputType)}' was provided, but an incompatible embedding generator of type '{TypeName(embeddingGeneratorType)}' was configured."; - - public static string InvalidSearchInputAndNoEmbeddingGeneratorWasConfigured(Type inputType, string supportedVectorTypes) - => $"A value of type '{TypeName(inputType)}' was passed to 'SearchAsync', but that isn't a supported vector type by your provider and no embedding generator was configured. The supported vector types are: {supportedVectorTypes}."; - - public static string MissingTypeOnPropertyDefinition(VectorStoreProperty property) - => $"Property '{property.Name}' has no type specified in its definition, and does not have a corresponding .NET property. Specify the type on the definition."; - - public static string UnsupportedVectorPropertyWithoutEmbeddingGenerator(VectorPropertyModel vectorProperty) - => $"Vector property '{vectorProperty.ModelName}' has type '{TypeName(vectorProperty.Type)}' which isn't supported by your provider, and no embedding generator is configured. Configure a generator that supports converting '{TypeName(vectorProperty.Type)}' to vector type supported by your provider."; - - public static string NonDynamicCollectionWithDictionaryNotSupported(Type dynamicCollectionType) - => $"Dynamic mapping via Dictionary is not supported via this class, use '{TypeName(dynamicCollectionType)}' instead."; - - private static string TypeName(this Type type) - { - var i = type.Name.IndexOf('`'); - if (i == -1) - { - return type.Name switch - { - "Int32" => "int", - "Int64" => "long", - "Boolean" => "bool", - "Double" => "double", - "Single" => "float", - "String" => "string", - - _ => type.Name - }; - } - - var genericTypeName = type.Name.Substring(0, i); - var genericArgs = string.Join(", ", type.GetGenericArguments().Select(t => t.TypeName())); - return $"{genericTypeName}<{genericArgs}>"; - } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorPropertyModel.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorPropertyModel.cs deleted file mode 100644 index 75d3a1057ff9..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorPropertyModel.cs +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.AI; - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -/// -/// Represents a vector property on a vector store record. -/// This is an internal support type meant for use by connectors only and not by applications. -/// -[Experimental("MEVD9001")] -public class VectorPropertyModel(string modelName, Type type) : PropertyModel(modelName, type) -{ - private int _dimensions; - - /// - /// Gets or sets the number of dimensions that the vector has. - /// - /// - /// This property is required when creating collections, but can be omitted if not using that functionality. - /// If not provided when trying to create a collection, create will fail. - /// - public int Dimensions - { - get => this._dimensions; - - set - { - if (value <= 0) - { - throw new ArgumentOutOfRangeException(nameof(value), "Dimensions must be greater than zero."); - } - - this._dimensions = value; - } - } - - /// - /// Gets or sets the kind of index to use. - /// - /// - /// The default varies by database type. For more information, see the documentation of your chosen database connector. - /// - /// - public string? IndexKind { get; set; } - - /// - /// Gets or sets the distance function to use when comparing vectors. - /// - /// - /// The default varies by database type. For more information, see the documentation of your chosen database connector. - /// - /// - public string? DistanceFunction { get; set; } - - /// - /// Gets or sets the type representing the embedding stored in the database if is set. - /// Otherwise, this property is identical to . - /// - /// - /// This property may be during model building while the embedding type is being resolved, - /// but is guaranteed to be non-null after building completes (validation ensures this). - /// - [AllowNull] - public Type EmbeddingType { get; set; } = null!; - - /// - /// Gets or sets the embedding generator to use for this property. - /// - public IEmbeddingGenerator? EmbeddingGenerator { get; set; } - - /// - /// Gets or sets the that was resolved for this property during model building. - /// This handler is used for runtime embedding generation dispatch. - /// - /// - /// This is for vector properties whose type is natively supported by the provider - /// (e.g., of , [], ), - /// since no embedding generation is needed. - /// - public EmbeddingGenerationDispatcher? EmbeddingGenerationDispatcher { get; set; } - - /// - /// Checks whether the given can produce embeddings of type - /// for any input type known to this property model. The base implementation checks for and ; - /// also checks for TInput. - /// - /// This is used for native vector property types, where the input type isn't known at model-build time. - public virtual bool CanGenerateEmbedding(IEmbeddingGenerator embeddingGenerator) - where TEmbedding : Embedding - => embeddingGenerator is IEmbeddingGenerator - || embeddingGenerator is IEmbeddingGenerator; - - /// - /// Checks whether the configured on this property supports the given embedding type. - /// The implementation on this non-generic checks for - /// and as input types for . - /// - public virtual Type? ResolveEmbeddingType(IEmbeddingGenerator embeddingGenerator, Type? userRequestedEmbeddingType) - where TEmbedding : Embedding - => embeddingGenerator switch - { - // On the TInput side, this out-of-the-box/simple implementation supports string and DataContent only - // (users who want arbitrary TInput types need to use the generic subclass of this type). - // The TEmbedding side is provided by the connector via the generic type parameter to this method, as the connector controls/knows which embedding types are supported. - // Note that if the user has manually specified an embedding type (e.g. to choose Embedding rather than the default Embedding), - // that's provided via the userRequestedEmbeddingType argument; we use that as a filter. - IEmbeddingGenerator when this.Type == typeof(string) && (userRequestedEmbeddingType is null || userRequestedEmbeddingType == typeof(TEmbedding)) - => typeof(TEmbedding), - IEmbeddingGenerator when this.Type == typeof(DataContent) && (userRequestedEmbeddingType is null || userRequestedEmbeddingType == typeof(TEmbedding)) - => typeof(TEmbedding), - - null => throw new ArgumentNullException(nameof(embeddingGenerator), "This method should only be called when an embedding generator is configured."), - _ => null - }; - - /// - /// Generates embeddings for the given , using the configured . - /// - /// Thrown if no is configured on this property. - public Task> GenerateEmbeddingsAsync(IEnumerable values, CancellationToken cancellationToken) - => this.EmbeddingGenerationDispatcher is not { } dispatcher - ? throw new InvalidOperationException($"No embedding generation is configured for property '{this.ModelName}'.") - : dispatcher.GenerateEmbeddingsAsync(this, values, cancellationToken); - - /// - /// Generates a single embedding for the given , using the configured . - /// - /// Thrown if no is configured on this property. - public Task GenerateEmbeddingAsync(object? value, CancellationToken cancellationToken) - => this.EmbeddingGenerationDispatcher is not { } dispatcher - ? throw new InvalidOperationException($"No embedding generation is configured for property '{this.ModelName}'.") - : dispatcher.GenerateEmbeddingAsync(this, value, cancellationToken); - - /// - /// Core method to generate a batch of embeddings. Called by with the correct type parameter. - /// - internal virtual async Task> GenerateEmbeddingsCoreAsync(IEnumerable values, CancellationToken cancellationToken) - where TEmbedding : Embedding - => this.EmbeddingGenerator switch - { - IEmbeddingGenerator generator when this.EmbeddingType == typeof(TEmbedding) - => await generator.GenerateAsync( - values.Select(v => v is string s - ? s - : throw new InvalidOperationException($"Property '{this.ModelName}' was configured with an embedding generator accepting a string, but {v?.GetType().Name ?? "null"} was provided.")), - options: null, - cancellationToken).ConfigureAwait(false), - - IEmbeddingGenerator generator when this.EmbeddingType == typeof(TEmbedding) - => await generator.GenerateAsync( - values.Select(v => v is DataContent c - ? c - : throw new InvalidOperationException($"Property '{this.ModelName}' was configured with an embedding generator accepting a {nameof(DataContent)}, but {v?.GetType().Name ?? "null"} was provided.")), - options: null, - cancellationToken).ConfigureAwait(false), - - null => throw new UnreachableException("This method should only be called when an embedding generator is configured."), - - _ => throw new InvalidOperationException( - $"The embedding generator configured on property '{this.ModelName}' cannot produce an embedding of type '{typeof(TEmbedding).Name}' for the given input type."), - }; - - /// - /// Core method to generate a single embedding. Called by with the correct type parameter. - /// - internal virtual async Task GenerateEmbeddingCoreAsync(object? value, CancellationToken cancellationToken) - where TEmbedding : Embedding - => this.EmbeddingGenerator switch - { - IEmbeddingGenerator generator when value is string s - => await generator.GenerateAsync(s, options: null, cancellationToken).ConfigureAwait(false), - - IEmbeddingGenerator generator when value is DataContent c - => await generator.GenerateAsync(c, options: null, cancellationToken).ConfigureAwait(false), - - null => throw new UnreachableException("This method should only be called when an embedding generator is configured."), - - _ => throw new InvalidOperationException( - VectorDataStrings.IncompatibleEmbeddingGeneratorWasConfiguredForInputType(value?.GetType() ?? typeof(object), this.EmbeddingGenerator!.GetType())), - }; - - /// - /// Returns the types of input that this property model supports. - /// - public virtual Type[] GetSupportedInputTypes() => [typeof(string), typeof(DataContent)]; - - /// - public override string ToString() - => $"{this.ModelName} (Vector, {this.Type.Name})"; -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorPropertyModel{TInput}.cs b/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorPropertyModel{TInput}.cs deleted file mode 100644 index e7f51d2c58e1..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/VectorPropertyModel{TInput}.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.AI; - -namespace Microsoft.Extensions.VectorData.ProviderServices; - -/// -[Experimental("MEVD9001")] -public sealed class VectorPropertyModel(string modelName) : VectorPropertyModel(modelName, typeof(TInput)) -{ - /// - public override bool CanGenerateEmbedding(IEmbeddingGenerator embeddingGenerator) - => embeddingGenerator is IEmbeddingGenerator - || base.CanGenerateEmbedding(embeddingGenerator); - - /// - public override Type? ResolveEmbeddingType(IEmbeddingGenerator embeddingGenerator, Type? userRequestedEmbeddingType) - => embeddingGenerator switch - { - IEmbeddingGenerator when this.Type == typeof(TInput) && (userRequestedEmbeddingType is null || userRequestedEmbeddingType == typeof(TEmbedding)) - => typeof(TEmbedding), - - null => throw new ArgumentNullException(nameof(embeddingGenerator), "This method should only be called when an embedding generator is configured."), - _ => null - }; - - /// - internal override async Task> GenerateEmbeddingsCoreAsync(IEnumerable values, CancellationToken cancellationToken) - { - switch (this.EmbeddingGenerator) - { - case IEmbeddingGenerator generator when this.EmbeddingType == typeof(TEmbedding): - return await generator.GenerateAsync( - values.Select(v => v is TInput s - ? s - : throw new InvalidOperationException($"Property '{this.ModelName}' was configured with an embedding generator accepting a {typeof(TInput).Name}, but {v?.GetType().Name ?? "null"} was provided.")), - options: null, - cancellationToken).ConfigureAwait(false); - - case null: - throw new UnreachableException("This method should only be called when an embedding generator is configured."); - - default: - throw new InvalidOperationException( - $"The embedding generator configured on property '{this.ModelName}' cannot produce an embedding of type '{typeof(TEmbedding).Name}' for the given input type."); - } - } - - /// - internal override async Task GenerateEmbeddingCoreAsync(object? value, CancellationToken cancellationToken) - { - if (this.EmbeddingGenerator is IEmbeddingGenerator generator && value is TInput t) - { - return await generator.GenerateAsync(t, options: null, cancellationToken).ConfigureAwait(false); - } - - // Fall through to base class which checks for string and DataContent input types. - return await base.GenerateEmbeddingCoreAsync(value, cancellationToken).ConfigureAwait(false); - } - - /// - public override Type[] GetSupportedInputTypes() => [typeof(TInput)]; -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/README.md b/dotnet/src/VectorData/VectorData.Abstractions/README.md new file mode 100644 index 000000000000..0e5c7c8e55ac --- /dev/null +++ b/dotnet/src/VectorData/VectorData.Abstractions/README.md @@ -0,0 +1 @@ +The code for Microsoft.Extensions.VectorData.Abstractions can now be found in the [dotnet/extensions repository](https://github.com/dotnet/extensions/tree/main/src/Libraries/Microsoft.Extensions.VectorData.Abstractions) diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreDataAttribute.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreDataAttribute.cs deleted file mode 100644 index d326bb068760..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreDataAttribute.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines an attribute to mark a property on a record class as 'data'. -/// -/// -/// Marking a property as 'data' means that the property is not a key and not a vector. But optionally, -/// this property can have an associated vector field containing an embedding for this data. -/// The characteristics defined here influence how the property is treated by the vector store. -/// -[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] -public sealed class VectorStoreDataAttribute : Attribute -{ - /// - /// Gets or sets a value indicating whether this data property is indexed. - /// - /// - /// The default is . - /// - public bool IsIndexed { get; init; } - - /// - /// Gets or sets a value indicating whether this data property is indexed for full-text search. - /// - /// - /// The default is . - /// - public bool IsFullTextIndexed { get; init; } - - /// - /// Gets or sets an optional name to use for the property in storage, if different from the property name. - /// - /// - /// For example, the property name might be "MyProperty" and the storage name might be "my_property". - /// - public string? StorageName { get; init; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreKeyAttribute.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreKeyAttribute.cs deleted file mode 100644 index 5e4001a447d3..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreKeyAttribute.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines an attribute to mark a property on a record class as the key under which the record is stored in a vector store. -/// -/// -/// The characteristics defined here influence how the property is treated by the vector store. -/// -[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] -public sealed class VectorStoreKeyAttribute : Attribute -{ - /// - /// Gets or sets an optional name to use for the property in storage, if different from the property name. - /// - /// - /// For example, the property name might be "MyProperty" and the storage name might be "my_property". - /// - public string? StorageName { get; init; } - - /// - /// Gets or sets whether this key property's value is auto-generated or not. - /// - /// - /// The availability of auto-generated properties - as well as the .NET types supported for them - varies across provider implementations. - /// The getter returns when the value has not been explicitly set; use to distinguish - /// between "explicitly set to false" and "not set". - /// The getter does not throw, even though it cannot distinguish "explicitly set to false" and "not set"; this is a workaround for a C# compiler - /// limitation that does not allow to be used as an attribute argument. - /// - public bool IsAutoGenerated - { - // The getter returns GetValueOrDefault() rather than throwing, as a workaround for a C# compiler limitation: - // Nullable cannot be used as a compile-time attribute argument, so the public property must be bool. - get => this.IsAutoGeneratedNullable.GetValueOrDefault(); - set => this.IsAutoGeneratedNullable = value; - } - - /// - /// Gets whether this key property's value is auto-generated or not, or if not set. - /// - internal bool? IsAutoGeneratedNullable { get; private set; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreVectorAttribute.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreVectorAttribute.cs deleted file mode 100644 index 4f898116c69f..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreVectorAttribute.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines an attribute to mark a property on a record class as a vector. -/// -/// -/// The characteristics defined here influence how the property is treated by the vector store. -/// -[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] -public sealed class VectorStoreVectorAttribute : Attribute -{ - /// - /// Initializes a new instance of the class. - /// - /// The number of dimensions that the vector has. - public VectorStoreVectorAttribute(int Dimensions) - { - if (Dimensions <= 0) - { - throw new ArgumentOutOfRangeException(nameof(Dimensions), "Dimensions must be greater than zero."); - } - - this.Dimensions = Dimensions; - } - - /// - /// Gets the number of dimensions that the vector has. - /// - /// - /// This property is required when creating collections, but can be omitted if not using that functionality. - /// If not provided when trying to create a collection, create will fail. - /// - public int Dimensions { get; private set; } - - /// - /// Gets or sets the kind of index to use. - /// - /// - /// The default value varies by database type. See the documentation of your chosen database connector for more information. - /// - /// -#pragma warning disable CA1019 // Define accessors for attribute arguments: The constructor overload that contains this property is obsolete. - public string? IndexKind { get; init; } -#pragma warning restore CA1019 - - /// - /// Gets or sets the distance function to use when comparing vectors. - /// - /// - /// The default value varies by database type. See the documentation of your chosen database connector for more information. - /// - /// -#pragma warning disable CA1019 // Define accessors for attribute arguments: The constructor overload that contains this property is obsolete. - public string? DistanceFunction { get; init; } -#pragma warning restore CA1019 - - /// - /// Gets or sets an optional name to use for the property in storage, if different from the property name. - /// - /// - /// For example, the property name might be "MyProperty" and the storage name might be "my_property". - /// - public string? StorageName { get; init; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/DistanceFunction.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/DistanceFunction.cs deleted file mode 100644 index 068caed55807..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/DistanceFunction.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines a list of well-known distance functions that can be used to compare vectors. -/// -/// -/// Not all Vector Store connectors support all distance functions, and some connectors might -/// support additional distance functions that aren't defined here. -/// For more information on what's supported, see the documentation for each connector. -/// -public static class DistanceFunction -{ - /// - /// Specifies the function that measures the cosine (angular) similarity between two vectors. - /// - /// - /// Cosine similarity measures only the angle between the two vectors, without taking into account the length of the vectors. - /// ConsineSimilarity = 1 - CosineDistance. - /// -1 means vectors are opposite. - /// 0 means vectors are orthogonal. - /// 1 means vectors are identical. - /// - public const string CosineSimilarity = nameof(CosineSimilarity); - - /// - /// Specifies the function that measures the cosine (angular) distance between two vectors. - /// - /// - /// CosineDistance = 1 - CosineSimilarity. - /// 2 means vectors are opposite. - /// 1 means vectors are orthogonal. - /// 0 means vectors are identical. - /// - public const string CosineDistance = nameof(CosineDistance); - - /// - /// Specifies the dot product similarity function, which measures both the length and angle between two vectors. - /// - /// - /// The higher the value, the more similar the vectors. - /// - public const string DotProductSimilarity = nameof(DotProductSimilarity); - - /// - /// Specifies the negative dot product similarity function, which measures both the length and angle between two vectors. - /// - /// - /// The value of NegativeDotProduct = -1 * DotProductSimilarity. - /// The higher the value, the greater the distance between the vectors and the less similar the vectors. - /// - public const string NegativeDotProductSimilarity = nameof(NegativeDotProductSimilarity); - - /// - /// Specifies the function that measures the Euclidean distance between two vectors. - /// - /// - /// Also known as l2-norm. - /// - public const string EuclideanDistance = nameof(EuclideanDistance); - - /// - /// Specifies the function that measures the Euclidean squared distance between two vectors. - /// - /// - /// Also known as l2-squared. - /// - public const string EuclideanSquaredDistance = nameof(EuclideanSquaredDistance); - - /// - /// Specifies the function that measures the number of differences between vectors at each dimension. - /// - public const string HammingDistance = nameof(HammingDistance); - - /// - /// Specifies the function that measures the Manhattan distance between two vectors. - /// - public const string ManhattanDistance = nameof(ManhattanDistance); -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/IndexKind.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/IndexKind.cs deleted file mode 100644 index 372f451e4c05..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/IndexKind.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines a list of well-known index types that can be used to index vectors. -/// -/// -/// Not all Vector Store connectors support all index types, and some connectors might -/// support additional index types that aren't defined here. For more information on what's -/// supported, see the documentation for each connector. -/// -public static class IndexKind -{ - /// - /// Specifies the Hierarchical Navigable Small World, which performs an approximate nearest neighbor (ANN) search. - /// - /// - /// This search has lower accuracy than exhaustive k nearest neighbor, but is faster and more efficient. - /// - public const string Hnsw = nameof(Hnsw); - - /// - /// Specifies the brute force search to find the nearest neighbors. - /// - /// - /// This search calculates the distances between all pairs of data points, so it has a linear time complexity that grows directly proportional to the number of points. - /// It's also referred to as "exhaustive k nearest neighbor" in some databases. - /// This search has high recall accuracy, but is slower and more expensive than HNSW. - /// It works better with smaller datasets. - /// - public const string Flat = nameof(Flat); - - /// - /// Specifies an Inverted File with Flat Compression. - /// - /// - /// This search is designed to enhance search efficiency by narrowing the search area through the use of neighbor partitions or clusters. - /// Also referred to as approximate nearest neighbor (ANN) search. - /// - public const string IvfFlat = nameof(IvfFlat); - - /// - /// Specifies the Disk-based Approximate Nearest Neighbor algorithm, which is designed for efficiently searching for approximate nearest neighbors (ANN) in high-dimensional spaces. - /// - /// - /// The primary focus of DiskANN is to handle large-scale datasets that can't fit entirely into memory, leveraging disk storage to store the data while maintaining fast search times. - /// - public const string DiskAnn = nameof(DiskAnn); - - /// - /// Specifies an index that compresses vectors using DiskANN-based quantization methods for better efficiency in the kNN search. - /// - public const string QuantizedFlat = nameof(QuantizedFlat); - - /// - /// Specifies a dynamic index that switches automatically from to indexes. - /// - public const string Dynamic = nameof(Dynamic); -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreCollectionDefinition.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreCollectionDefinition.cs deleted file mode 100644 index b7ba514b0adc..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreCollectionDefinition.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using Microsoft.Extensions.AI; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Describes the properties of a record in a vector store collection. -/// -/// -/// Each property contains additional information about how the property will be treated by the vector store. -/// -public sealed class VectorStoreCollectionDefinition -{ - private IList? _properties; - - /// - /// Gets or sets the list of properties that are stored in the record. - /// - [AllowNull] - public IList Properties - { - get => this._properties ??= []; - set => this._properties = value; - } - - /// - /// Gets or sets the default embedding generator for vector properties in this collection. - /// - public IEmbeddingGenerator? EmbeddingGenerator { get; set; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreDataProperty.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreDataProperty.cs deleted file mode 100644 index 0f1a7d764bde..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreDataProperty.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines a data property on a vector store record. -/// -/// -/// The characteristics defined here influence how the property is treated by the vector store. -/// -public sealed class VectorStoreDataProperty : VectorStoreProperty -{ - /// - /// Initializes a new instance of the class. - /// - /// The name of the property on the data model. If the record is mapped to a .NET type, this corresponds to the .NET property name on that type. - /// The type of the property. Required when using a record type of Dictionary<string, object?> (dynamic mapping), but can be omitted when mapping any other .NET type. - public VectorStoreDataProperty(string name, Type? type = null) - : base(name, type) - { - } - - /// - /// Gets or sets a value indicating whether this data property is indexed. - /// - /// - /// The default is . - /// - public bool IsIndexed { get; set; } - - /// - /// Gets or sets a value indicating whether this data property is indexed for full-text search. - /// - /// - /// The default is . - /// - public bool IsFullTextIndexed { get; set; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreKeyProperty.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreKeyProperty.cs deleted file mode 100644 index 2c2a6f6262f0..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreKeyProperty.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines a key property on a vector store record. -/// -/// -/// The characteristics defined here influence how the property is treated by the vector store. -/// -public sealed class VectorStoreKeyProperty : VectorStoreProperty -{ - /// - /// Initializes a new instance of the class. - /// - /// The name of the property on the data model. If the record is mapped to a .NET type, this corresponds to the .NET property name on that type. - /// The type of the property. Required when using a record type of Dictionary<string, object?> (dynamic mapping), but can be omitted when mapping any other .NET type. - public VectorStoreKeyProperty(string name, Type? type = null) - : base(name, type) - { - } - - /// - /// Gets or sets whether this key property's value is auto-generated or not. - /// - /// - /// The availability of auto-generated properties - as well as the .NET types supported for them - varies across provider implementations. - /// - public bool? IsAutoGenerated { get; set; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreProperty.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreProperty.cs deleted file mode 100644 index d3f2b8faced9..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreProperty.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines a base property class for properties on a vector store record. -/// -/// -/// The characteristics defined here influence how the property is treated by the vector store. -/// -public abstract class VectorStoreProperty -{ - /// - /// Initializes a new instance of the class. - /// - /// The name of the property on the data model. If the record is mapped to a .NET type, this corresponds to the .NET property name on that type. - /// The type of the property. - private protected VectorStoreProperty(string name, Type? type) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentException("Value cannot be null or whitespace.", nameof(name)); - } - - this.Name = name; - this.Type = type; - } - - private protected VectorStoreProperty(VectorStoreProperty source) - { - this.Name = source.Name; - this.StorageName = source.StorageName; - this.Type = source.Type; - this.ProviderAnnotations = source.ProviderAnnotations is not null - ? new Dictionary(source.ProviderAnnotations) - : null; - } - - /// - /// Gets or sets the name of the property on the data model. - /// - public string Name { get; set; } - - /// - /// Gets or sets an optional name to use for the property in storage, if different from the property name. - /// - /// - /// For example, the property name might be "MyProperty" and the storage name might be "my_property". - /// This property is only respected by implementations that don't support a well-known - /// serialization mechanism like JSON, in which case the attributes used by that serialization system will - /// be used. - /// - public string? StorageName { get; set; } - - /// - /// Gets or sets the type of the property. - /// - public Type? Type { get; set; } - - /// - /// Gets or sets a dictionary of provider-specific annotations for this property. - /// - /// - /// This allows setting database-specific configuration options that aren't universal across all vector stores. - /// Use provider-specific extension methods to set and get values in a strongly-typed manner. - /// - public Dictionary? ProviderAnnotations { get; set; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreVectorProperty.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreVectorProperty.cs deleted file mode 100644 index 54762c7ebe81..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreVectorProperty.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using Microsoft.Extensions.AI; -using Microsoft.Extensions.VectorData.ProviderServices; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines a vector property on a vector store record. -/// -/// -/// The characteristics defined here influence how the property is treated by the vector store. -/// -public class VectorStoreVectorProperty : VectorStoreProperty -{ - private int _dimensions; - - /// - /// Initializes a new instance of the class. - /// - /// The name of the property on the data model. If the record is mapped to a .NET type, this corresponds to the .NET property name on that type. - /// The number of dimensions that the vector has. - public VectorStoreVectorProperty(string name, int dimensions) - : base(name, type: null) - { - this.Dimensions = dimensions; - } - - /// - /// Initializes a new instance of the class. - /// - /// The name of the property on the data model. If the record is mapped to a .NET type, this corresponds to the .NET property name on that type. - /// The type of the property. - /// The number of dimensions that the vector has. - public VectorStoreVectorProperty(string name, Type type, int dimensions) - : base(name, type) - { - this.Dimensions = dimensions; - } - - /// - /// Gets or sets the default embedding generator to use for this property. - /// - /// - /// If not set, embedding generation will be performed in the database, if supported by your connector. - /// Otherwise, if your database does not support embedding generation, only pregenerated embeddings can be used (for example, ReadOnlyMemory<float>). - /// - public IEmbeddingGenerator? EmbeddingGenerator { get; set; } - - /// - /// Gets or sets the number of dimensions that the vector has. - /// - /// - /// This property is required when creating collections, but can be omitted if not using that functionality. - /// If not provided when trying to create a collection, create will fail. - /// - public int Dimensions - { - get => this._dimensions; - - set - { - if (value <= 0) - { - throw new ArgumentOutOfRangeException(nameof(value), "Dimensions must be greater than zero."); - } - - this._dimensions = value; - } - } - - /// - /// Gets or sets the kind of index to use. - /// - /// - /// The default varies by database type. See the documentation of your chosen database connector for more information. - /// - /// - public string? IndexKind { get; set; } - - /// - /// Gets or sets the distance function to use when comparing vectors. - /// - /// - /// The default varies by database type. See the documentation of your chosen database connector for more information. - /// - /// - public string? DistanceFunction { get; set; } - - /// - /// Gets or sets the desired embedding type (for example, Embedding<Half>) for cases where the default (typically Embedding<float>) isn't suitable. - /// - public Type? EmbeddingType { get; set; } - - internal virtual VectorPropertyModel CreatePropertyModel() - => new(this.Name, this.Type ?? throw new InvalidOperationException(VectorDataStrings.MissingTypeOnPropertyDefinition(this))) - { - Dimensions = this.Dimensions, - IndexKind = this.IndexKind, - DistanceFunction = this.DistanceFunction, - EmbeddingGenerator = this.EmbeddingGenerator, - EmbeddingType = this.EmbeddingType! - }; -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreVectorProperty{TInput}.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreVectorProperty{TInput}.cs deleted file mode 100644 index 23a63b27604c..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordDefinition/VectorStoreVectorProperty{TInput}.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using Microsoft.Extensions.AI; -using Microsoft.Extensions.VectorData.ProviderServices; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines a vector property on a vector store record. -/// -/// -/// -/// The characteristics defined here influence how the property is treated by the vector store. -/// -/// -/// This generic version of only needs to be used when an is -/// configured on the property, and a custom .NET type is used as input (any type other than or ). -/// -/// -public class VectorStoreVectorProperty : VectorStoreVectorProperty -{ - /// - public VectorStoreVectorProperty(string propertyName, int dimensions) - : base(propertyName, typeof(TInput), dimensions) - { - } - - internal override VectorPropertyModel CreatePropertyModel() - => new VectorPropertyModel(this.Name) - { - Dimensions = this.Dimensions, - IndexKind = this.IndexKind, - DistanceFunction = this.DistanceFunction, - EmbeddingGenerator = this.EmbeddingGenerator - }; -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordOptions/FilteredRecordRetrievalOptions.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordOptions/FilteredRecordRetrievalOptions.cs deleted file mode 100644 index 0ef217b8b4de..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordOptions/FilteredRecordRetrievalOptions.cs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Threading; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines options for calling . -/// -/// The type of the record. -public sealed class FilteredRecordRetrievalOptions -{ - private int _skip = 0; - - /// - /// Gets or sets the number of results to skip before returning results, that is, the index of the first result to return. - /// - /// The value is less than 0. - public int Skip - { - get => this._skip; - set - { - if (value < 0) - { - throw new ArgumentOutOfRangeException(nameof(value), "Skip must be greater than or equal to 0."); - } - - this._skip = value; - } - } - - /// - /// Gets or sets the data property to order by. - /// - /// - /// If not provided, the order of returned results is non-deterministic. - /// - public Func? OrderBy { get; set; } - - /// - /// Gets or sets a value indicating whether to include vectors in the retrieval result. - /// - public bool IncludeVectors { get; set; } - - /// - /// Represents a builder for sorting. - /// - // This type does not derive any collection in order to avoid Intellisense suggesting LINQ methods. - public sealed class OrderByDefinition - { - private readonly List _values = []; - - /// - /// Gets the expressions to sort by. - /// - /// This property is intended to be consumed by the connectors to retrieve the configuration. - public IReadOnlyList Values => this._values; - - /// - /// Creates an ascending sort. - /// - public OrderByDefinition Ascending(Expression> propertySelector) - { - if (propertySelector is null) - { - throw new ArgumentNullException(nameof(propertySelector)); - } - - this._values.Add(new(propertySelector, true)); - return this; - } - - /// - /// Creates a descending sort. - /// - public OrderByDefinition Descending(Expression> propertySelector) - { - if (propertySelector is null) - { - throw new ArgumentNullException(nameof(propertySelector)); - } - - this._values.Add(new(propertySelector, false)); - return this; - } - - /// - /// Provides a way to define property ordering. - /// - /// This class is intended to be consumed by the connectors to retrieve the configuration. - public sealed class SortInfo - { - internal SortInfo(Expression> propertySelector, bool isAscending) - { - this.PropertySelector = propertySelector; - this.Ascending = isAscending; - } - - /// - /// Gets the expression to select the property to sort by. - /// - public Expression> PropertySelector { get; } - - /// - /// Gets a value that indicates whether the sort is ascending; otherwise, false. - /// - /// - /// if the sort is ascending; otherwise, . - /// - public bool Ascending { get; } - } - } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/RecordOptions/RecordRetrievalOptions.cs b/dotnet/src/VectorData/VectorData.Abstractions/RecordOptions/RecordRetrievalOptions.cs deleted file mode 100644 index ac17b697136e..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/RecordOptions/RecordRetrievalOptions.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System.Collections.Generic; -using System.Threading; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines options for calling -/// or . -/// -public class RecordRetrievalOptions -{ - /// - /// Gets or sets a value indicating whether to include vectors in the retrieval result. - /// - public bool IncludeVectors { get; set; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/Throw.cs b/dotnet/src/VectorData/VectorData.Abstractions/Throw.cs deleted file mode 100644 index 42682c708155..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/Throw.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -internal static class Throw -{ - /// Throws an exception indicating that a required service is not available. - public static InvalidOperationException CreateMissingServiceException(Type serviceType, object? serviceKey) => - new(serviceKey is null ? - $"No service of type '{serviceType}' is available." : - $"No service of type '{serviceType}' for the key '{serviceKey}' is available."); -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorData.Abstractions.csproj b/dotnet/src/VectorData/VectorData.Abstractions/VectorData.Abstractions.csproj deleted file mode 100644 index ea63dd6f4065..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorData.Abstractions.csproj +++ /dev/null @@ -1,71 +0,0 @@ - - - - Microsoft.Extensions.VectorData.Abstractions - Microsoft.Extensions.VectorData - net10.0;net8.0;netstandard2.0;net462 - true - - false - - - - - - 10.1.0 - 10.0.0.0 - - 10.0.1 - Microsoft.Extensions.VectorData.Abstractions - $(AssemblyName) - Abstractions for vector database access. - -Commonly Used Types: -Microsoft.Extensions.VectorData.IVectorStore -Microsoft.Extensions.VectorData.IVectorStoreRecordCollection<TKey, TRecord> - neticon.png - neticon.png - PACKAGE.md - - Vector, Database, SDK - $(PackageDescription) - https://dot.net/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/HybridSearchOptions.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/HybridSearchOptions.cs deleted file mode 100644 index e3ca2cc0b430..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/HybridSearchOptions.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Linq.Expressions; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines options for hybrid search when using a dense vector and string keywords to do the search. -/// -public class HybridSearchOptions -{ - private int _skip = 0; - - /// - /// Gets or sets a search filter to use before doing the hybrid search. - /// - public Expression>? Filter { get; set; } - - /// - /// Gets or sets the target dense vector property to search on. - /// Only needs to be set when the collection has multiple vector properties. - /// - /// - /// If this property isn't set, checks if there is a vector property to use by default, and - /// throws if either none or multiple exist. - /// - public Expression>? VectorProperty { get; set; } - - /// - /// Gets or sets the additional target property to do the text or keyword search on. - /// The property must have full text indexing enabled. - /// - /// - /// If this property isn't set, checks if there is a text property with full text indexing enabled, and - /// throws an exception if either none or multiple exist. - /// - public Expression>? AdditionalProperty { get; set; } - - /// - /// Gets or sets the number of results to skip before returning results, that is, the index of the first result to return. - /// - /// The value is less than 0. - public int Skip - { - get => this._skip; - set - { - if (value < 0) - { - throw new ArgumentOutOfRangeException(nameof(value), "Skip must be greater than or equal to 0."); - } - - this._skip = value; - } - } - - /// - /// Gets or sets a value indicating whether to include vectors in the retrieval result. - /// - public bool IncludeVectors { get; set; } - - /// - /// Gets or sets the score threshold to filter results. - /// - /// - /// - /// The meaning of the score is a combination of the distance function configured for and the text - /// relevance score for the full-text search on . - /// - /// - /// The range of scores also depends on the distance function; for example, cosine similarity/distance scores - /// fall within 0 to 1, while Euclidean distance is unbounded. Scores can also differ between vector databases. - /// - /// - public double? ScoreThreshold { get; set; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/IKeywordHybridSearchable.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/IKeywordHybridSearchable.cs deleted file mode 100644 index d0bb9ee95c00..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/IKeywordHybridSearchable.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; -using Microsoft.Extensions.AI; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Contains a method for performing a hybrid search using a vector and keywords. -/// -/// The record data model to use for retrieving data from the store. -public interface IKeywordHybridSearchable -{ - /// - /// Performs a hybrid search for records that match the given embedding and keywords, after applying the provided filters. - /// - /// The type of the input value on which to perform the vector similarity search. - /// The value on which to perform the similarity search. See the remarks section for more details. - /// A collection of keywords to search the store with. - /// The maximum number of results to return. - /// The options that control the behavior of the search. - /// The to monitor for cancellation requests. The default is . - /// The records found by the hybrid search, including their result scores. - /// - /// The types supported for the vary based on the provider being used and the embedding generation configured: - /// - /// - /// - /// A or (for images, sound...) if an appropriate has been configured that accepts that type as input. - /// For example, register an that accepts as input in your dependency injection container, and then pass in a - /// argument to this method; the argument will be automatically passed to the to generate the embedding and perform the search. - /// Some databases support generating embeddings at the database side. In this case, you can pass in a or without configuring an - /// with Microsoft.Extensions.VectorData. The provider will simply send your argument to the database as-is for embedding generation. - /// - /// - /// Arbitrary .NET types can also be passed in as long as an appropriate has been configured; for example, you can create your own - /// that accepts your own custom types as input, and uses another to generate embedding from multiple properties. For .NET types beyond and - /// , you must use the generic in your record definition. - /// - /// - /// To work with embeddings directly, pass in a or a .NET array of the appropriate type. Most providers support at least ReadOnlyMemory<float> and float[], - /// but some support other types (for example, ReadOnlyMemory<Half>, ). Some providers might also support their own custom types as well, for example, to represent sparse embeddings. - /// Consult your provider's documentation for supported types. - /// - /// - /// If you're using directly in your code, that type returns an (for example, Embedding{float}), - /// which can also be passed in directly, as long as the provider supports the specific embedding type. However, consider registering your with the provider - /// instead and pass in the input type (for example, ). - /// - /// - /// - IAsyncEnumerable> HybridSearchAsync( - TInput searchValue, - ICollection keywords, - int top, - HybridSearchOptions? options = default, - CancellationToken cancellationToken = default) - where TInput : notnull; - - /// Asks the for an object of the specified type . - /// The type of object being requested. - /// An optional key that can be used to help identify the target service. - /// The found object, otherwise . - /// is . - /// - /// The purpose of this method is to allow for the retrieval of strongly typed services that might be provided by the , - /// including itself or any services it might be wrapping. For example, to access the for the instance, - /// can be used to request it. - /// - object? GetService(Type serviceType, object? serviceKey = null); -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/IVectorSearchable.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/IVectorSearchable.cs deleted file mode 100644 index 8d6dc76e8daf..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/IVectorSearchable.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; -using Microsoft.Extensions.AI; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines an interface for performing vector searches on a vector store. -/// -/// The record data model to use for retrieving data from the store. -public interface IVectorSearchable -{ - /// - /// Searches the vector store for records that are similar to the given value. - /// - /// The type of the input value on which to perform the similarity search. - /// The value on which to perform the similarity search. See the remarks section for more details. - /// The maximum number of results to return. - /// The options that control the behavior of the search. - /// The to monitor for cancellation requests. The default is . - /// The records found by the vector search, including their result scores. - /// - /// The types supported for the vary based on the provider being used and the embedding generation configured: - /// - /// - /// - /// A or (for images, sound...) if an appropriate has been configured that accepts that type as input. - /// For example, register an that accepts as input in your dependency injection container, and then pass in a - /// argument to this method; the argument will be automatically passed to the to generate the embedding and perform the search. - /// Some databases support generating embeddings at the database side. In this case, you can pass in a or without configuring an - /// with Microsoft.Extensions.VectorData. The provider will simply send your argument to the database as-is for embedding generation. - /// - /// - /// Arbitrary .NET types can also be passed in as long as an appropriate has been configured; for example, you can create your own - /// that accepts your own custom types as input, and uses another to generate embedding from multiple properties. For .NET types beyond and - /// , you must use the generic in your record definition. - /// - /// - /// To work with embeddings directly, pass in a or a .NET array of the appropriate type. Most providers support at least ReadOnlyMemory<float> and float[], - /// but some support other types (for example, ReadOnlyMemory<Half>, ). Some providers might also support their own custom types as well, for example, to represent sparse embeddings. - /// Consult your provider's documentation for supported types. - /// - /// - /// If you're using directly in your code, that type returns an (for example, Embedding{float}), - /// which can also be passed in directly, as long as the provider supports the specific embedding type. However, consider registering your with the provider - /// instead and pass in the input type (for example, ). - /// - /// - /// - IAsyncEnumerable> SearchAsync( - TInput searchValue, - int top, - VectorSearchOptions? options = default, - CancellationToken cancellationToken = default) - where TInput : notnull; - - /// Asks the for an object of the specified type . - /// The type of object being requested. - /// An optional key that can be used to help identify the target service. - /// The found object, otherwise . - /// is . - /// - /// The purpose of this method is to allow for the retrieval of strongly typed services that might be provided by the , - /// including itself or any services it might be wrapping. For example, to access the for the instance, - /// can be used to request it. - /// - object? GetService(Type serviceType, object? serviceKey = null); -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/KeywordHybridSearchExtensions.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/KeywordHybridSearchExtensions.cs deleted file mode 100644 index dea184745fb9..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/KeywordHybridSearchExtensions.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// Provides a collection of static methods for extending instances. -public static class KeywordHybridSearchExtensions -{ - /// - /// Asks the for an object of the specified type - /// and throw an exception if one isn't available. - /// - /// The record data model to use for retrieving data from the store. - /// The keyword hybrid search. - /// The type of object being requested. - /// An optional key that can be used to help identify the target service. - /// The found object. - /// is . - /// is . - /// No service of the requested type for the specified key is available. - public static object GetRequiredService(this IKeywordHybridSearchable keywordHybridSearch, Type serviceType, object? serviceKey = null) - { - if (keywordHybridSearch is null) { throw new ArgumentNullException(nameof(keywordHybridSearch)); } - if (serviceType is null) { throw new ArgumentNullException(nameof(serviceType)); } - - return - keywordHybridSearch.GetService(serviceType, serviceKey) ?? - throw Throw.CreateMissingServiceException(serviceType, serviceKey); - } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/RecordSearchOptions.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/RecordSearchOptions.cs deleted file mode 100644 index 207034bd95c9..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/RecordSearchOptions.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Linq.Expressions; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines options for vector search via . -/// -public class VectorSearchOptions -{ - private int _skip = 0; - - /// - /// Gets or sets a search filter to use before doing the vector search. - /// - public Expression>? Filter { get; set; } - - /// - /// Gets or sets the vector property to search on. - /// Only needs to be set when the collection has multiple vector properties. - /// - /// - /// If this property isn't set provided, checks if there is a vector property to use by default, and - /// throws an exception if either none or multiple exist. - /// - public Expression>? VectorProperty { get; set; } - - /// - /// Gets or sets the number of results to skip before returning results, that is, the index of the first result to return. - /// - /// The value is less than 0. - public int Skip - { - get => this._skip; - set - { - if (value < 0) - { - throw new ArgumentOutOfRangeException(nameof(value), "Skip must be greater than or equal to 0."); - } - - this._skip = value; - } - } - - /// - /// Gets or sets a value indicating whether to include vectors in the retrieval result. - /// - public bool IncludeVectors { get; set; } - - /// - /// Gets or sets the score threshold to filter results. - /// - /// - /// - /// The meaning of the score depends on the distance function configured for the vector property. - /// For similarity functions (e.g. , ), - /// higher scores indicate more similar results, and results with scores lower than the threshold will be filtered out. - /// For distance functions (e.g. , ), - /// lower scores indicate more similar results, and results with scores higher than the threshold will be filtered out. - /// - /// - /// The range of scores also depends on the distance function; for example, cosine similarity/distance scores - /// fall within 0 to 1, while Euclidean distance is unbounded. Scores can also differ between vector databases. - /// - /// - public double? ScoreThreshold { get; set; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/VectorSearchExtensions.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/VectorSearchExtensions.cs deleted file mode 100644 index 65e931c99d4e..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/VectorSearchExtensions.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// Provides a collection of static methods for extending instances. -public static class VectorSearchExtensions -{ - /// - /// Asks the for an object of the specified type - /// and throws an exception if one isn't available. - /// - /// The record data model to use for retrieving data from the store. - /// The vector search. - /// The type of object being requested. - /// An optional key that can be used to help identify the target service. - /// The found object. - /// is . - /// is . - /// No service of the requested type for the specified key is available. - public static object GetRequiredService(this IVectorSearchable vectorSearch, Type serviceType, object? serviceKey = null) - { - if (vectorSearch is null) { throw new ArgumentNullException(nameof(vectorSearch)); } - if (serviceType is null) { throw new ArgumentNullException(nameof(serviceType)); } - - return - vectorSearch.GetService(serviceType, serviceKey) ?? - throw Throw.CreateMissingServiceException(serviceType, serviceKey); - } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/VectorSearchResult.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/VectorSearchResult.cs deleted file mode 100644 index f5793844d674..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorSearch/VectorSearchResult.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -namespace Microsoft.Extensions.VectorData; - -/// -/// Represents a single search result from a vector search. -/// -/// The record data model to use for retrieving data from the store. -public sealed class VectorSearchResult -{ - /// - /// Initializes a new instance of the class. - /// - /// The record that was found by the search. - /// The score of this result in relation to the search query. - public VectorSearchResult(TRecord record, double? score) - { - this.Record = record; - this.Score = score; - } - - /// - /// Gets the record that was found by the search. - /// - public TRecord Record { get; } - - /// - /// Gets the score of this result in relation to the search query. - /// - public double? Score { get; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStore.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStore.cs deleted file mode 100644 index ab284796fd6b..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStore.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Represents a vector store that contains collections of records. -/// -/// -/// This type can be used with collections of any schema type, but requires you to provide schema information when getting a collection. -/// Unless otherwise documented, implementations of this abstract base class can be expected to be thread-safe, and can be used concurrently from multiple threads. -/// -public abstract class VectorStore : IDisposable -{ - /// - /// Gets a collection from the vector store. - /// - /// The data type of the record key. - /// The record data model to use for adding, updating, and retrieving data from the collection. - /// The name of the collection. - /// The schema of the record type. - /// A new instance for managing the records in the collection. - /// - /// To successfully request a collection, either must be annotated with attributes that define the schema of - /// the record type, or must be provided. - /// - /// - /// - /// - [RequiresDynamicCode("This API is not compatible with NativeAOT. For dynamic mapping via Dictionary, use GetCollectionDynamic() instead.")] - [RequiresUnreferencedCode("This API is not compatible with trimming. For dynamic mapping via Dictionary, use GetCollectionDynamic() instead.")] - public abstract VectorStoreCollection GetCollection(string name, VectorStoreCollectionDefinition? definition = null) - where TKey : notnull - where TRecord : class; - - /// - /// Gets a collection from the vector store, using dynamic mapping; the record type is represented as a . - /// - /// The name of the collection. - /// The schema of the record type. - /// A new instance for managing the records in the collection. - public abstract VectorStoreCollection> GetDynamicCollection(string name, VectorStoreCollectionDefinition definition); - - /// - /// Retrieves the names of all the collections in the vector store. - /// - /// The to monitor for cancellation requests. The default is . - /// The list of names of all the collections in the vector store. - public abstract IAsyncEnumerable ListCollectionNamesAsync(CancellationToken cancellationToken = default); - - /// - /// Checks if the collection exists in the vector store. - /// - /// The name of the collection. - /// The to monitor for cancellation requests. The default is . - /// if the collection exists, otherwise. - public abstract Task CollectionExistsAsync(string name, CancellationToken cancellationToken = default); - - /// - /// Deletes the collection from the vector store. - /// - /// The name of the collection to delete. - /// The to monitor for cancellation requests. The default is . - /// A that completes when the collection has been deleted. - public abstract Task EnsureCollectionDeletedAsync(string name, CancellationToken cancellationToken = default); - - /// Asks the for an object of the specified type . - /// The type of object being requested. - /// An optional key that can be used to help identify the target service. - /// The found object, otherwise . - /// is . - /// - /// The purpose of this method is to allow for the retrieval of strongly typed services that might be provided by the , - /// including itself or any services it might be wrapping. For example, to access the for the instance, - /// can be used to request it. - /// - public abstract object? GetService(Type serviceType, object? serviceKey = null); - - /// - /// Disposes the and releases any resources it holds. - /// - /// if called from ; if called from a finalizer. - protected virtual void Dispose(bool disposing) - { - } - - /// - public void Dispose() - { - this.Dispose(disposing: true); - GC.SuppressFinalize(this); - } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollection.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollection.cs deleted file mode 100644 index cf5636215712..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollection.cs +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.SemanticKernel; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Represents a named collection of records in a vector store, and can be used to search and manage records, and to create or delete the collection itself. -/// -/// The data type of the record key. -/// The record data model to use for adding, updating, and retrieving data from the store. -/// -/// Unless otherwise documented, implementations of this abstract base class can be expected to be thread-safe, and can be used concurrently from multiple threads. -/// -#pragma warning disable CA1711 // Identifiers should not have incorrect suffix (Collection) -public abstract class VectorStoreCollection : IVectorSearchable, IDisposable -#pragma warning restore CA1711 - where TKey : notnull - where TRecord : class -{ - /// - /// Gets the name of the collection. - /// - public abstract string Name { get; } - - /// - /// Checks if the collection exists in the vector store. - /// - /// The to monitor for cancellation requests. The default is . - /// if the collection exists, otherwise. - public abstract Task CollectionExistsAsync(CancellationToken cancellationToken = default); - - /// - /// Creates this collection in the vector store if it doesn't already exist. - /// - /// The to monitor for cancellation requests. The default is . - /// A that completes when the collection has been created. - public abstract Task EnsureCollectionExistsAsync(CancellationToken cancellationToken = default); - - /// - /// Deletes the collection from the vector store if it exists. - /// - /// The to monitor for cancellation requests. The default is . - /// A that completes when the collection has been deleted. - public abstract Task EnsureCollectionDeletedAsync(CancellationToken cancellationToken = default); - - /// - /// Gets a record from the vector store. Does not guarantee that the collection exists. - /// Returns null if the record is not found. - /// - /// The unique ID associated with the record to get. - /// Optional options for retrieving the record. - /// The to monitor for cancellation requests. The default is . - /// The record if found, otherwise null. - /// The command fails to execute for any reason. - public abstract Task GetAsync(TKey key, RecordRetrievalOptions? options = default, CancellationToken cancellationToken = default); - - /// - /// Gets a batch of records from the vector store. Does not guarantee that the collection exists. - /// - /// The unique IDs associated with the record to get. - /// Optional options for retrieving the records. - /// The to monitor for cancellation requests. The default is . - /// The records associated with the specified unique keys. - /// - /// - /// The exact method of retrieval is implementation-specific and can vary based on database support. - /// The default implementation of this method retrieves the records one after the other, but implementations which supporting batching can override to provide a more efficient implementation. - /// - /// - /// Only found records are returned, so the result set might be smaller than the requested keys. - /// - /// - /// This method throws for any issues other than records not being found. - /// - /// - /// The command fails to execute for any reason. - public virtual async IAsyncEnumerable GetAsync(IEnumerable keys, RecordRetrievalOptions? options = default, [EnumeratorCancellation] CancellationToken cancellationToken = default) - { - Verify.NotNull(keys); - - foreach (var key in keys) - { - var record = await this.GetAsync(key, options, cancellationToken).ConfigureAwait(false); - - if (record is not null) - { - yield return record; - } - } - } - - /// - /// Deletes a record from the vector store. Does not guarantee that the collection exists. - /// - /// The unique ID associated with the record to remove. - /// The to monitor for cancellation requests. The default is . - /// The unique identifier for the record. - /// The command fails to execute for any reason other than that the record does not exist. - public abstract Task DeleteAsync(TKey key, CancellationToken cancellationToken = default); - - /// - /// Deletes a batch of records from the vector store. Does not guarantee that the collection exists. - /// - /// The unique IDs associated with the records to remove. - /// The to monitor for cancellation requests. The default is . - /// A that completes when the records have been deleted. - /// - /// - /// The exact method of deleting is implementation-specific and can vary based on database support. - /// The default implementation of this method deletes the records one after the other, but implementations which supporting batching can override to provide a more efficient implementation. - /// - /// - /// If a record isn't found, it is ignored and the batch succeeds. - /// If any record can't be deleted for any other reason, the operation throws. Some records might have already been deleted while others might not have, so the entire operation should be retried. - /// - /// - /// The command fails to execute for any reason other than that a record does not exist. - public virtual async Task DeleteAsync(IEnumerable keys, CancellationToken cancellationToken = default) - { - Verify.NotNull(keys); - - foreach (var key in keys) - { - await this.DeleteAsync(key, cancellationToken).ConfigureAwait(false); - } - } - - /// - /// Upserts a record into the vector store. Does not guarantee that the collection exists. - /// If the record already exists, it is updated. - /// If the record does not exist, it is created. - /// - /// The record to upsert. - /// The to monitor for cancellation requests. The default is . - /// The command fails to execute for any reason. - public abstract Task UpsertAsync(TRecord record, CancellationToken cancellationToken = default); - - /// - /// Upserts a batch of records into the vector store. Does not guarantee that the collection exists. - /// If the record already exists, it is updated. - /// If the record does not exist, it is created. - /// - /// The records to upsert. - /// The to monitor for cancellation requests. The default is . - /// - /// - /// The exact method of upserting the batch is implementation-specific and can vary based on database support. - /// - /// - /// Similarly, the error behavior can vary across databases: where possible, the batch should be upserted atomically, so that any errors cause the entire batch to be rolled - /// back. Where not supported, some records might be upserted while others are not. If key properties are set by the user, then the entire upsert operation is idempotent, - /// and can simply be retried again if an error occurs. However, if store-generated keys are in use, the upsert operation is no longer idempotent; in that case, if the - /// database doesn't guarantee atomicity, retrying could cause duplicate records to be created. - /// - /// - /// Implementations of should implement this method in a way which performs embedding generation once for the batch, rather than - /// generating an embedding for each record separately. This is why a default implementation that calls is not provided. - /// - /// - /// The command fails to execute for any reason. - public abstract Task UpsertAsync(IEnumerable records, CancellationToken cancellationToken = default); - - /// - /// Gets matching records from the vector store. Does not guarantee that the collection exists. - /// - /// The predicate to filter the records. - /// The maximum number of results to return. - /// Options for retrieving the records. - /// The to monitor for cancellation requests. The default is . - /// The records that match the given predicate. - /// The command fails to execute for any reason. - public abstract IAsyncEnumerable GetAsync(Expression> filter, int top, FilteredRecordRetrievalOptions? options = null, CancellationToken cancellationToken = default); - - /// - public abstract IAsyncEnumerable> SearchAsync(TInput searchValue, int top, VectorSearchOptions? options = null, CancellationToken cancellationToken = default) - where TInput : notnull; - - /// - public abstract object? GetService(Type serviceType, object? serviceKey = null); - - /// - /// Disposes the and releases any resources it holds. - /// - /// if called from ; if called from a finalizer. - protected virtual void Dispose(bool disposing) - { - } - - /// - public void Dispose() - { - this.Dispose(disposing: true); - GC.SuppressFinalize(this); - } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollectionMetadata.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollectionMetadata.cs deleted file mode 100644 index f36fe294ce63..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollectionMetadata.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -namespace Microsoft.Extensions.VectorData; - -/// Provides metadata about an . -public class VectorStoreCollectionMetadata -{ - /// Gets or sets the name of the vector store system. - /// - /// Where possible, this value maps to the "db.system.name" attribute defined in the - /// OpenTelemetry Semantic Conventions for database calls and systems; see . - /// Example: redis, sqlite, mysql. - /// - public string? VectorStoreSystemName { get; init; } - - /// - /// Gets or sets the name of the vector store (database). - /// - public string? VectorStoreName { get; init; } - - /// - /// Gets or sets the name of a collection (table, container) within the vector store (database). - /// - public string? CollectionName { get; init; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollectionOptions.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollectionOptions.cs deleted file mode 100644 index 04f67aae662b..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreCollectionOptions.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using Microsoft.Extensions.AI; - -namespace Microsoft.Extensions.VectorData; - -/// Defines an abstract base class for options passed to a collection. -public abstract class VectorStoreCollectionOptions -{ - /// - /// Initializes a new instance of the class. - /// - protected VectorStoreCollectionOptions() - { - } - - /// - /// Initializes a new instance of the class. - /// - protected VectorStoreCollectionOptions(VectorStoreCollectionOptions? source) - { - this.Definition = source?.Definition; - this.EmbeddingGenerator = source?.EmbeddingGenerator; - } - - /// - /// Gets or sets an optional record definition that defines the schema of the record type. - /// - /// - /// If not provided, the schema will be inferred from the record model class using reflection. - /// In this case, the record model properties must be annotated with the appropriate attributes to indicate their usage. - /// See , , and . - /// - public VectorStoreCollectionDefinition? Definition { get; set; } - - /// - /// Gets or sets the default embedding generator to use when generating vectors embeddings with this collection. - /// - public IEmbeddingGenerator? EmbeddingGenerator { get; set; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreException.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreException.cs deleted file mode 100644 index a90599b34142..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreException.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// -/// Defines a base exception type for any type of failure when using vector stores. -/// -public class VectorStoreException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - public VectorStoreException() - { - } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The error message that explains the reason for the exception. - public VectorStoreException(string? message) : base(message) - { - } - - /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that's the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that's the cause of the current exception, or a null reference if no inner exception is specified. - public VectorStoreException(string? message, Exception? innerException) : base(message, innerException) - { - } - - /// Gets or sets the name of the vector store system. - /// - /// Where possible, this value maps to the "db.system.name" attribute defined in the - /// OpenTelemetry Semantic Conventions for database calls and systems; see . - /// Example: redis, sqlite, mysql. - /// - public string? VectorStoreSystemName { get; init; } - - /// - /// Gets or sets the name of the vector store (database). - /// - public string? VectorStoreName { get; init; } - - /// - /// Gets or sets the name of the vector store collection that the failing operation was performed on. - /// - public string? CollectionName { get; init; } - - /// - /// Gets or sets the name of the vector store operation that failed. - /// - public string? OperationName { get; init; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreExtensions.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreExtensions.cs deleted file mode 100644 index ceeecb8166bb..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreExtensions.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.Extensions.VectorData; - -/// Provides a collection of static methods for extending instances. -public static class VectorStoreExtensions -{ - /// - /// Asks the for an object of the specified type - /// and throws an exception if one isn't available. - /// - /// The record data model to use for retrieving data from the store. - /// The vector store. - /// The type of object being requested. - /// An optional key that can be used to help identify the target service. - /// The found object. - /// is . - /// is . - /// No service of the requested type for the specified key is available. - public static object GetRequiredService(this VectorStore vectorStore, Type serviceType, object? serviceKey = null) - { - if (vectorStore is null) { throw new ArgumentNullException(nameof(vectorStore)); } - if (serviceType is null) { throw new ArgumentNullException(nameof(serviceType)); } - - return - vectorStore.GetService(serviceType, serviceKey) ?? - throw Throw.CreateMissingServiceException(serviceType, serviceKey); - } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreMetadata.cs b/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreMetadata.cs deleted file mode 100644 index 97571a0691bf..000000000000 --- a/dotnet/src/VectorData/VectorData.Abstractions/VectorStorage/VectorStoreMetadata.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -namespace Microsoft.Extensions.VectorData; - -/// Provides metadata about an . -public class VectorStoreMetadata -{ - /// Gets or sets the name of the vector store system. - /// - /// Where possible, this value maps to the "db.system.name" attribute defined in the - /// OpenTelemetry Semantic Conventions for database calls and systems; see . - /// Example: redis, sqlite, mysql. - /// - public string? VectorStoreSystemName { get; init; } - - /// - /// Gets or sets the name of the vector store (database). - /// - public string? VectorStoreName { get; init; } -} diff --git a/dotnet/src/VectorData/VectorData.Abstractions/neticon.png b/dotnet/src/VectorData/VectorData.Abstractions/neticon.png deleted file mode 100644 index a0f1fdbf4d5eae0e561018cccee74f6a454cdb9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7006 zcmeHMXH-+`n%)#eMU;C)kZw7O2nvFLpcE@A^-u+AN(mh$UH*JD5Jjm{4}uUR zs5C(zdURn*zrcHqdVxK)P)7322TAMVbNR4HRzo3_~zdgjvf?Ot98@H{LHdy zK*)TM=g&B9f}+9IKfm=aF5e3_{PQJ$ zY4?9DHvtd+Y14o8TQs=)&+P)Wjb3|LIT@*NDqyYm#gu^q*EFSow<%yKVx`_Ka)!0 z2YAaQr%LYyQ%n$Rjx)e%JeM5_ov70FUMveJTS(J+%C4(L)~h*MQ8!wJtf_X{`Ol?k z;{27%#**2uiR&R6-eaRK1Mdgl2xHQ=uS(~VqsTVrsUnQhc zRIK5>@(05w3gHYdsI0;;sOO66pUEl)DGyD(D4>$7drUDFZ|uxx;-nWj7d|rj=u+D@ z-HU+mLOInrsXdSL1Z6nVB&D z@>f4!yq=_B+16+qw5k=4o#*tf;6Oe*F;`&L!)bT{U7Wc3YmG2;NRxb%woCt~*Yr2E zfwiUdS=7SK&5>df-aqY8lp~SEUG*ziXGvHMLp_#vgvVMQ*&{+d@(a>v4;7p_%Jte0Ga5zNbUI28WAgY5f?FX^;q`1WTw2~t|P54N&e^@=nFqDj}W#o z_-kZBWDQ%($YJH43Y7YrbjfsUrAEjla>?j0;YLdXxjK}P@xDGc%r&c)6`t?XW=*{r z%Z^p)?6*7obKU_;NZK_ejh9n&?qzO0#(}Uo+KSm|e}q1+f$wM!G8>lLvKK1UK^uz5 zDk&5(DuUnzQy{aQ8%b~*_4Ri`TOj}Dd{0OCls}^VD8=qDC%Q9tSSt5LZoxd!|ai3oGtf&cOy(`^W9zMNR;bII|OS+Pe(-9=f!m6}w zV>f(mH^BYE-=Wl=)Q2s2TF*j&tRkN0KOu3-(VN?4?-v|?W^Xj)@u4^bNB%bN+f|D= z?r1ey$UbahYv!qISaxV8>+1Mnz!M&S1o+~titx|65MA`iQMjscL!+LOGjZ?p>}x6d z4`FiZV9i-E6F8c|Fq37-TTTtJOdIZ9<*YrJU86UuQr6dipNC%AxT?lXa9U=`iq+2= zOT!CFUlJM1&INj~InR!=@x@{Z8BnvgL~_>nN)y@!r<0$uGCJ<0B-q!vZn@~#5^Ig8B}}g&dYBee=x50Wv$R^^f%aTE~g_a7&8Y(5L>! zkYgCl@1ZVqFSwkH(ns-EtYbOFLrarf#r6W9#x8rO<<_6h33faYV{<&_gBahO#ga9j z$|}=ea)vEm|Hb`E%L9Gn#Osxg( z&sxXz7lsse+_i@<_LUl@8$916h*m6!R?~zr_ZQU^H3F(aC1is#I$VP$GO(s!pT&Y# z85JYcwQqu6Ja6sje&x*)nOdx;bt1hNMTSwSikFeKE)+MRrW?mg=8mp^AR_kz{C%e* z32H_>c600^d$9)ob+$yzpyxHa+k0Sz7GG41I0A59bKJf?X}E6mX$pU~Wc%_?$2w1s zZEbk$svZ4U+WH;XPEb^-IqhGQX1U|z8KWp8&jVlWFPP+7Um6;oMy?>TFU`cMT5bYx z;7_~MfZ(sumPQHg++U)9PT=+=zxu+qmP==xJ&oI%XgD8=YZo%*rGq2U_J^D4d%7H`}jau-;<_^n?THcf9*rKD^J#%p%l zA8DILPr+wPY^MpxQbxGXG2f0xcjxSw;wjl53EsXe0poYHgfc(T;v5J;H$neUhElxe zrX0NdQ4e#4L4e-JmsN$%C+#BKX8TYA1YlhN`|QyqnlH{Igil*i0?NrD9qi2Fw_&~eMSk3UGyWzcay4oPaWE~nJ{R}-u+%oE z^4pk7G%~M66x6$a(@21!KD)Us1JG?!Xn4Zb;NYOn2SGc%JK!@mQv*PGMGxMb{#a4F z_#t!~GhhJR9)$w;fi20azFx86@7j4yB zpC7-bK<170rK@aOPg zDv69Iy;oMY0yq-ORy`~=Y8>ZQ_}+6m=ElBFD(BO@q9)h-K%)s9-^rh(;7T`vu={0p zCzf*G!~Iex?wWwWS?rOOYx{i!_Lh~OXJ7gYPR(bWfke`)l(GCjjtT06t7+0hHGHhh zA9y}JSM5#_xw|dqtlV?PVqZwGRm*pM)dvDj|LAzkF?4x}RLkCA#>G3V21ZLIt^gG< zQI&0O8}Rf;Def0;ZbweV+|x(R-?(Vnj5F9~eOT)4!nDr7Yq-5!y1bz1t;HjQSLn-A zt1qf%FzvKZ`+#!ufUYj;;FE!eL$>Pcse)qp0BW@>*U{2zo_CWHpgvHpnGofD&KYKY z+!}avbdRD^hZQf zU#$@f{W=^JvL7g)bcEZ<)O9tw4?Dxp&lksZ;$I_{?{l;o=>&}=tF-5MU&27^*rhJT zcd0DiLPxBSPJ<5cx}JGQAds^*(&j4-nHoTwx>dVUGJHkMM7w*nPbN5n_W)JJ zoSF~F)URWm1xS-QkhpAB(#}xq`0?;AQ=#^xj8iv{-*?l`8a;)kpuatAQXeVT+=;#A zT0rvGu`_`{>KMvxzgLkb$EeCy`RyvAx+nC!D381cssru;3nBjt{S>AGvQAs(kxLO{ zIp*xXImIAQJ>kiL&b~R(P_(nAu2z<~Dc*-_c3=C`sjCz@AZVOwgE5s@G#uy{iQNJ} z*pY1bjnx4K{yik#93ftw2}MI#Dt>w>)q5vp~-G zX7!=BUrYpB-3#04(mvmC$-Y!WY8${8gcraWB}q}i z(|PAS*SoXp)9`8tTYTuy7`=#uWFoR#J2(AVcxr-9uF+7kB$GxNkA$Vfoz}l40*Ydo zXReR;i`X4$Te~{&2?RE~^39WlS?>E>my@CS3|paiTe-zGjS$iwI*YbAHOwW*PD@wI z=Nl-L-*Y(4b+hX{-tb98arKb!Q^EK+RA0Lfp4`cv&x7o<`~ghNZ#@Z$`B6O*2R6%R z+kg>9tGG(TtYgVXWD_X)ySeq_3Tq2*GEPMlF@o;BBxfbxC%!xOuwUa+?wXac%Dce> z+d&$P_VsrSw*$bMY#z8~U%K$AIc8vOosw2D4`XdBe5NKVuc+s10x-cw)v;&2Yd`@# z6UL-Y1G;FY$G$?{@cwL6zaRL5p_lTzugeI5PB@eSk^x^LJ=N!qHsScr*=1fnx>1;L zY5eqB8dlecz6GSs<7{=#sl?FWEY66Ejk>f}1odw~P?}i0yH&4d%vKKZ@hTi7-IW8%;{(vI`&L;i z@`wN4O!SHFV&u%JzXt*g%E%4J$^z@6FOtA7Yc(*Rz2%_90Exxp+}r^Vb|pF?C;F8w zu&f+_Jsvg^Wp?I6!+uV$Bi#fzohClm^T{PdQzz%Nn}GENT0zaz{xqo+NWJ!QdLYKf zBHdX|LMnBh5jXZ;>OoAWv*rOX&O8Sbzjyl*y-%<2V2oE_*lEG(1GlpzBZ6aoOp%y8 ze&=uJp63A7*h}C9j-sY70bc4bHQr`@q#!@&!5LxUu`)c;-&WVK?$9+vP%D`7v^_`5 zrOcY7w(+sWUl!hkCI>q|qg_*OZ$os^0Fsg`di5ki_Tzr$8gh}#WNKHtX|hlAupfW6 zk_ZWVB&Hjb9ZbLk!Ie1lMyGd?qhgq8>{#iC>Kg^*taLx^YuW+VQG;}IK{6+Y@0i7& z6iRAQBlI8*LwK}P>x0;cL*en^{8^OvUg%KTXIa~~>xA%u_2)y{h_+YQ?tpDgX9rIe zOo3t5%oVK)PzXFaqN#F2^qJbgB3HzT`{nJcFO`#ATLWNBXfYU5CYHs&PnH^f*Wl6k z?<0KM*e@M?auAvtBi}A#6V#ej{yvSOE8v?4^Jb8y4~i{ zSIC{Kc9#!&HhKqJI9L>s*NbwiwWXI+w-X6TM}&3$PlPOE+G8HP8Hi(#UMtyKy= zLo(ZOb7qTQ^r{NHBg^h=C`gbboZigk0*;z5+XW@P;EzUwQZv5|SZ6W0tBbATVDt$& z4th!!{t_tBc>V9qZE^8&@=VbaMh;!ivCF~IC28PzN2Z{@`)H;y3+{?j%eQl6gP|I9 z-agi;Y>P($m>0yG48Z>=AC0W_h5((46THSuk)X||?u=A_N-{J)`M9Q^WnUMh84VTQ zIvQlFtG4Z5X~3!o0K!K+^E@{TZ;5W3XkNzy z*j?DZB4J)s(LK@K0K1T4u&xvPHDTX zs$=NfQalJo9RXF+0@j1~t~aK@*DAWgsI@Sl{8AP8%T`P`Vu~Tv_%ZmbJz^#V>NJZl-TbST^RMK5DlNOs$kegkbICLYRJk-}g{l-Wn^Vya`SL3T1tiIw^Z zm~h)cx+UimpKrqQ=$a*_BCrvMGi%5Nr5qU)hq|P1Tjp!gLgpIqRRIs`qsDGjcel*OH-c~&6W812bsUI z>umkx8_8Ottu&n?L`^t@;63h8!Nb19V4*G1v2?3e;$WrvvX7%#JaxH?R) zN@KLmgq3q$NONDrj=7c`8~kK5VTf>xS$Q2C8@T{(7ygTX1N^6hZ&3*F7Z@!5FaMz+ n@b3Qu^xx$8Uk}h2jH{d|uJ4jrSC|P(2)ca1@;v^m$K8JeR7TPQ diff --git a/dotnet/src/VectorData/Weaviate/Weaviate.csproj b/dotnet/src/VectorData/Weaviate/Weaviate.csproj index 26b59e293cb9..4e98297f7d08 100644 --- a/dotnet/src/VectorData/Weaviate/Weaviate.csproj +++ b/dotnet/src/VectorData/Weaviate/Weaviate.csproj @@ -27,6 +27,7 @@ + @@ -34,10 +35,6 @@ - - - - diff --git a/dotnet/test/VectorData/VectorData.ConformanceTests/VectorData.ConformanceTests.csproj b/dotnet/test/VectorData/VectorData.ConformanceTests/VectorData.ConformanceTests.csproj index dfdf5e4c0da0..eedce5d9664e 100644 --- a/dotnet/test/VectorData/VectorData.ConformanceTests/VectorData.ConformanceTests.csproj +++ b/dotnet/test/VectorData/VectorData.ConformanceTests/VectorData.ConformanceTests.csproj @@ -15,13 +15,10 @@ + - - - - diff --git a/dotnet/test/VectorData/VectorData.UnitTests/CollectionModelBuilderTests.cs b/dotnet/test/VectorData/VectorData.UnitTests/CollectionModelBuilderTests.cs deleted file mode 100644 index fe588e1100d1..000000000000 --- a/dotnet/test/VectorData/VectorData.UnitTests/CollectionModelBuilderTests.cs +++ /dev/null @@ -1,525 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.AI; -using Microsoft.Extensions.VectorData; -using Microsoft.Extensions.VectorData.ProviderServices; -using Xunit; - -namespace VectorData.UnitTests; - -#pragma warning disable CA2000 // Dispose objects before losing scope - -public class CollectionModelBuilderTests -{ - [Fact] - public void Default_embedding_generator_without_record_definition() - { - using var embeddingGenerator = new FakeEmbeddingGenerator>(); - var model = new CustomModelBuilder().Build(typeof(RecordWithStringVectorProperty), typeof(int), definition: null, embeddingGenerator); - - // The embedding's .NET type (Embedding) is inferred from the embedding generator. - Assert.Same(embeddingGenerator, model.VectorProperty.EmbeddingGenerator); - Assert.Same(typeof(string), model.VectorProperty.Type); - Assert.Same(typeof(Embedding), model.VectorProperty.EmbeddingType); - } - - [Fact] - public void Default_embedding_generator_with_clr_type_and_record_definition() - { - using var embeddingGenerator = new FakeEmbeddingGenerator>(); - - var recordDefinition = new VectorStoreCollectionDefinition - { - Properties = - [ - new VectorStoreKeyProperty(nameof(RecordWithEmbeddingVectorProperty.Id), typeof(int)), - new VectorStoreDataProperty(nameof(RecordWithEmbeddingVectorProperty.Name), typeof(string)), - new VectorStoreVectorProperty(nameof(RecordWithEmbeddingVectorProperty.Embedding), typeof(string), dimensions: 3) - { - // The following configures the property to be Embedding (non-default embedding type for this connector) - EmbeddingType = typeof(Embedding) - } - ] - }; - - var model = new CustomModelBuilder().Build(typeof(RecordWithStringVectorProperty), typeof(int), recordDefinition, embeddingGenerator); - - // The embedding's .NET type (Embedding) is inferred from the embedding generator. - Assert.Same(embeddingGenerator, model.VectorProperty.EmbeddingGenerator); - Assert.Same(typeof(string), model.VectorProperty.Type); - Assert.Same(typeof(Embedding), model.VectorProperty.EmbeddingType); - } - - [Fact] - public void Default_embedding_generator_with_dynamic() - { - using var embeddingGenerator = new FakeEmbeddingGenerator>(); - - var recordDefinition = new VectorStoreCollectionDefinition - { - Properties = - [ - new VectorStoreKeyProperty(nameof(RecordWithEmbeddingVectorProperty.Id), typeof(int)), - new VectorStoreDataProperty(nameof(RecordWithEmbeddingVectorProperty.Name), typeof(string)), - new VectorStoreVectorProperty(nameof(RecordWithEmbeddingVectorProperty.Embedding), typeof(string), dimensions: 3) - ] - }; - - var model = new CustomModelBuilder().BuildDynamic(recordDefinition, embeddingGenerator); - - // The embedding's .NET type (Embedding) is inferred from the embedding generator. - Assert.Same(embeddingGenerator, model.VectorProperty.EmbeddingGenerator); - Assert.Same(typeof(string), model.VectorProperty.Type); - Assert.Same(typeof(Embedding), model.VectorProperty.EmbeddingType); - } - - [Fact] - public void Default_embedding_generator_with_dynamic_and_non_default_EmbeddingType() - { - using var embeddingGenerator = new FakeEmbeddingGenerator>(); - - var recordDefinition = new VectorStoreCollectionDefinition - { - Properties = - [ - new VectorStoreKeyProperty(nameof(RecordWithEmbeddingVectorProperty.Id), typeof(int)), - new VectorStoreDataProperty(nameof(RecordWithEmbeddingVectorProperty.Name), typeof(string)), - new VectorStoreVectorProperty(nameof(RecordWithEmbeddingVectorProperty.Embedding), typeof(string), dimensions: 3) - { - EmbeddingType = typeof(Embedding) - } - ] - }; - - var model = new CustomModelBuilder().BuildDynamic(recordDefinition, embeddingGenerator); - - Assert.Same(embeddingGenerator, model.VectorProperty.EmbeddingGenerator); - Assert.Same(typeof(string), model.VectorProperty.Type); - Assert.Same(typeof(Embedding), model.VectorProperty.EmbeddingType); - } - - [Fact] - public void Property_embedding_generator_takes_precedence_over_default_generator() - { - using var propertyEmbeddingGenerator = new FakeEmbeddingGenerator>(); - using var defaultEmbeddingGenerator = new FakeEmbeddingGenerator>(); - - var recordDefinition = new VectorStoreCollectionDefinition - { - Properties = - [ - new VectorStoreKeyProperty(nameof(RecordWithEmbeddingVectorProperty.Id), typeof(int)), - new VectorStoreDataProperty(nameof(RecordWithEmbeddingVectorProperty.Name), typeof(string)), - new VectorStoreVectorProperty(nameof(RecordWithEmbeddingVectorProperty.Embedding), typeof(string), dimensions: 3) - { - EmbeddingGenerator = propertyEmbeddingGenerator - } - ] - }; - - var model = new CustomModelBuilder().BuildDynamic(recordDefinition, defaultEmbeddingGenerator); - - Assert.Same(propertyEmbeddingGenerator, model.VectorProperty.EmbeddingGenerator); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Embedding_property_type_with_default_embedding_generator(bool dynamic) - { - using var embeddingGenerator = new FakeEmbeddingGenerator>(); - - var model = dynamic - ? new CustomModelBuilder().BuildDynamic( - new VectorStoreCollectionDefinition - { - Properties = - [ - new VectorStoreKeyProperty(nameof(RecordWithEmbeddingVectorProperty.Id), typeof(int)), - new VectorStoreDataProperty(nameof(RecordWithEmbeddingVectorProperty.Name), typeof(string)), - new VectorStoreVectorProperty(nameof(RecordWithEmbeddingVectorProperty.Embedding), typeof(ReadOnlyMemory), dimensions: 3) - ] - }, - embeddingGenerator) - : new CustomModelBuilder().Build(typeof(RecordWithEmbeddingVectorProperty), typeof(int), definition: null, embeddingGenerator); - - var vectorProperty = model.VectorProperty; - Assert.Same(embeddingGenerator, vectorProperty.EmbeddingGenerator); - Assert.Same(typeof(ReadOnlyMemory), vectorProperty.Type); - } - - [Fact] - public void Embedding_property_type_with_property_embedding_generator() - { - using var embeddingGenerator = new FakeEmbeddingGenerator>(); - - var model = new CustomModelBuilder().Build( - typeof(RecordWithEmbeddingVectorProperty), - typeof(int), - new VectorStoreCollectionDefinition - { - Properties = - [ - new VectorStoreKeyProperty(nameof(RecordWithEmbeddingVectorProperty.Id), typeof(int)), - new VectorStoreDataProperty(nameof(RecordWithEmbeddingVectorProperty.Name), typeof(string)), - new VectorStoreVectorProperty(nameof(RecordWithEmbeddingVectorProperty.Embedding), typeof(ReadOnlyMemory), dimensions: 3) - { - EmbeddingGenerator = embeddingGenerator - } - ] - }, - embeddingGenerator); - - var vectorProperty = model.VectorProperty; - Assert.Same(embeddingGenerator, vectorProperty.EmbeddingGenerator); - Assert.Same(typeof(ReadOnlyMemory), vectorProperty.EmbeddingType); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Custom_input_type(bool dynamic) - { - using var embeddingGenerator = new FakeEmbeddingGenerator>(); - - // TODO: Allow custom input type without a record definition (i.e. generic attribute) - var recordDefinition = new VectorStoreCollectionDefinition - { - Properties = - [ - new VectorStoreKeyProperty(nameof(RecordWithEmbeddingVectorProperty.Id), typeof(int)), - new VectorStoreDataProperty(nameof(RecordWithEmbeddingVectorProperty.Name), typeof(string)), - new VectorStoreVectorProperty(nameof(RecordWithEmbeddingVectorProperty.Embedding), dimensions: 3) - ] - }; - - var model = dynamic - ? new CustomModelBuilder().BuildDynamic(recordDefinition, embeddingGenerator) - : new CustomModelBuilder().Build(typeof(RecordWithCustomerVectorProperty), typeof(int), recordDefinition, embeddingGenerator); - - var vectorProperty = model.VectorProperty; - - Assert.Same(embeddingGenerator, vectorProperty.EmbeddingGenerator); - Assert.Same(typeof(Customer), vectorProperty.Type); - Assert.Same(typeof(Embedding), vectorProperty.EmbeddingType); - } - - [Fact] - public void Incompatible_embedding_on_embedding_generator_throws() - { - // Embedding is not a supported embedding type by the connector - using var embeddingGenerator = new FakeEmbeddingGenerator>(); - - var exception = Assert.Throws(() => - new CustomModelBuilder().Build(typeof(RecordWithStringVectorProperty), typeof(int), definition: null, embeddingGenerator)); - - Assert.Equal($"Embedding generator 'FakeEmbeddingGenerator>' on vector property '{nameof(RecordWithStringVectorProperty.Embedding)}' cannot convert the input type 'string' to a supported vector type (one of: ReadOnlyMemory, Embedding, float[], ReadOnlyMemory, Embedding, Half[]).", exception.Message); - } - - [Fact] - public void Incompatible_input_on_embedding_generator_throws() - { - // int is not a supported input type for the embedding generator - using var embeddingGenerator = new FakeEmbeddingGenerator>(); - - var exception = Assert.Throws(() => - new CustomModelBuilder().Build(typeof(RecordWithStringVectorProperty), typeof(int), definition: null, embeddingGenerator)); - - Assert.Equal($"Embedding generator 'FakeEmbeddingGenerator>' on vector property '{nameof(RecordWithStringVectorProperty.Embedding)}' cannot convert the input type 'string' to a supported vector type (one of: ReadOnlyMemory, Embedding, float[], ReadOnlyMemory, Embedding, Half[]).", exception.Message); - } - - [Fact] - public void Non_embedding_vector_property_without_embedding_generator_throws() - { - var exception = Assert.Throws(() => - new CustomModelBuilder().Build(typeof(RecordWithStringVectorProperty), typeof(int), definition: null, defaultEmbeddingGenerator: null)); - - Assert.Equal($"Vector property '{nameof(RecordWithStringVectorProperty.Embedding)}' has type 'string' which isn't supported by your provider, and no embedding generator is configured. Configure a generator that supports converting 'string' to vector type supported by your provider.", exception.Message); - } - - [Fact] - public void EmbeddingType_not_supported_by_provider() - { - using var embeddingGenerator = new FakeEmbeddingGenerator>(); - - var recordDefinition = new VectorStoreCollectionDefinition - { - Properties = - [ - new VectorStoreKeyProperty(nameof(RecordWithEmbeddingVectorProperty.Id), typeof(int)), - new VectorStoreDataProperty(nameof(RecordWithEmbeddingVectorProperty.Name), typeof(string)), - new VectorStoreVectorProperty(nameof(RecordWithEmbeddingVectorProperty.Embedding), typeof(string), dimensions: 3) - { - EmbeddingType = typeof(Embedding) // The provider supports float/Half only, not byte - } - ] - }; - - var exception = Assert.Throws(() => - new CustomModelBuilder().Build(typeof(RecordWithStringVectorProperty), typeof(int), recordDefinition, embeddingGenerator)); - - Assert.Equal("Vector property 'Embedding' has embedding type 'Embedding' configured, but that type isn't supported by your provider. Supported types are ReadOnlyMemory, Embedding, float[], ReadOnlyMemory, Embedding, Half[].", exception.Message); - } - - [Fact] - public void EmbeddingType_not_supported_by_generator() - { - using var embeddingGenerator = new FakeEmbeddingGenerator>(); - - var recordDefinition = new VectorStoreCollectionDefinition - { - Properties = - [ - new VectorStoreKeyProperty(nameof(RecordWithEmbeddingVectorProperty.Id), typeof(int)), - new VectorStoreDataProperty(nameof(RecordWithEmbeddingVectorProperty.Name), typeof(string)), - new VectorStoreVectorProperty(nameof(RecordWithEmbeddingVectorProperty.Embedding), typeof(string), dimensions: 3) - { - EmbeddingType = typeof(Embedding) // The generator (instantiated above) supports only Embedding - } - ] - }; - - var exception = Assert.Throws(() => - new CustomModelBuilder().Build(typeof(RecordWithStringVectorProperty), typeof(int), recordDefinition, embeddingGenerator)); - - Assert.Equal("Vector property 'Embedding' has embedding type 'Embedding' configured, but that type isn't supported by your embedding generator.", exception.Message); - } - - [Fact] - public void Missing_Type_on_property_definition() - { - var recordDefinition = new VectorStoreCollectionDefinition - { - Properties = - [ - new VectorStoreKeyProperty(nameof(RecordWithEmbeddingVectorProperty.Id), typeof(int)), - new VectorStoreDataProperty(nameof(RecordWithEmbeddingVectorProperty.Name), typeof(string)), - new VectorStoreVectorProperty(nameof(RecordWithEmbeddingVectorProperty.Embedding), typeof(ReadOnlyMemory), dimensions: 3) - ] - }; - - // Key - recordDefinition.Properties[0].Type = null; - var exception = Assert.Throws(() => new CustomModelBuilder().BuildDynamic(recordDefinition, defaultEmbeddingGenerator: null)); - Assert.Equal($"Property '{nameof(RecordWithEmbeddingVectorProperty.Id)}' has no type specified in its definition, and does not have a corresponding .NET property. Specify the type on the definition.", exception.Message); - - // Data - recordDefinition.Properties[0].Type = typeof(int); - recordDefinition.Properties[1].Type = null; - exception = Assert.Throws(() => new CustomModelBuilder().BuildDynamic(recordDefinition, defaultEmbeddingGenerator: null)); - Assert.Equal($"Property '{nameof(RecordWithEmbeddingVectorProperty.Name)}' has no type specified in its definition, and does not have a corresponding .NET property. Specify the type on the definition.", exception.Message); - - // Vector - recordDefinition.Properties[1].Type = typeof(string); - recordDefinition.Properties[2].Type = null; - exception = Assert.Throws(() => new CustomModelBuilder().BuildDynamic(recordDefinition, defaultEmbeddingGenerator: null)); - Assert.Equal($"Property '{nameof(RecordWithEmbeddingVectorProperty.Embedding)}' has no type specified in its definition, and does not have a corresponding .NET property. Specify the type on the definition.", exception.Message); - } - - public class RecordWithStringVectorProperty - { - [VectorStoreKey] - public int Id { get; set; } - - [VectorStoreData] - public string Name { get; set; } - - [VectorStoreVector(Dimensions: 3)] - public string Embedding { get; set; } - } - - public class RecordWithEmbeddingVectorProperty - { - [VectorStoreKey] - public int Id { get; set; } - - [VectorStoreData] - public string Name { get; set; } - - [VectorStoreVector(Dimensions: 3)] - public ReadOnlyMemory Embedding { get; set; } - } - - public class RecordWithCustomerVectorProperty - { - [VectorStoreKey] - public int Id { get; set; } - - [VectorStoreData] - public string Name { get; set; } - - [VectorStoreVector(Dimensions: 3)] - public Customer Embedding { get; set; } - } - - public class Customer - { - public string FirstName { get; set; } - public string LastName { get; set; } - } - - private sealed class CustomModelBuilder(CollectionModelBuildingOptions? options = null) - : CollectionModelBuilder(options ?? s_defaultOptions) - { - private static readonly CollectionModelBuildingOptions s_defaultOptions = new() - { - SupportsMultipleVectors = true, - RequiresAtLeastOneVector = false - }; - - protected override void ValidateKeyProperty(KeyPropertyModel keyProperty) - { - var type = keyProperty.Type; - - if (type != typeof(string) && type != typeof(int)) - { - throw new NotSupportedException( - $"Property '{keyProperty.ModelName}' has unsupported type '{type.Name}'. Key properties must be one of the supported types: string, int."); - } - } - - protected override bool IsDataPropertyTypeValid(Type type, [NotNullWhen(false)] out string? supportedTypes) - { - supportedTypes = "string, int"; - - if (Nullable.GetUnderlyingType(type) is Type underlyingType) - { - type = underlyingType; - } - - return type == typeof(string) || type == typeof(int); - } - - protected override bool IsVectorPropertyTypeValid(Type type, [NotNullWhen(false)] out string? supportedTypes) - => IsVectorPropertyTypeValidCore(type, out supportedTypes); - - internal static bool IsVectorPropertyTypeValidCore(Type type, [NotNullWhen(false)] out string? supportedTypes) - { - supportedTypes = "ReadOnlyMemory, Embedding, float[], ReadOnlyMemory, Embedding, Half[]"; - - if (Nullable.GetUnderlyingType(type) is Type underlyingType) - { - type = underlyingType; - } - - return type == typeof(ReadOnlyMemory) - || type == typeof(Embedding) - || type == typeof(float[]) - || type == typeof(ReadOnlyMemory) - || type == typeof(Embedding) - || type == typeof(Half[]); - } - - protected override IReadOnlyList EmbeddingGenerationDispatchers { get; } = - [ - EmbeddingGenerationDispatcher.Create>(), - EmbeddingGenerationDispatcher.Create>() - ]; - } - - [Fact] - public void IsAutoGenerated_attribute_true_overrides_default() - { - // Guid key with explicit IsAutoGenerated = true; the attribute should override SupportsKeyAutoGeneration. - var model = new GuidKeyModelBuilder().Build( - typeof(RecordWithGuidKeyAutoGeneratedTrue), typeof(Guid), definition: null, defaultEmbeddingGenerator: null); - - Assert.True(model.KeyProperty.IsAutoGenerated); - } - - [Fact] - public void IsAutoGenerated_attribute_false_overrides_default() - { - // Guid key with explicit IsAutoGenerated = false; the attribute should override SupportsKeyAutoGeneration, - // which would otherwise return true for Guid. - var model = new GuidKeyModelBuilder().Build( - typeof(RecordWithGuidKeyAutoGeneratedFalse), typeof(Guid), definition: null, defaultEmbeddingGenerator: null); - - Assert.False(model.KeyProperty.IsAutoGenerated); - } - - [Fact] - public void IsAutoGenerated_omitted_falls_back_to_SupportsKeyAutoGeneration_true() - { - // Guid key with no IsAutoGenerated attribute set; should fall back to SupportsKeyAutoGeneration, which returns true for Guid. - var model = new GuidKeyModelBuilder().Build( - typeof(RecordWithGuidKeyNoIsAutoGenerated), typeof(Guid), definition: null, defaultEmbeddingGenerator: null); - - Assert.True(model.KeyProperty.IsAutoGenerated); - } - - [Fact] - public void IsAutoGenerated_omitted_falls_back_to_SupportsKeyAutoGeneration_false() - { - // int key with no IsAutoGenerated attribute set; should fall back to SupportsKeyAutoGeneration, which returns false for non-Guid. - var model = new GuidKeyModelBuilder().Build( - typeof(RecordWithIntKeyNoIsAutoGenerated), typeof(int), definition: null, defaultEmbeddingGenerator: null); - - Assert.False(model.KeyProperty.IsAutoGenerated); - } - - public class RecordWithGuidKeyAutoGeneratedTrue - { - [VectorStoreKey(IsAutoGenerated = true)] - public Guid Id { get; set; } - } - - public class RecordWithGuidKeyAutoGeneratedFalse - { - [VectorStoreKey(IsAutoGenerated = false)] - public Guid Id { get; set; } - } - - public class RecordWithGuidKeyNoIsAutoGenerated - { - [VectorStoreKey] - public Guid Id { get; set; } - } - - public class RecordWithIntKeyNoIsAutoGenerated - { - [VectorStoreKey] - public int Id { get; set; } - } - - private sealed class GuidKeyModelBuilder() - : CollectionModelBuilder(new CollectionModelBuildingOptions - { - SupportsMultipleVectors = true, - RequiresAtLeastOneVector = false - }) - { - protected override bool IsDataPropertyTypeValid(Type type, [NotNullWhen(false)] out string? supportedTypes) - { - supportedTypes = null; - return true; - } - - protected override bool IsVectorPropertyTypeValid(Type type, [NotNullWhen(false)] out string? supportedTypes) - { - supportedTypes = null; - return true; - } - } - - private sealed class FakeEmbeddingGenerator : IEmbeddingGenerator - where TEmbedding : Embedding - { - public Task> GenerateAsync( - IEnumerable values, - EmbeddingGenerationOptions? options = null, - CancellationToken cancellationToken = default) - => throw new UnreachableException(); - - public object? GetService(Type serviceType, object? serviceKey = null) - => throw new UnreachableException(); - - public void Dispose() { } - } -} diff --git a/dotnet/test/VectorData/VectorData.UnitTests/PropertyModelTests.cs b/dotnet/test/VectorData/VectorData.UnitTests/PropertyModelTests.cs deleted file mode 100644 index aad7b64beee3..000000000000 --- a/dotnet/test/VectorData/VectorData.UnitTests/PropertyModelTests.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using Microsoft.Extensions.VectorData.ProviderServices; -using Xunit; - -namespace VectorData.UnitTests; - -public class PropertyModelTests -{ - #region Value type nullability - - [Fact] - public void IsNullable_NonNullableValueType_ReturnsFalse() - { - var property = new DataPropertyModel("test", typeof(int)); - Assert.False(property.IsNullable); - } - - [Fact] - public void IsNullable_NullableValueType_ReturnsTrue() - { - var property = new DataPropertyModel("test", typeof(int?)); - Assert.True(property.IsNullable); - } - - [Fact] - public void IsNullable_Guid_ReturnsFalse() - { - var property = new DataPropertyModel("test", typeof(Guid)); - Assert.False(property.IsNullable); - } - - [Fact] - public void IsNullable_NullableGuid_ReturnsTrue() - { - var property = new DataPropertyModel("test", typeof(Guid?)); - Assert.True(property.IsNullable); - } - - [Fact] - public void IsNullable_ReadOnlyMemoryFloat_ReturnsFalse() - { - var property = new DataPropertyModel("test", typeof(ReadOnlyMemory)); - Assert.False(property.IsNullable); - } - - [Fact] - public void IsNullable_NullableReadOnlyMemoryFloat_ReturnsTrue() - { - var property = new DataPropertyModel("test", typeof(ReadOnlyMemory?)); - Assert.True(property.IsNullable); - } - - #endregion - - #region Reference type nullability (dynamic mapping, no PropertyInfo) - - [Fact] - public void IsNullable_String_WithoutPropertyInfo_ReturnsTrue() - { - // Without PropertyInfo (dynamic mapping), reference types are assumed nullable - var property = new DataPropertyModel("test", typeof(string)); - Assert.True(property.IsNullable); - } - - [Fact] - public void IsNullable_ByteArray_WithoutPropertyInfo_ReturnsTrue() - { - var property = new DataPropertyModel("test", typeof(byte[])); - Assert.True(property.IsNullable); - } - - #endregion - -#if NET - #region NRT detection via NullabilityInfoContext (POCO mapping with PropertyInfo) - - [Fact] - public void IsNullable_NonNullableString_WithPropertyInfo_ReturnsFalse() - { - var propertyInfo = typeof(NrtTestRecord).GetProperty(nameof(NrtTestRecord.NonNullableString))!; - var property = new DataPropertyModel("test", typeof(string)) { PropertyInfo = propertyInfo }; - Assert.False(property.IsNullable); - } - - [Fact] - public void IsNullable_NullableString_WithPropertyInfo_ReturnsTrue() - { - var propertyInfo = typeof(NrtTestRecord).GetProperty(nameof(NrtTestRecord.NullableString))!; - var property = new DataPropertyModel("test", typeof(string)) { PropertyInfo = propertyInfo }; - Assert.True(property.IsNullable); - } - - [Fact] - public void IsNullable_NonNullableByteArray_WithPropertyInfo_ReturnsFalse() - { - var propertyInfo = typeof(NrtTestRecord).GetProperty(nameof(NrtTestRecord.NonNullableByteArray))!; - var property = new DataPropertyModel("test", typeof(byte[])) { PropertyInfo = propertyInfo }; - Assert.False(property.IsNullable); - } - - [Fact] - public void IsNullable_NullableByteArray_WithPropertyInfo_ReturnsTrue() - { - var propertyInfo = typeof(NrtTestRecord).GetProperty(nameof(NrtTestRecord.NullableByteArray))!; - var property = new DataPropertyModel("test", typeof(byte[])) { PropertyInfo = propertyInfo }; - Assert.True(property.IsNullable); - } - - [Fact] - public void IsNullable_ValueType_WithPropertyInfo_StillUsesTypeCheck() - { - var propertyInfo = typeof(NrtTestRecord).GetProperty(nameof(NrtTestRecord.NonNullableInt))!; - var property = new DataPropertyModel("test", typeof(int)) { PropertyInfo = propertyInfo }; - Assert.False(property.IsNullable); - - var nullablePropertyInfo = typeof(NrtTestRecord).GetProperty(nameof(NrtTestRecord.NullableInt))!; - var nullableProperty = new DataPropertyModel("test", typeof(int?)) { PropertyInfo = nullablePropertyInfo }; - Assert.True(nullableProperty.IsNullable); - } - -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor -#pragma warning disable CA1812 // Class is used via reflection - private sealed class NrtTestRecord - { - public string NonNullableString { get; set; } - public string? NullableString { get; set; } - public byte[] NonNullableByteArray { get; set; } - public byte[]? NullableByteArray { get; set; } - public int NonNullableInt { get; set; } - public int? NullableInt { get; set; } - } -#pragma warning restore CA1812 -#pragma warning restore CS8618 - - #endregion -#endif -} diff --git a/dotnet/test/VectorData/VectorData.UnitTests/VectorData.UnitTests.csproj b/dotnet/test/VectorData/VectorData.UnitTests/VectorData.UnitTests.csproj deleted file mode 100644 index cc7bf6d4e2bc..000000000000 --- a/dotnet/test/VectorData/VectorData.UnitTests/VectorData.UnitTests.csproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - VectorData.UnitTests - VectorData.UnitTests - net10.0 - true - enable - disable - false - $(NoWarn);VSTHRD111,CA2007,CS8618 - $(NoWarn);MEVD9001 - $(NoWarn);CA1515 - $(NoWarn);CA1707 - $(NoWarn);CA1716 - $(NoWarn);CA1720 - $(NoWarn);CA1721 - $(NoWarn);CA1861 - $(NoWarn);CA1863 - $(NoWarn);CA2007;VSTHRD111 - $(NoWarn);CS1591 - $(NoWarn);IDE1006 - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - From 99d1953e935bd88a4cc993cbad9485703734f1b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jun 2026 10:36:05 +0100 Subject: [PATCH 23/33] Bump axios from 1.13.2 to 1.16.0 in /dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend (#14044) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [axios](https://github.com/axios/axios) from 1.13.2 to 1.16.0.
Release notes

Sourced from axios's releases.

v1.16.0 — May 2, 2026

This release adds support for the QUERY HTTP method and a new ECONNREFUSED error constant, lands a substantial wave of HTTP, fetch, and XHR adapter bug fixes around redirects, aborts, headers, and timeouts, and welcomes 23 new contributors.

⚠️ Notable Changes

A handful of fixes in this release are either security-adjacent or change observable behaviour. Please review before upgrading:

  • Fetch adapter now enforces maxBodyLength and maxContentLength. These limits were silently ignored on the fetch adapter prior to 1.16.0 — anyone relying on them as a safety net (DoS protection, accidental large uploads) had no protection. (#10795)
  • Proxy requests now preserve user-supplied Host headers. Previously, the proxy path could overwrite a custom Host. Virtual-host-style routing through a proxy will now behave correctly. (#10822)
  • Basic auth credentials embedded in URLs are now URL-decoded. If you have percent-encoded credentials in a URL (e.g. https://user:p%40ss@host), the decoded value is what now goes on the wire. (#10825)
  • parseProtocol now strictly requires a colon in the protocol separator. Strings that loosely parsed as protocols before may no longer match. (#10729)
  • Deprecated unescape() replaced with modern UTF-8 encoding. Non-ASCII URL handling is now spec-correct; consumers depending on legacy unescape() quirks may see different output bytes. (#7378)
  • transformRequest input typing change was reverted. The typing change introduced in #10745 was reverted in #10810 after follow-up review — net behavior is unchanged from 1.15.2. (#10745, #10810)

🚀 New Features

  • QUERY HTTP Method: Added support for the QUERY HTTP method across adapters and type definitions. (#10802)
  • ECONNREFUSED Error Constant: Exposed ECONNREFUSED as a constant on AxiosError so callers can match connection-refused failures without comparing string literals (closes #6485). (#10680)
  • Encode Helper Export: Exported the internal encode helper from buildURL so userland param serializers can reuse the same encoding logic that axios uses internally. (#6897)

🐛 Bug Fixes

  • HTTP Adapter — Redirects & Headers: Cleared stale headers when a redirect targets a no-proxy host, fixed the redirect listener chain so listeners no longer stack across hops, restored the missing requestDetails argument on beforeRedirect, preserved user-supplied Host headers when forwarding through a proxy, and properly URL-decoded basic auth credentials. (#10794, #10800, #6241, #10822, #10825)
  • HTTP Adapter — Streams & Timeouts: Preserved the partial response object on AxiosError when a stream is aborted after headers arrive, honoured the timeout option during the connect phase when redirects are disabled, and resolved an unsettled-promise hang when an aborted request was combined with compression and maxRedirects: 0. (#10708, #10819, #7149)
  • Fetch Adapter: Enforced maxBodyLength / maxContentLength in the fetch adapter, set the User-Agent header to match the HTTP adapter, preserved the original abort reason instead of replacing it with a generic error, and deferred global access so importing the module no longer throws a TypeError in restricted environments. (#10795, #10772, #10806, #7260)
  • XHR Adapter: Unsubscribed the cancelToken and AbortSignal listeners on the error, timeout, and abort code paths to prevent leaked subscriptions. (#10787)
  • Error Handling: Attached the parsed response to AxiosError when JSON.parse fails inside dispatchRequest, prevented settle from emitting undefined error codes, and tightened the parseProtocol regex to require a colon in the protocol separator. (#10724, #7276, #10729)
  • Types & Exports: Aligned the CommonJS CancelToken typings with the ESM build, fixed a compiler error caused by RawAxiosHeaders, and re-exported create from the package index. (#7414, #6389, #6460)
  • UTF-8 Encoding: Replaced the deprecated unescape() call with a modern UTF-8 encoding implementation. (#7378)
  • Misc Cleanup: Resolved a batch of small inconsistencies and gadget-level issues across the codebase. (#10833)

🔧 Maintenance & Chores

  • Refactor — ES6 Modernisation: Modernised the utils module and XHR adapter to use ES6 features, and tidied the multipart boundary error message. (#10588, #7419)
  • Tests: Hardened the HTTP test server lifecycle to fix flaky FormData EPIPE failures, fixed Win32 platform support for the pipe tests, and corrected an incorrect test assumption. (#10820, #10791, #10796)
  • Docs: Documented paramsSerializer.encode for strict RFC 3986 query encoding, updated the parseReviver TypeScript definitions and configuration docs for ES2023, added timeout guidance to the README's first async example, and expanded notes around the recent type changes. (#10821, #10782, #10759, #10804)
  • Reverted: Reverted the transformRequest input typing change from #10745 after follow-up review. (#10745, #10810)
  • Dependencies: Bumped actions/setup-node, the github-actions group, and postcss (in /docs) to their latest versions. (#10785, #10813, #10814)
  • Release: Updated changelog and packages, and prepared the 1.16.0 release. (#10790, #10834)

🌟 New Contributors

We are thrilled to welcome our new contributors. Thank you for helping improve axios:

... (truncated)

Changelog

Sourced from axios's changelog.

v1.16.0 — May 2, 2026

This release adds support for the QUERY HTTP method and a new ECONNREFUSED error constant, lands a substantial wave of HTTP, fetch, and XHR adapter bug fixes around redirects, aborts, headers, and timeouts, and welcomes 23 new contributors.

⚠️ Notable Changes

A handful of fixes in this release are either security-adjacent or change observable behaviour. Please review before upgrading:

  • Fetch adapter now enforces maxBodyLength and maxContentLength. These limits were silently ignored on the fetch adapter prior to 1.16.0 — anyone relying on them as a safety net (DoS protection, accidental large uploads) had no protection. (#10795)
  • Proxy requests now preserve user-supplied Host headers. Previously, the proxy path could overwrite a custom Host. Virtual-host-style routing through a proxy will now behave correctly. (#10822)
  • Basic auth credentials embedded in URLs are now URL-decoded. If you have percent-encoded credentials in a URL (e.g. https://user:p%40ss@host), the decoded value is what now goes on the wire. (#10825)
  • parseProtocol now strictly requires a colon in the protocol separator. Strings that loosely parsed as protocols before may no longer match. (#10729)
  • Deprecated unescape() replaced with modern UTF-8 encoding. Non-ASCII URL handling is now spec-correct; consumers depending on legacy unescape() quirks may see different output bytes. (#7378)
  • transformRequest input typing change was reverted. The typing change introduced in #10745 was reverted in #10810 after follow-up review — net behavior is unchanged from 1.15.2. (#10745, #10810)

🚀 New Features

  • QUERY HTTP Method: Added support for the QUERY HTTP method across adapters and type definitions. (#10802)
  • ECONNREFUSED Error Constant: Exposed ECONNREFUSED as a constant on AxiosError so callers can match connection-refused failures without comparing string literals (closes #6485). (#10680)
  • Encode Helper Export: Exported the internal encode helper from buildURL so userland param serializers can reuse the same encoding logic that axios uses internally. (#6897)

🐛 Bug Fixes

  • HTTP Adapter — Redirects & Headers: Cleared stale headers when a redirect targets a no-proxy host, fixed the redirect listener chain so listeners no longer stack across hops, restored the missing requestDetails argument on beforeRedirect, preserved user-supplied Host headers when forwarding through a proxy, and properly URL-decoded basic auth credentials. (#10794, #10800, #6241, #10822, #10825)
  • HTTP Adapter — Streams & Timeouts: Preserved the partial response object on AxiosError when a stream is aborted after headers arrive, honoured the timeout option during the connect phase when redirects are disabled, and resolved an unsettled-promise hang when an aborted request was combined with compression and maxRedirects: 0. (#10708, #10819, #7149)
  • Fetch Adapter: Enforced maxBodyLength / maxContentLength in the fetch adapter, set the User-Agent header to match the HTTP adapter, preserved the original abort reason instead of replacing it with a generic error, and deferred global access so importing the module no longer throws a TypeError in restricted environments. (#10795, #10772, #10806, #7260)
  • XHR Adapter: Unsubscribed the cancelToken and AbortSignal listeners on the error, timeout, and abort code paths to prevent leaked subscriptions. (#10787)
  • Error Handling: Attached the parsed response to AxiosError when JSON.parse fails inside dispatchRequest, prevented settle from emitting undefined error codes, and tightened the parseProtocol regex to require a colon in the protocol separator. (#10724, #7276, #10729)
  • Types & Exports: Aligned the CommonJS CancelToken typings with the ESM build, fixed a compiler error caused by RawAxiosHeaders, and re-exported create from the package index. (#7414, #6389, #6460)
  • UTF-8 Encoding: Replaced the deprecated unescape() call with a modern UTF-8 encoding implementation. (#7378)
  • Misc Cleanup: Resolved a batch of small inconsistencies and gadget-level issues across the codebase. (#10833)

🔧 Maintenance & Chores

  • Refactor — ES6 Modernisation: Modernised the utils module and XHR adapter to use ES6 features, and tidied the multipart boundary error message. (#10588, #7419)
  • Tests: Hardened the HTTP test server lifecycle to fix flaky FormData EPIPE failures, fixed Win32 platform support for the pipe tests, and corrected an incorrect test assumption. (#10820, #10791, #10796)
  • Docs: Documented paramsSerializer.encode for strict RFC 3986 query encoding, updated the parseReviver TypeScript definitions and configuration docs for ES2023, added timeout guidance to the README's first async example, and expanded notes around the recent type changes. (#10821, #10782, #10759, #10804)
  • Reverted: Reverted the transformRequest input typing change from #10745 after follow-up review. (#10745, #10810)
  • Dependencies: Bumped actions/setup-node, the github-actions group, and postcss (in /docs) to their latest versions. (#10785, #10813, #10814)
  • Release: Updated changelog and packages, and prepared the 1.16.0 release. (#10790, #10834)

🌟 New Contributors

We are thrilled to welcome our new contributors. Thank you for helping improve axios:

... (truncated)

Commits
  • df53d7d chore(release): prepare release 1.16.0 (#10834)
  • 9d92bcd fix: gadgets and smaller issues (#10833)
  • 5107ee6 fix: prevent undefined error codes in settle (#7276)
  • e573499 fix(fetch): defer global access in fetch adapter (#7260)
  • ad68e1a fix(http): honor timeout during connect without redirects (#10819)
  • 2a51828 fix(http): decode URL basic auth credentials (#10825)
  • 0e8b6bb fix(http): preserve user-supplied Host header when forwarding through a proxy...
  • 79f39e1 docs: document paramsSerializer.encode for strict RFC 3986 query encoding (#1...
  • 0fe3a5f [Docs/Types] Update parseReviver TypeScript definitions for ES2023 and add ...
  • cd6737f chore: matches the sibling responseStream.on(aborted) handler and added tests...
  • Additional commits viewable in compare view
Maintainer changes

This version was pushed to npm by GitHub Actions, a new releaser for axios since your current version.

Install script changes

This version modifies prepare script that runs during installation. Review the package contents before updating.


Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> --- .../package-lock.json | 25 ++++++++++-------- .../package.json | 2 +- .../yarn.lock | 26 +++++++++---------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json index 98663274936a..537a29230df4 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package-lock.json @@ -14,7 +14,7 @@ "@protobuf-ts/grpcweb-transport": "^2.9.6", "@protobuf-ts/runtime": "^2.9.6", "@protobuf-ts/runtime-rpc": "^2.9.6", - "axios": "^1.7.9", + "axios": "^1.16.0", "react": "^19.2.1", "react-dom": "^19.2.1", "react-markdown": "^10.1.0", @@ -2550,14 +2550,14 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", - "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz", + "integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "proxy-from-env": "^2.1.0" } }, "node_modules/bail": { @@ -4712,10 +4712,13 @@ } }, "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } }, "node_modules/psl": { "version": "1.15.0", diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package.json b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package.json index ddf690c6c514..a070350881e3 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package.json +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/package.json @@ -16,7 +16,7 @@ "@protobuf-ts/grpcweb-transport": "^2.9.6", "@protobuf-ts/runtime": "^2.9.6", "@protobuf-ts/runtime-rpc": "^2.9.6", - "axios": "^1.7.9", + "axios": "^1.16.0", "react": "^19.2.1", "react-dom": "^19.2.1", "react-markdown": "^10.1.0", diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock index 16779dcd3b6d..cd231c191799 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/src/ProcessFramework.Aspire.SignalR.ReactFrontend/yarn.lock @@ -1520,14 +1520,14 @@ asynckit@^0.4.0: resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== -axios@^1.7.9: - version "1.13.2" - resolved "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz" - integrity sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA== +axios@^1.16.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.16.0.tgz#f8e5dd931cef2a5f8c32216d5784eda2f8750eb7" + integrity sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w== dependencies: - follow-redirects "^1.15.6" - form-data "^4.0.4" - proxy-from-env "^1.1.0" + follow-redirects "^1.16.0" + form-data "^4.0.5" + proxy-from-env "^2.1.0" bail@^2.0.0: version "2.0.2" @@ -1950,12 +1950,12 @@ flatted@^3.2.9: resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz" integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== -follow-redirects@^1.15.6: +follow-redirects@^1.16.0: version "1.16.0" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== -form-data@^4.0.4: +form-data@^4.0.5: version "4.0.6" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.6.tgz#28e864e1b786dbebb68db1f452f9635278665827" integrity sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ== @@ -2709,10 +2709,10 @@ property-information@^7.0.0: resolved "https://registry.npmjs.org/property-information/-/property-information-7.0.0.tgz" integrity sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg== -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +proxy-from-env@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba" + integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA== psl@^1.1.33: version "1.15.0" From e99c633fba9e4005bdb9b90a1f5441945b781040 Mon Sep 17 00:00:00 2001 From: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> Date: Thu, 25 Jun 2026 10:39:45 +0100 Subject: [PATCH 24/33] .Net: Harden file path validation in Core, Document, and Web plugins (#14118) ## Motivation and Context This change hardens file system path handling in the file-based plugins. Previously, the path used for allowlist validation could differ from the path ultimately used for file I/O, so the two operations were not guaranteed to refer to the same file system location. ## Description - Adds a shared `PathUtilities.GetSafeFullPath` helper that produces a canonical full path for a given input. - Updates `FileIOPlugin`, `SessionsPythonPlugin`, `DocumentPlugin` and `WebFileDownloadPlugin` to validate and perform I/O against the same canonical path, and to compare paths using OS-appropriate string comparison. - Adds regression tests covering the new behavior. ## Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the SK Contribution Guidelines - [x] All unit tests pass, and I have added new tests where possible --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/System/PathUtilities.cs | 175 ++++++++++++ .../CodeInterpreter/SessionsPythonPlugin.cs | 26 +- .../src/Plugins/Plugins.Core/FileIOPlugin.cs | 33 ++- .../Plugins.Document/DocumentPlugin.cs | 25 +- .../Core/FileIOPluginTests.cs | 165 +++++++++++ .../Core/PathUtilitiesTests.cs | 259 ++++++++++++++++++ .../Core/SessionsPythonPluginTests.cs | 142 ++++++++++ .../Document/DocumentPluginTests.cs | 4 + .../Plugins.UnitTests.csproj | 1 + .../Web/WebFileDownloadPluginTests.cs | 46 +++- .../Plugins.Web/WebFileDownloadPlugin.cs | 36 ++- 11 files changed, 865 insertions(+), 47 deletions(-) create mode 100644 dotnet/src/InternalUtilities/src/System/PathUtilities.cs create mode 100644 dotnet/src/Plugins/Plugins.UnitTests/Core/PathUtilitiesTests.cs diff --git a/dotnet/src/InternalUtilities/src/System/PathUtilities.cs b/dotnet/src/InternalUtilities/src/System/PathUtilities.cs new file mode 100644 index 000000000000..404fe237b8b6 --- /dev/null +++ b/dotnet/src/InternalUtilities/src/System/PathUtilities.cs @@ -0,0 +1,175 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Runtime.InteropServices; + +namespace Microsoft.SemanticKernel; + +/// +/// Provides utility methods for secure path resolution, including symbolic link handling. +/// +[ExcludeFromCodeCoverage] +internal static class PathUtilities +{ + internal static StringComparison PathComparison { get; } = + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? StringComparison.OrdinalIgnoreCase + : StringComparison.Ordinal; + + /// + /// Returns the canonical full path for with symbolic links handled safely. + /// On .NET 6 and later, symbolic links are resolved to their final target. On older frameworks, + /// where links cannot be resolved safely, any path containing a symbolic link is rejected. + /// + /// The path to canonicalize. + /// The fully resolved canonical path. + /// + /// On frameworks older than .NET 6, thrown if the path contains a symbolic link. + /// + internal static string GetSafeFullPath(string path) + { + var fullPath = Path.GetFullPath(path); + +#if NET6_0_OR_GREATER + return ResolveExistingSegments(fullPath); +#else + ThrowIfPathContainsReparsePoint(fullPath); + return fullPath; +#endif + } + +#if NET6_0_OR_GREATER + private static string ResolveExistingSegments(string fullPath) + { + var root = Path.GetPathRoot(fullPath) ?? string.Empty; + return ResolveSegments(root, GetSegmentsAfterRoot(fullPath, root)); + } + + private static string ResolveSegments(string basePath, string[] segments) + { + var resolvedPath = basePath; + for (var i = 0; i < segments.Length; i++) + { + var candidatePath = CombinePath(resolvedPath, segments[i]); + + if (!TryGetFileSystemInfo(candidatePath, out var fileSystemInfo)) + { + return CombineRemainingPath(candidatePath, segments, i + 1); + } + + var linkTarget = ResolveLinkTarget(fileSystemInfo); + if (linkTarget is not null) + { + // The link target may itself contain unresolved symbolic links, + // so canonicalize it before continuing with the remaining segments. + resolvedPath = ResolveExistingSegments(linkTarget); + } + else + { + resolvedPath = candidatePath; + } + } + + return resolvedPath; + } + + private static bool TryGetFileSystemInfo(string path, [NotNullWhen(true)] out FileSystemInfo? fileSystemInfo) + { + if (!TryGetAttributes(path, out var attributes)) + { + fileSystemInfo = null; + return false; + } + + fileSystemInfo = (attributes & FileAttributes.Directory) != 0 + ? new DirectoryInfo(path) + : new FileInfo(path); + return true; + } + + private static string? ResolveLinkTarget(FileSystemInfo fileSystemInfo) + { + if ((fileSystemInfo.Attributes & FileAttributes.ReparsePoint) == 0) + { + return null; + } + + try + { + var target = fileSystemInfo.ResolveLinkTarget(returnFinalTarget: true); + return target?.FullName + ?? throw new InvalidOperationException( + $"Access denied: path contains a symbolic link that cannot be resolved at '{fileSystemInfo.FullName}'."); + } + catch (IOException) + { + throw new InvalidOperationException( + $"Access denied: path contains a symbolic link that cannot be resolved at '{fileSystemInfo.FullName}'."); + } + } +#endif + +#if !NET6_0_OR_GREATER + private static void ThrowIfPathContainsReparsePoint(string fullPath) + { + var root = Path.GetPathRoot(fullPath) ?? string.Empty; + var segments = GetSegmentsAfterRoot(fullPath, root); + + var currentPath = root; + foreach (var segment in segments) + { + currentPath = CombinePath(currentPath, segment); + + if (TryGetAttributes(currentPath, out var attributes) && + (attributes & FileAttributes.ReparsePoint) != 0) + { + throw new InvalidOperationException( + $"Access denied: path contains a symbolic link at '{currentPath}'."); + } + } + } +#endif + + private static string[] GetSegmentsAfterRoot(string fullPath, string root) + { + return fullPath.Substring(root.Length) + .Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, + StringSplitOptions.RemoveEmptyEntries); + } + + private static bool TryGetAttributes(string path, out FileAttributes attributes) + { + try + { + attributes = File.GetAttributes(path); + return true; + } + catch (FileNotFoundException) + { + } + catch (DirectoryNotFoundException) + { + } + + attributes = default; + return false; + } + + private static string CombinePath(string basePath, string segment) + { + return string.IsNullOrEmpty(basePath) ? segment : Path.Combine(basePath, segment); + } + + private static string CombineRemainingPath(string basePath, string[] segments, int startIndex) + { + var result = basePath; + for (var i = startIndex; i < segments.Length; i++) + { + result = Path.Combine(result, segments[i]); + } + + return result; + } +} diff --git a/dotnet/src/Plugins/Plugins.Core/CodeInterpreter/SessionsPythonPlugin.cs b/dotnet/src/Plugins/Plugins.Core/CodeInterpreter/SessionsPythonPlugin.cs index 7f8272031c9a..fc43e1ba7299 100644 --- a/dotnet/src/Plugins/Plugins.Core/CodeInterpreter/SessionsPythonPlugin.cs +++ b/dotnet/src/Plugins/Plugins.Core/CodeInterpreter/SessionsPythonPlugin.cs @@ -308,18 +308,18 @@ private string ValidateLocalPathForUpload(string localFilePath) "File upload requires 'AllowedUploadDirectories' to be configured."); } - var canonicalPath = Path.GetFullPath(localFilePath); + var canonicalPath = PathUtilities.GetSafeFullPath(localFilePath); foreach (var allowedDir in this._settings.AllowedUploadDirectories) { - var canonicalAllowedDir = Path.GetFullPath(allowedDir); + var canonicalAllowedDir = PathUtilities.GetSafeFullPath(allowedDir); // Ensure we match the directory correctly by appending separator var separator = Path.DirectorySeparatorChar.ToString(); - var allowedDirWithSeparator = canonicalAllowedDir.EndsWith(separator, StringComparison.OrdinalIgnoreCase) + var allowedDirWithSeparator = canonicalAllowedDir.EndsWith(separator, PathUtilities.PathComparison) ? canonicalAllowedDir : canonicalAllowedDir + separator; - if (canonicalPath.StartsWith(allowedDirWithSeparator, StringComparison.OrdinalIgnoreCase)) + if (canonicalPath.StartsWith(allowedDirWithSeparator, PathUtilities.PathComparison)) { return canonicalPath; } @@ -340,29 +340,31 @@ private string ValidateLocalPathForDownload(string localFilePath) // If no restrictions configured, allow all paths (permissive by default for downloads) if (this._settings.AllowedDownloadDirectories is null || !this._settings.AllowedDownloadDirectories.Any()) { - return Path.GetFullPath(localFilePath); + return PathUtilities.GetSafeFullPath(localFilePath); } - // Get the directory of the target file path - var targetDirectory = Path.GetDirectoryName(localFilePath); + var canonicalFilePath = PathUtilities.GetSafeFullPath(localFilePath); + + // Get the directory of the resolved target file path. + var targetDirectory = Path.GetDirectoryName(canonicalFilePath); if (string.IsNullOrEmpty(targetDirectory)) { targetDirectory = "."; } - var canonicalTargetDir = Path.GetFullPath(targetDirectory); - var canonicalFilePath = Path.GetFullPath(localFilePath); + var canonicalTargetDir = PathUtilities.GetSafeFullPath(targetDirectory); foreach (var allowedDir in this._settings.AllowedDownloadDirectories) { - var canonicalAllowedDir = Path.GetFullPath(allowedDir); + var canonicalAllowedDir = PathUtilities.GetSafeFullPath(allowedDir); // Ensure we match the directory correctly by appending separator var separator = Path.DirectorySeparatorChar.ToString(); - var allowedDirWithSeparator = canonicalAllowedDir.EndsWith(separator, StringComparison.OrdinalIgnoreCase) + var allowedDirWithSeparator = canonicalAllowedDir.EndsWith(separator, PathUtilities.PathComparison) ? canonicalAllowedDir : canonicalAllowedDir + separator; - if (canonicalTargetDir.StartsWith(allowedDirWithSeparator, StringComparison.OrdinalIgnoreCase)) + if (canonicalTargetDir.StartsWith(allowedDirWithSeparator, PathUtilities.PathComparison) + || (canonicalTargetDir + separator).Equals(allowedDirWithSeparator, PathUtilities.PathComparison)) { return canonicalFilePath; } diff --git a/dotnet/src/Plugins/Plugins.Core/FileIOPlugin.cs b/dotnet/src/Plugins/Plugins.Core/FileIOPlugin.cs index 9a94a08538a0..c67b8a9ad089 100644 --- a/dotnet/src/Plugins/Plugins.Core/FileIOPlugin.cs +++ b/dotnet/src/Plugins/Plugins.Core/FileIOPlugin.cs @@ -57,12 +57,12 @@ public IEnumerable? AllowedFolders [KernelFunction, Description("Read a file")] public async Task ReadAsync([Description("Source file")] string path) { - if (!this.IsFilePathAllowed(path)) + if (!this.TryGetAllowedFilePath(path, out var canonicalPath)) { throw new InvalidOperationException("Reading from the provided location is not allowed."); } - using var reader = File.OpenText(path); + using var reader = File.OpenText(canonicalPath); return await reader.ReadToEndAsync().ConfigureAwait(false); } @@ -80,19 +80,19 @@ public async Task WriteAsync( [Description("Destination file")] string path, [Description("File content")] string content) { - if (!this.IsFilePathAllowed(path)) + if (!this.TryGetAllowedFilePath(path, out var canonicalPath)) { throw new InvalidOperationException("Writing to the provided location is not allowed."); } - if (this.DisableFileOverwrite && File.Exists(path)) + if (this.DisableFileOverwrite && File.Exists(canonicalPath)) { throw new InvalidOperationException("Overwriting existing files is disabled."); } byte[] text = Encoding.UTF8.GetBytes(content); var fileMode = this.DisableFileOverwrite ? FileMode.CreateNew : FileMode.Create; - using var writer = new FileStream(path, fileMode, FileAccess.Write, FileShare.None); + using var writer = new FileStream(canonicalPath, fileMode, FileAccess.Write, FileShare.None); await writer.WriteAsync(text #if !NET , 0, text.Length @@ -108,9 +108,10 @@ await writer.WriteAsync(text /// to verify it is in the allowed folder list. Paths are canonicalized before comparison. /// Subdirectories of allowed folders are also permitted. /// - private bool IsFilePathAllowed(string path) + private bool TryGetAllowedFilePath(string path, out string canonicalPath) { Verify.NotNullOrWhiteSpace(path); + canonicalPath = string.Empty; if (path.StartsWith("\\\\", StringComparison.OrdinalIgnoreCase)) { @@ -124,10 +125,12 @@ private bool IsFilePathAllowed(string path) throw new ArgumentException("Invalid file path, a fully qualified file location must be specified.", nameof(path)); } - if (File.Exists(path) && File.GetAttributes(path).HasFlag(FileAttributes.ReadOnly)) + canonicalPath = PathUtilities.GetSafeFullPath(path); + + if (File.Exists(canonicalPath) && File.GetAttributes(canonicalPath).HasFlag(FileAttributes.ReadOnly)) { // Most environments will throw this with OpenWrite, but running inside docker on Linux will not. - throw new UnauthorizedAccessException($"File is read-only: {path}"); + throw new UnauthorizedAccessException($"File is read-only: {canonicalPath}"); } if (this._allowedFolders is null || this._allowedFolders.Count == 0) @@ -135,19 +138,23 @@ private bool IsFilePathAllowed(string path) return false; } - var canonicalDir = Path.GetFullPath(directoryPath); + var canonicalDir = Path.GetDirectoryName(canonicalPath); + if (string.IsNullOrEmpty(canonicalDir)) + { + throw new ArgumentException("Invalid file path, a fully qualified file location must be specified.", nameof(path)); + } foreach (var allowedFolder in this._allowedFolders) { - var canonicalAllowed = Path.GetFullPath(allowedFolder); + var canonicalAllowed = PathUtilities.GetSafeFullPath(allowedFolder); var separator = Path.DirectorySeparatorChar.ToString(); - if (!canonicalAllowed.EndsWith(separator, StringComparison.OrdinalIgnoreCase)) + if (!canonicalAllowed.EndsWith(separator, PathUtilities.PathComparison)) { canonicalAllowed += separator; } - if (canonicalDir.StartsWith(canonicalAllowed, StringComparison.OrdinalIgnoreCase) - || (canonicalDir + separator).Equals(canonicalAllowed, StringComparison.OrdinalIgnoreCase)) + if (canonicalDir.StartsWith(canonicalAllowed, PathUtilities.PathComparison) + || (canonicalDir + separator).Equals(canonicalAllowed, PathUtilities.PathComparison)) { return true; } diff --git a/dotnet/src/Plugins/Plugins.Document/DocumentPlugin.cs b/dotnet/src/Plugins/Plugins.Document/DocumentPlugin.cs index 2cc87da09a48..906668f261e3 100644 --- a/dotnet/src/Plugins/Plugins.Document/DocumentPlugin.cs +++ b/dotnet/src/Plugins/Plugins.Document/DocumentPlugin.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.ComponentModel; using System.IO; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -146,7 +145,7 @@ private static string CanonicalizePath(string path) { Verify.NotNullOrWhiteSpace(path); - if (path.StartsWith("\\\\", StringComparison.OrdinalIgnoreCase)) + if (IsUncOrExtendedPath(path)) { throw new ArgumentException("Invalid file path, UNC paths are not supported.", nameof(path)); } @@ -157,19 +156,19 @@ private static string CanonicalizePath(string path) // Re-check after expansion: an env var could have expanded to a UNC // or extended-path prefix (e.g., %NETSHARE% → \\server\share). - if (expanded.StartsWith("\\\\", StringComparison.OrdinalIgnoreCase)) + if (IsUncOrExtendedPath(expanded)) { throw new ArgumentException("Invalid file path, UNC paths are not supported.", nameof(path)); } - return Path.GetFullPath(expanded); + return PathUtilities.GetSafeFullPath(expanded); } - // Use case-insensitive comparison on Windows (case-insensitive FS), case-sensitive on Linux/macOS. - private static readonly StringComparison s_pathComparison = - RuntimeInformation.IsOSPlatform(OSPlatform.Windows) - ? StringComparison.OrdinalIgnoreCase - : StringComparison.Ordinal; + private static bool IsUncOrExtendedPath(string path) + { + return path.StartsWith("\\\\", StringComparison.OrdinalIgnoreCase) || + path.StartsWith("//", StringComparison.OrdinalIgnoreCase); + } /// /// Checks whether a canonicalized file path falls within one of the allowed directories. @@ -191,15 +190,15 @@ private bool IsFilePathAllowed(string canonicalPath) foreach (var allowedDirectory in this._allowedDirectories) { - var canonicalAllowed = Path.GetFullPath(allowedDirectory); + var canonicalAllowed = PathUtilities.GetSafeFullPath(allowedDirectory); var separator = Path.DirectorySeparatorChar.ToString(); - if (!canonicalAllowed.EndsWith(separator, s_pathComparison)) + if (!canonicalAllowed.EndsWith(separator, PathUtilities.PathComparison)) { canonicalAllowed += separator; } - if (directoryPath.StartsWith(canonicalAllowed, s_pathComparison) - || (directoryPath + separator).Equals(canonicalAllowed, s_pathComparison)) + if (directoryPath.StartsWith(canonicalAllowed, PathUtilities.PathComparison) + || (directoryPath + separator).Equals(canonicalAllowed, PathUtilities.PathComparison)) { return true; } diff --git a/dotnet/src/Plugins/Plugins.UnitTests/Core/FileIOPluginTests.cs b/dotnet/src/Plugins/Plugins.UnitTests/Core/FileIOPluginTests.cs index 50b44004233d..29d5ba6c5d1d 100644 --- a/dotnet/src/Plugins/Plugins.UnitTests/Core/FileIOPluginTests.cs +++ b/dotnet/src/Plugins/Plugins.UnitTests/Core/FileIOPluginTests.cs @@ -2,6 +2,7 @@ using System; using System.IO; +using System.Runtime.InteropServices; using System.Threading.Tasks; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Plugins.Core; @@ -142,4 +143,168 @@ public async Task ItCannotReadFromDisallowedFoldersAsync() await Assert.ThrowsAsync(async () => await plugin.ReadAsync(Path.Combine("\\\\UNC\\server\\folder\\myfile.txt", Path.GetRandomFileName()))); await Assert.ThrowsAsync(async () => await plugin.ReadAsync(Path.Combine("", Path.GetRandomFileName()))); } + + [Fact] + public async Task ItCannotReadThroughSymlinkOutsideAllowedFoldersAsync() + { + // Arrange + var tempDir = Path.Combine(Path.GetTempPath(), $"FileIOPluginTests_{Guid.NewGuid():N}"); + var allowedDir = Path.Combine(tempDir, "allowed"); + var outsideDir = Path.Combine(tempDir, "outside"); + Directory.CreateDirectory(allowedDir); + Directory.CreateDirectory(outsideDir); + + try + { + var outsideFile = Path.Combine(outsideDir, "secret.txt"); + await File.WriteAllTextAsync(outsideFile, "secret"); + + var symlinkPath = Path.Combine(allowedDir, "link.txt"); + try + { + File.CreateSymbolicLink(symlinkPath, outsideFile); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) + { + // Skip: this environment does not permit symbolic link creation (e.g., Windows without the required privilege). + return; + } + + var plugin = new FileIOPlugin() { AllowedFolders = [allowedDir] }; + + // Act & Assert + await Assert.ThrowsAsync(() => plugin.ReadAsync(symlinkPath)); + } + finally + { + TryDeleteDirectory(tempDir); + } + } + + [Fact] + public async Task ItCannotWriteThroughSymlinkOutsideAllowedFoldersAsync() + { + // Arrange + var tempDir = Path.Combine(Path.GetTempPath(), $"FileIOPluginTests_{Guid.NewGuid():N}"); + var allowedDir = Path.Combine(tempDir, "allowed"); + var outsideDir = Path.Combine(tempDir, "outside"); + Directory.CreateDirectory(allowedDir); + Directory.CreateDirectory(outsideDir); + + try + { + var outsideFile = Path.Combine(outsideDir, "secret.txt"); + await File.WriteAllTextAsync(outsideFile, "secret"); + + var symlinkPath = Path.Combine(allowedDir, "link.txt"); + try + { + File.CreateSymbolicLink(symlinkPath, outsideFile); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) + { + // Skip: this environment does not permit symbolic link creation (e.g., Windows without the required privilege). + return; + } + + var plugin = new FileIOPlugin() + { + AllowedFolders = [allowedDir], + DisableFileOverwrite = false + }; + + // Act & Assert + await Assert.ThrowsAsync(() => plugin.WriteAsync(symlinkPath, "changed")); + Assert.Equal("secret", await File.ReadAllTextAsync(outsideFile)); + } + finally + { + TryDeleteDirectory(tempDir); + } + } + + [Fact] + public async Task ItCannotWriteThroughDanglingSymlinkOutsideAllowedFoldersAsync() + { + // Arrange + var tempDir = Path.Combine(Path.GetTempPath(), $"FileIOPluginTests_{Guid.NewGuid():N}"); + var allowedDir = Path.Combine(tempDir, "allowed"); + var outsideDir = Path.Combine(tempDir, "outside"); + Directory.CreateDirectory(allowedDir); + Directory.CreateDirectory(outsideDir); + + try + { + var outsideFile = Path.Combine(outsideDir, "created-through-link.txt"); + var symlinkPath = Path.Combine(allowedDir, "link.txt"); + try + { + File.CreateSymbolicLink(symlinkPath, outsideFile); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) + { + // Skip: this environment does not permit symbolic link creation (e.g., Windows without the required privilege). + return; + } + + var plugin = new FileIOPlugin() + { + AllowedFolders = [allowedDir], + DisableFileOverwrite = false + }; + + // Act & Assert + await Assert.ThrowsAsync(() => plugin.WriteAsync(symlinkPath, "created")); + Assert.False(File.Exists(outsideFile)); + } + finally + { + TryDeleteDirectory(tempDir); + } + } + + [Fact] + public async Task ItUsesCaseSensitiveAllowListComparisonOnLinuxAsync() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return; + } + + // Arrange + var tempDir = Path.Combine(Path.GetTempPath(), $"FileIOPluginTests_{Guid.NewGuid():N}"); + var allowedDir = Path.Combine(tempDir, "Allowed"); + var disallowedDir = Path.Combine(tempDir, "allowed"); + Directory.CreateDirectory(allowedDir); + Directory.CreateDirectory(disallowedDir); + + try + { + var disallowedFile = Path.Combine(disallowedDir, "secret.txt"); + await File.WriteAllTextAsync(disallowedFile, "secret"); + + var plugin = new FileIOPlugin() { AllowedFolders = [allowedDir] }; + + // Act & Assert + await Assert.ThrowsAsync(() => plugin.ReadAsync(disallowedFile)); + } + finally + { + TryDeleteDirectory(tempDir); + } + } + + private static void TryDeleteDirectory(string path) + { + try + { + Directory.Delete(path, recursive: true); + } + catch (IOException) + { + } + catch (UnauthorizedAccessException) + { + } + } } diff --git a/dotnet/src/Plugins/Plugins.UnitTests/Core/PathUtilitiesTests.cs b/dotnet/src/Plugins/Plugins.UnitTests/Core/PathUtilitiesTests.cs new file mode 100644 index 000000000000..8b6626e7c6b6 --- /dev/null +++ b/dotnet/src/Plugins/Plugins.UnitTests/Core/PathUtilitiesTests.cs @@ -0,0 +1,259 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.IO; +using Microsoft.SemanticKernel; +using Xunit; + +namespace SemanticKernel.Plugins.UnitTests.Core; + +public sealed class PathUtilitiesTests : IDisposable +{ + private readonly string _tempDir; + + public PathUtilitiesTests() + { + this._tempDir = Path.Combine(Path.GetTempPath(), $"PathUtilitiesTests_{Guid.NewGuid():N}"); + Directory.CreateDirectory(this._tempDir); + } + + [Fact] + public void GetSafeFullPathReturnsCanonicalPathForRegularFile() + { + // Arrange + var filePath = Path.Combine(this._tempDir, "regular.txt"); + File.WriteAllText(filePath, "test"); + + // Act + var resolved = PathUtilities.GetSafeFullPath(filePath); + + // Assert + Assert.Equal(Path.GetFullPath(filePath), resolved); + } + + [Fact] + public void GetSafeFullPathResolvesRelativePaths() + { + // Arrange + var filePath = Path.Combine(this._tempDir, "subdir", "..", "regular.txt"); + var expectedPath = Path.GetFullPath(Path.Combine(this._tempDir, "regular.txt")); + File.WriteAllText(expectedPath, "test"); + + // Act + var resolved = PathUtilities.GetSafeFullPath(filePath); + + // Assert + Assert.Equal(expectedPath, resolved); + } + + [Fact] + public void GetSafeFullPathHandlesNonExistentFile() + { + // Arrange + var filePath = Path.Combine(this._tempDir, "nonexistent.txt"); + + // Act + var resolved = PathUtilities.GetSafeFullPath(filePath); + + // Assert + Assert.Equal(Path.GetFullPath(filePath), resolved); + } + + [Fact] + public void GetSafeFullPathResolvesFileSymlink() + { + // Arrange + var targetFile = Path.Combine(this._tempDir, "target.txt"); + File.WriteAllText(targetFile, "secret content"); + + var symlinkPath = Path.Combine(this._tempDir, "link.txt"); + + try + { + File.CreateSymbolicLink(symlinkPath, targetFile); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) + { + // Skip: this environment does not permit symbolic link creation (e.g., Windows without the required privilege). + return; + } + + // Act + var resolved = PathUtilities.GetSafeFullPath(symlinkPath); + + // Assert — should resolve to the actual target, not the symlink path + Assert.Equal(Path.GetFullPath(targetFile), resolved); + } + + [Fact] + public void GetSafeFullPathResolvesSymlinkPointingOutsideDirectory() + { + // Arrange - simulates the attack scenario: + // An allowed directory contains a symlink pointing to a file outside it + var allowedDir = Path.Combine(this._tempDir, "allowed"); + var outsideDir = Path.Combine(this._tempDir, "outside"); + Directory.CreateDirectory(allowedDir); + Directory.CreateDirectory(outsideDir); + + var sensitiveFile = Path.Combine(outsideDir, "sensitive.txt"); + File.WriteAllText(sensitiveFile, "sensitive data"); + + var symlinkInAllowedDir = Path.Combine(allowedDir, "link.txt"); + + try + { + File.CreateSymbolicLink(symlinkInAllowedDir, sensitiveFile); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) + { + // Skip: this environment does not permit symbolic link creation (e.g., Windows without the required privilege). + return; + } + + // Act + var resolved = PathUtilities.GetSafeFullPath(symlinkInAllowedDir); + + // Assert — resolved path should be OUTSIDE the allowed directory + // This proves the symlink bypass is prevented + var allowedDirCanonical = Path.GetFullPath(allowedDir) + Path.DirectorySeparatorChar; + Assert.False(resolved.StartsWith(allowedDirCanonical, StringComparison.OrdinalIgnoreCase), + $"Resolved path '{resolved}' should NOT start with allowed dir '{allowedDirCanonical}'. " + + "If it does, the symlink bypass vulnerability is still present."); + Assert.Equal(Path.GetFullPath(sensitiveFile), resolved); + } + + [Fact] + public void GetSafeFullPathResolvesDirectorySymlink() + { + // Arrange - symlink directory inside allowed dir points to outside + var allowedDir = Path.Combine(this._tempDir, "allowed"); + var outsideDir = Path.Combine(this._tempDir, "outside"); + Directory.CreateDirectory(allowedDir); + Directory.CreateDirectory(outsideDir); + + File.WriteAllText(Path.Combine(outsideDir, "secret.txt"), "secret"); + + var symlinkDir = Path.Combine(allowedDir, "linkeddir"); + + try + { + Directory.CreateSymbolicLink(symlinkDir, outsideDir); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) + { + // Skip: this environment does not permit symbolic link creation (e.g., Windows without the required privilege). + return; + } + + var fileViaSymlink = Path.Combine(symlinkDir, "secret.txt"); + + // Act + var resolved = PathUtilities.GetSafeFullPath(fileViaSymlink); + + // Assert — resolved path should point to the real location outside allowed dir + var expectedPath = Path.GetFullPath(Path.Combine(outsideDir, "secret.txt")); + Assert.Equal(expectedPath, resolved); + } + + [Fact] + public void GetSafeFullPathResolvesNestedDirectorySymlink() + { + // Arrange + var allowedDir = Path.Combine(this._tempDir, "allowed"); + var outsideDir = Path.Combine(this._tempDir, "outside"); + var nestedOutsideDir = Path.Combine(outsideDir, "nested"); + Directory.CreateDirectory(allowedDir); + Directory.CreateDirectory(nestedOutsideDir); + + File.WriteAllText(Path.Combine(nestedOutsideDir, "secret.txt"), "secret"); + + var symlinkDir = Path.Combine(allowedDir, "linkeddir"); + + try + { + Directory.CreateSymbolicLink(symlinkDir, outsideDir); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) + { + // Skip: this environment does not permit symbolic link creation (e.g., Windows without the required privilege). + return; + } + + var fileViaNestedSymlink = Path.Combine(symlinkDir, "nested", "secret.txt"); + + // Act + var resolved = PathUtilities.GetSafeFullPath(fileViaNestedSymlink); + + // Assert + var expectedPath = Path.GetFullPath(Path.Combine(nestedOutsideDir, "secret.txt")); + Assert.Equal(expectedPath, resolved); + } + + [Fact] + public void GetSafeFullPathResolvesChainedSymlinks() + { + // Arrange - link1 -> link2 -> realTarget + var realTarget = Path.Combine(this._tempDir, "real.txt"); + File.WriteAllText(realTarget, "secret content"); + + var link2 = Path.Combine(this._tempDir, "link2.txt"); + var link1 = Path.Combine(this._tempDir, "link1.txt"); + + try + { + File.CreateSymbolicLink(link2, realTarget); + File.CreateSymbolicLink(link1, link2); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) + { + // Skip: this environment does not permit symbolic link creation (e.g., Windows without the required privilege). + return; + } + + // Act + var resolved = PathUtilities.GetSafeFullPath(link1); + + // Assert — should resolve through the whole chain to the real target + Assert.Equal(Path.GetFullPath(realTarget), resolved); + } + + [Fact] + public void GetSafeFullPathResolvesDanglingSymlinkTarget() + { + // Arrange + var missingTarget = Path.Combine(this._tempDir, "missing.txt"); + var symlinkPath = Path.Combine(this._tempDir, "dangling-link.txt"); + + try + { + File.CreateSymbolicLink(symlinkPath, missingTarget); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) + { + // Skip: this environment does not permit symbolic link creation (e.g., Windows without the required privilege). + return; + } + + // Act + var resolved = PathUtilities.GetSafeFullPath(symlinkPath); + + // Assert + Assert.Equal(Path.GetFullPath(missingTarget), resolved); + } + + public void Dispose() + { + try + { + Directory.Delete(this._tempDir, recursive: true); + } + catch (IOException) + { + // Best effort cleanup + } + catch (UnauthorizedAccessException) + { + // Best effort cleanup + } + } +} diff --git a/dotnet/src/Plugins/Plugins.UnitTests/Core/SessionsPythonPluginTests.cs b/dotnet/src/Plugins/Plugins.UnitTests/Core/SessionsPythonPluginTests.cs index e39891d90f07..e4fc1cf2de12 100644 --- a/dotnet/src/Plugins/Plugins.UnitTests/Core/SessionsPythonPluginTests.cs +++ b/dotnet/src/Plugins/Plugins.UnitTests/Core/SessionsPythonPluginTests.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Runtime.InteropServices; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -472,6 +473,133 @@ public async Task ItShouldDenyDownloadOutsideAllowedDirectoriesAsync() Assert.Contains("not within allowed download directories", exception.Message); } + [Fact] + public async Task ItShouldDenyDownloadThroughSymlinkOutsideAllowedDirectoriesAsync() + { + // Arrange + var tempDir = Path.Combine(Path.GetTempPath(), $"SessionsPythonPluginTests_{Guid.NewGuid():N}"); + var allowedDir = Path.Combine(tempDir, "allowed"); + var outsideDir = Path.Combine(tempDir, "outside"); + Directory.CreateDirectory(allowedDir); + Directory.CreateDirectory(outsideDir); + + try + { + var outsideFile = Path.Combine(outsideDir, "download.txt"); + await File.WriteAllTextAsync(outsideFile, "existing"); + + var symlinkPath = Path.Combine(allowedDir, "download.txt"); + try + { + File.CreateSymbolicLink(symlinkPath, outsideFile); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) + { + // Skip: this environment does not permit symbolic link creation (e.g., Windows without the required privilege). + return; + } + + var settings = new SessionsPythonSettings( + sessionId: Guid.NewGuid().ToString(), + endpoint: new Uri("http://localhost:8888")) + { + AllowedDownloadDirectories = new[] { allowedDir } + }; + + var plugin = new SessionsPythonPlugin(settings, this._httpClientFactory); + + // Act & Assert + var exception = await Assert.ThrowsAsync( + () => plugin.DownloadFileAsync("test.txt", symlinkPath)); + + Assert.Contains("not within allowed download directories", exception.Message); + } + finally + { + TryDeleteDirectory(tempDir); + } + } + + [Fact] + public async Task ItShouldAllowDownloadDirectlyInsideAllowedDirectoryAsync() + { + // Arrange + var tempDir = Path.Combine(Path.GetTempPath(), $"SessionsPythonPluginTests_{Guid.NewGuid():N}"); + Directory.CreateDirectory(tempDir); + + try + { + var responseContent = new byte[] { 1, 2, 3 }; + this._messageHandlerStub.ResponseToReturn = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new ByteArrayContent(responseContent), + }; + + var settings = new SessionsPythonSettings( + sessionId: Guid.NewGuid().ToString(), + endpoint: new Uri("http://localhost:8888")) + { + AllowedDownloadDirectories = new[] { tempDir } + }; + + var plugin = new SessionsPythonPlugin(settings, this._httpClientFactory); + var downloadPath = Path.Combine(tempDir, "download.txt"); + + // Act + var result = await plugin.DownloadFileAsync("test.txt", downloadPath); + + // Assert + Assert.Equal(responseContent, result); + Assert.Equal(responseContent, await File.ReadAllBytesAsync(downloadPath)); + } + finally + { + TryDeleteDirectory(tempDir); + } + } + + [Fact] + public async Task ItShouldDenyUploadWithDifferentPathCasingOnLinuxAsync() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return; + } + + // Arrange + var tempDir = Path.Combine(Path.GetTempPath(), $"SessionsPythonPluginTests_{Guid.NewGuid():N}"); + var allowedDir = Path.Combine(tempDir, "Allowed"); + var disallowedDir = Path.Combine(tempDir, "allowed"); + Directory.CreateDirectory(allowedDir); + Directory.CreateDirectory(disallowedDir); + + try + { + var disallowedFile = Path.Combine(disallowedDir, "secret.txt"); + await File.WriteAllTextAsync(disallowedFile, "secret"); + + var settings = new SessionsPythonSettings( + sessionId: Guid.NewGuid().ToString(), + endpoint: new Uri("http://localhost:8888")) + { + EnableDangerousFileUploads = true, + AllowedUploadDirectories = new[] { allowedDir } + }; + + var plugin = new SessionsPythonPlugin(settings, this._httpClientFactory); + + // Act & Assert + var exception = await Assert.ThrowsAsync( + () => plugin.UploadFileAsync("test.txt", disallowedFile)); + + Assert.Contains("not within allowed upload directories", exception.Message); + } + finally + { + TryDeleteDirectory(tempDir); + } + } + [Fact] public async Task ItShouldDenyUploadWithPathTraversalAsync() { @@ -506,4 +634,18 @@ public void Dispose() this._httpClient.Dispose(); this._messageHandlerStub.Dispose(); } + + private static void TryDeleteDirectory(string path) + { + try + { + Directory.Delete(path, recursive: true); + } + catch (IOException) + { + } + catch (UnauthorizedAccessException) + { + } + } } diff --git a/dotnet/src/Plugins/Plugins.UnitTests/Document/DocumentPluginTests.cs b/dotnet/src/Plugins/Plugins.UnitTests/Document/DocumentPluginTests.cs index 1308485da8e8..f31232f34e71 100644 --- a/dotnet/src/Plugins/Plugins.UnitTests/Document/DocumentPluginTests.cs +++ b/dotnet/src/Plugins/Plugins.UnitTests/Document/DocumentPluginTests.cs @@ -186,6 +186,10 @@ public async Task ItDeniesUncPathsAsync() // Act & Assert — UNC paths are rejected await Assert.ThrowsAnyAsync(async () => await target.ReadTextAsync("\\\\UNC\\server\\folder\\file.docx")); await Assert.ThrowsAnyAsync(async () => await target.AppendTextAsync("text", "\\\\UNC\\server\\folder\\file.docx")); + + // Act & Assert — forward-slash UNC paths are rejected too + await Assert.ThrowsAnyAsync(async () => await target.ReadTextAsync("//UNC/server/folder/file.docx")); + await Assert.ThrowsAnyAsync(async () => await target.AppendTextAsync("text", "//UNC/server/folder/file.docx")); } [Fact] diff --git a/dotnet/src/Plugins/Plugins.UnitTests/Plugins.UnitTests.csproj b/dotnet/src/Plugins/Plugins.UnitTests/Plugins.UnitTests.csproj index 9ed1e93acca1..cd444b483e18 100644 --- a/dotnet/src/Plugins/Plugins.UnitTests/Plugins.UnitTests.csproj +++ b/dotnet/src/Plugins/Plugins.UnitTests/Plugins.UnitTests.csproj @@ -40,6 +40,7 @@ + diff --git a/dotnet/src/Plugins/Plugins.UnitTests/Web/WebFileDownloadPluginTests.cs b/dotnet/src/Plugins/Plugins.UnitTests/Web/WebFileDownloadPluginTests.cs index 7a552dc27529..6d0ce6f5aeb4 100644 --- a/dotnet/src/Plugins/Plugins.UnitTests/Web/WebFileDownloadPluginTests.cs +++ b/dotnet/src/Plugins/Plugins.UnitTests/Web/WebFileDownloadPluginTests.cs @@ -3,6 +3,7 @@ using System; using System.IO; using System.Net.Http; +using System.Runtime.InteropServices; using System.Threading.Tasks; using Microsoft.SemanticKernel.Plugins.Web; using Xunit; @@ -155,15 +156,54 @@ public async Task DownloadToFileFailsForInvalidParametersAsync() await Assert.ThrowsAsync(async () => await webFileDownload.DownloadToFileAsync(validUri, validFilePath)); await Assert.ThrowsAsync(async () => await webFileDownload.DownloadToFileAsync(invalidUri, validFilePath)); await Assert.ThrowsAsync(async () => await webFileDownload.DownloadToFileAsync(validUri, invalidFilePath)); - // UNC paths are rejected as ArgumentException on Windows; on Linux Path.GetFullPath - // canonicalizes them to a regular path, so they are caught by the AllowedFolders check instead. - await Assert.ThrowsAnyAsync(async () => await webFileDownload.DownloadToFileAsync(validUri, "\\\\UNC\\server\\folder\\myfile.txt")); + await Assert.ThrowsAsync(async () => await webFileDownload.DownloadToFileAsync(validUri, "\\\\UNC\\server\\folder\\myfile.txt")); + await Assert.ThrowsAsync(async () => await webFileDownload.DownloadToFileAsync(validUri, "//UNC/server/folder/myfile.txt")); + await Assert.ThrowsAsync(async () => await webFileDownload.DownloadToFileAsync(validUri, "//?/C:/Windows/win.ini")); await Assert.ThrowsAsync(async () => await webFileDownload.DownloadToFileAsync(validUri, "")); // Relative paths are now canonicalized to absolute paths via Path.GetFullPath, // so they are caught by the AllowedFolders check rather than the "fully qualified" check. await Assert.ThrowsAsync(async () => await webFileDownload.DownloadToFileAsync(validUri, "myfile.txt")); } + [Fact] + public async Task DownloadToFileUsesCaseSensitiveAllowListComparisonOnLinuxAsync() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return; + } + + // Arrange + this._messageHandlerStub.AddImageResponse(File.ReadAllBytes(SKLogoPng)); + var uri = new Uri("https://raw.githubusercontent.com/microsoft/semantic-kernel/refs/heads/main/docs/images/sk_logo.png"); + var tempDir = Path.Combine(Path.GetTempPath(), $"WebFileDownloadPluginTests_{Guid.NewGuid():N}"); + var allowedDir = Path.Combine(tempDir, "Allowed"); + var disallowedDir = Path.Combine(tempDir, "allowed"); + Directory.CreateDirectory(allowedDir); + Directory.CreateDirectory(disallowedDir); + + try + { + var webFileDownload = new WebFileDownloadPlugin() + { + AllowedDomains = ["raw.githubusercontent.com"], + AllowedFolders = [allowedDir] + }; + + var disallowedFile = Path.Combine(disallowedDir, "download.txt"); + + // Act & Assert + await Assert.ThrowsAsync(() => webFileDownload.DownloadToFileAsync(uri, disallowedFile)); + } + finally + { + if (Path.Exists(tempDir)) + { + Directory.Delete(tempDir, true); + } + } + } + /// public void Dispose() { diff --git a/dotnet/src/Plugins/Plugins.Web/WebFileDownloadPlugin.cs b/dotnet/src/Plugins/Plugins.Web/WebFileDownloadPlugin.cs index b420b07008a1..d410bb8e22f0 100644 --- a/dotnet/src/Plugins/Plugins.Web/WebFileDownloadPlugin.cs +++ b/dotnet/src/Plugins/Plugins.Web/WebFileDownloadPlugin.cs @@ -122,7 +122,7 @@ public async Task DownloadToFileAsync( throw new InvalidOperationException("Downloading from the provided location is not allowed."); } - var expandedFilePath = Path.GetFullPath(Environment.ExpandEnvironmentVariables(filePath)); + var expandedFilePath = CanonicalizePath(filePath); if (!this.IsFilePathAllowed(expandedFilePath)) { throw new InvalidOperationException("Downloading to the provided location is not allowed."); @@ -199,6 +199,30 @@ private bool IsUriAllowed(Uri uri) && this._allowedDomains.Contains(uri.Host); } + private static string CanonicalizePath(string path) + { + Verify.NotNullOrWhiteSpace(path); + + if (IsUncOrExtendedPath(path)) + { + throw new ArgumentException("Invalid file path, UNC paths are not supported.", nameof(path)); + } + + var expanded = Environment.ExpandEnvironmentVariables(path); + if (IsUncOrExtendedPath(expanded)) + { + throw new ArgumentException("Invalid file path, UNC paths are not supported.", nameof(path)); + } + + return PathUtilities.GetSafeFullPath(expanded); + } + + private static bool IsUncOrExtendedPath(string path) + { + return path.StartsWith("\\\\", StringComparison.OrdinalIgnoreCase) || + path.StartsWith("//", StringComparison.OrdinalIgnoreCase); + } + /// /// If a list of allowed folder has been provided, the folder of the provided filePath is checked /// to verify it is in the allowed folder list. Paths are canonicalized before comparison. @@ -231,19 +255,19 @@ private bool IsFilePathAllowed(string path) return false; } - var canonicalDir = Path.GetFullPath(directoryPath); + var canonicalDir = PathUtilities.GetSafeFullPath(directoryPath); foreach (var allowedFolder in this._allowedFolders) { - var canonicalAllowed = Path.GetFullPath(allowedFolder); + var canonicalAllowed = PathUtilities.GetSafeFullPath(allowedFolder); var separator = Path.DirectorySeparatorChar.ToString(); - if (!canonicalAllowed.EndsWith(separator, StringComparison.OrdinalIgnoreCase)) + if (!canonicalAllowed.EndsWith(separator, PathUtilities.PathComparison)) { canonicalAllowed += separator; } - if (canonicalDir.StartsWith(canonicalAllowed, StringComparison.OrdinalIgnoreCase) - || (canonicalDir + separator).Equals(canonicalAllowed, StringComparison.OrdinalIgnoreCase)) + if (canonicalDir.StartsWith(canonicalAllowed, PathUtilities.PathComparison) + || (canonicalDir + separator).Equals(canonicalAllowed, PathUtilities.PathComparison)) { return true; } From cf9af8b966841e8f16d528bd0f2c69c51213b68d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jun 2026 14:21:45 +0100 Subject: [PATCH 25/33] .Net: Bump axios to 1.16.0 and form-data to 4.0.6 in /dotnet/samples/Demos/ProcessFrameworkWithSignalR (#13858) ### Motivation and Context This update is required to resolve the current Dependabot security alerts for the sample npm manifest in `dotnet/samples/Demos/ProcessFrameworkWithSignalR`. ### Description Updates the sample manifest to require `axios` `^1.16.0` and regenerates the lockfile so the resolved dependency set includes: - `axios` `1.16.0` - `form-data` `4.0.6` - compatible transitive updates such as `follow-redirects` `1.16.0` These changes keep the scope limited to the sample's `package.json` and `package-lock.json` while clearing the reported npm audit findings for this manifest. ### Contribution Checklist - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone :smile: > **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> --- .../package-lock.json | 47 ++++++++++--------- .../ProcessFrameworkWithSignalR/package.json | 2 +- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/package-lock.json b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/package-lock.json index 8c3670dc3cf8..0777ede19616 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/package-lock.json +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/package-lock.json @@ -5,7 +5,7 @@ "packages": { "": { "dependencies": { - "axios": "^1.12.0" + "axios": "^1.16.0" } }, "node_modules/asynckit": { @@ -15,14 +15,14 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.0.tgz", - "integrity": "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz", + "integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "proxy-from-env": "^2.1.0" } }, "node_modules/call-bind-apply-helpers": { @@ -119,9 +119,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -139,16 +139,16 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -240,9 +240,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -282,10 +282,13 @@ } }, "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } } } } diff --git a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/package.json b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/package.json index b541fde4f83e..783d7858c2f7 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithSignalR/package.json +++ b/dotnet/samples/Demos/ProcessFrameworkWithSignalR/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "axios": "^1.12.0" + "axios": "^1.16.0" } } From dfc5227227352e7cf4b11de1d9b8e49ebc7b43ff Mon Sep 17 00:00:00 2001 From: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> Date: Thu, 25 Jun 2026 14:37:21 +0100 Subject: [PATCH 26/33] .Net: Update .NET SDK to 10.0.301 (#14119) Updates the .NET SDK version in `dotnet/global.json` from `10.0.100` to `10.0.301`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/global.json b/dotnet/global.json index 21f1386b7c54..869bf826236f 100644 --- a/dotnet/global.json +++ b/dotnet/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "10.0.100", + "version": "10.0.301", "rollForward": "major", "allowPrerelease": false } From efa3268a09cae98322c2aab0927a69665b1f27a9 Mon Sep 17 00:00:00 2001 From: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> Date: Tue, 30 Jun 2026 15:51:30 +0100 Subject: [PATCH 27/33] Python: Enforce excluded_functions on MCP tool invocation path (#14124) ### Motivation and Context The MCP server created by `create_mcp_server_from_kernel` (and the `Kernel.as_mcp_server` wrapper) accepts an `excluded_functions` argument to keep selected kernel functions off the server. Previously this list was applied only when building the tool set advertised by the `list_tools` handler; the `call_tool` handler did not consult it and forwarded the client-supplied name straight to the kernel. As a result the set of advertised tools and the set of callable tools could diverge. ### Description - Derive a single `exposed_names` set from `functions_to_expose` and check it in the `call_tool` handler, returning a `METHOD_NOT_FOUND` error for any name that is not exposed. - Remove a leftover `print` debug statement in `_call_kernel_function`. - Add a unit test covering the `call_tool` behavior for a non-exposed function. ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the SK Contribution Guidelines - [x] All unit tests pass, and I have added new tests where possible --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- python/semantic_kernel/connectors/mcp.py | 11 ++++- python/tests/unit/connectors/mcp/test_mcp.py | 51 ++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/python/semantic_kernel/connectors/mcp.py b/python/semantic_kernel/connectors/mcp.py index 6d7f8d2e182d..9282e56c66af 100644 --- a/python/semantic_kernel/connectors/mcp.py +++ b/python/semantic_kernel/connectors/mcp.py @@ -1023,6 +1023,7 @@ def create_mcp_server_from_kernel( functions_to_expose = [ func for func in kernel.get_full_list_of_function_metadata() if func.name not in (excluded_functions or []) ] + exposed_names = frozenset(func.name for func in functions_to_expose) if len(functions_to_expose) > 0: @@ -1058,8 +1059,15 @@ async def _call_tool( *args: Any, ) -> Sequence[types.TextContent | types.ImageContent | types.AudioContent | types.EmbeddedResource]: """Call a tool in the kernel.""" - await _log(level="debug", data=f"Calling tool with args: {args}") function_name, arguments = args[0], args[1] + if function_name not in exposed_names: + raise McpError( + error=types.ErrorData( + code=types.METHOD_NOT_FOUND, + message=f"Unknown tool: {function_name}", + ) + ) + await _log(level="debug", data=f"Calling tool: {function_name}") result = await _call_kernel_function(function_name, arguments) if result: value = result.value @@ -1165,7 +1173,6 @@ async def _set_logging_level(level: types.LoggingLevel) -> None: async def _call_kernel_function(function_name: str, arguments: Any) -> FunctionResult | None: function = kernel.get_function(plugin_name=None, function_name=function_name) arguments["server"] = server - print("arguments", arguments) return await function.invoke(kernel=kernel, **arguments) return server diff --git a/python/tests/unit/connectors/mcp/test_mcp.py b/python/tests/unit/connectors/mcp/test_mcp.py index dc8ea38330d3..2fe5052c6f61 100644 --- a/python/tests/unit/connectors/mcp/test_mcp.py +++ b/python/tests/unit/connectors/mcp/test_mcp.py @@ -406,3 +406,54 @@ async def test_mcp_normalization_function(mock_session, list_tool_calls_with_sla assert _normalize_mcp_name("weird\\name with spaces") == "weird-name-with-spaces" assert _normalize_mcp_name("simple_name") == "simple_name" assert _normalize_mcp_name("Name-With.Dots_And-Hyphens") == "Name-With.Dots_And-Hyphens" + + +async def test_excluded_function_cannot_be_called(kernel: "Kernel"): + """Test that excluded functions are rejected at call time, not just hidden from listing.""" + from semantic_kernel.connectors.mcp import create_mcp_server_from_kernel + from semantic_kernel.functions.kernel_function_decorator import kernel_function + + side_effect_called = False + + @kernel_function(name="public_echo") + def public_echo(message: str) -> str: + return f"echo: {message}" + + @kernel_function(name="secret_admin") + def secret_admin(target: str) -> str: + nonlocal side_effect_called + side_effect_called = True + return f"privileged action on {target}" + + kernel.add_function(plugin_name="tools", function=public_echo) + kernel.add_function(plugin_name="tools", function=secret_admin) + + server = create_mcp_server_from_kernel(kernel, excluded_functions=["secret_admin"]) + + # Verify the server was created with handlers + assert types.ListToolsRequest in server.request_handlers + assert types.CallToolRequest in server.request_handlers + + # Mock _get_cached_tool_definition to bypass SDK request context requirements + # (normally set by a real MCP session transport) + async def _fake_get_cached_tool_definition(tool_name): + return None + + server._get_cached_tool_definition = _fake_get_cached_tool_definition + + # Build a proper CallToolRequest as the MCP SDK would send + call_tool_request = types.CallToolRequest( + method="tools/call", + params=types.CallToolRequestParams(name="secret_admin", arguments={}), + ) + + # The internal handler wraps our _call_tool; invoke via the registered handler + handler = server.request_handlers[types.CallToolRequest] + result = await handler(call_tool_request) + + # The call must fail (isError=True) with the correct error message + assert result.root.isError is True, "Calling an excluded function should return an error" + assert any("Unknown tool" in c.text for c in result.root.content if hasattr(c, "text")), ( + f"Expected 'Unknown tool' error, got: {result.root.content}" + ) + assert not side_effect_called, "Excluded function's side effect should not have fired" From 38a5480af04d339b9c07090653737342c0a420a6 Mon Sep 17 00:00:00 2001 From: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> Date: Tue, 30 Jun 2026 22:10:27 +0100 Subject: [PATCH 28/33] Python: Default MCP SSE server samples to loopback with host validation (#14127) ## Motivation and Context The Python MCP server demos under `python/samples/demos/mcp_server/` can optionally run over the SSE transport (`--transport sse`). This updates that sample wiring to follow the Model Context Protocol guidance for local development servers, so developers who use these demos as a starting point inherit sensible defaults. ## Description - **Loopback by default**: the SSE samples now bind to `127.0.0.1` instead of `0.0.0.0`. A new `--host` argument makes binding to other interfaces an explicit opt-in that logs a warning. - **Host/Origin validation**: added Starlette `TrustedHostMiddleware` plus a small Origin allowlist middleware so the local listener only serves loopback callers (requests without an `Origin` header are still allowed, for non-browser MCP clients). - **Sample hygiene**: switched `Starlette(debug=True)` to `debug=False` so the demos don't ship verbose debug output. - **Docs**: the README now describes the loopback-by-default behavior, the `--host` opt-in, and points to the existing `mcp_with_oauth` sample for authenticated, network-reachable deployments. Applies to `sk_mcp_server.py` and `agent_as_server.py`. The stdio transport (the default) and the other stdio-only samples are unchanged. ## Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] I didn't break anyone :smile: --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- python/samples/demos/mcp_server/README.md | 14 +++ .../demos/mcp_server/agent_as_server.py | 93 ++++++++++++++++++- .../samples/demos/mcp_server/sk_mcp_server.py | 92 +++++++++++++++++- 3 files changed, 189 insertions(+), 10 deletions(-) diff --git a/python/samples/demos/mcp_server/README.md b/python/samples/demos/mcp_server/README.md index 1eafdff3b4f9..1aef1595c1d2 100644 --- a/python/samples/demos/mcp_server/README.md +++ b/python/samples/demos/mcp_server/README.md @@ -61,6 +61,20 @@ uv --directory=/semantic-kernel/python/samples/demos/mcp_ser This will start a server that listens for incoming requests on port `8000`. +> [!NOTE] +> By default the SSE server binds to `127.0.0.1` (loopback) and only accepts requests +> with a loopback `Host` header and, when present, a loopback `Origin` header. A local +> MCP server exposes tools, plugins and model providers backed by your own credentials, +> so it is good practice to keep it reachable only from your own machine. The +> [MCP specification](https://modelcontextprotocol.io/) recommends validating `Origin` +> and binding to loopback, in part to guard against [DNS rebinding](https://en.wikipedia.org/wiki/DNS_rebinding). +> +> You can override the bind address with `--host`, e.g. `--host 0.0.0.0` to expose the +> server on the network. Do this only on a trusted network. The bundled Host/Origin +> checks only allow loopback callers, so a non-loopback deployment needs proper +> authentication - see the [`mcp_with_oauth`](../mcp_with_oauth/) sample for the +> authenticated, Streamable-HTTP pattern recommended for production. + --- In both cases, `uv` will ensure that `semantic-kernel` is installed with the `mcp` extra in a temporary virtual environment. diff --git a/python/samples/demos/mcp_server/agent_as_server.py b/python/samples/demos/mcp_server/agent_as_server.py index 3cbc012d5652..af9b2e2be6b2 100644 --- a/python/samples/demos/mcp_server/agent_as_server.py +++ b/python/samples/demos/mcp_server/agent_as_server.py @@ -5,6 +5,7 @@ # /// # Copyright (c) Microsoft. All rights reserved. import argparse +import ipaddress import logging from typing import Annotated, Any, Literal @@ -51,6 +52,16 @@ """ +def is_loopback_host(host: str) -> bool: + """Return True if the host refers to a loopback interface (incl. IPv6 ::1).""" + if host == "localhost": + return True + try: + return ipaddress.ip_address(host).is_loopback + except ValueError: + return False + + def parse_arguments(): parser = argparse.ArgumentParser(description="Run the Semantic Kernel MCP server.") parser.add_argument( @@ -66,7 +77,20 @@ def parse_arguments(): default=None, help="Port to use for SSE transport (required if transport is 'sse').", ) - return parser.parse_args() + parser.add_argument( + "--host", + type=str, + default="127.0.0.1", + help=( + "Host/interface to bind the SSE server to (default: 127.0.0.1). " + "Binding to anything other than loopback (e.g. 0.0.0.0) exposes the server " + "to the network and should only be done on a trusted network with authentication added." + ), + ) + args = parser.parse_args() + if args.transport == "sse" and args.port is None: + parser.error("--port is required when --transport is 'sse'.") + return args # Define a simple plugin for the sample @@ -88,7 +112,7 @@ def get_item_price( return "$9.99" -async def run(transport: Literal["sse", "stdio"] = "stdio", port: int | None = None) -> None: +async def run(transport: Literal["sse", "stdio"] = "stdio", port: int | None = None, host: str = "127.0.0.1") -> None: async with ( # 1. Login to Azure and create a Azure AI Project Client AzureCliCredential() as creds, @@ -110,7 +134,53 @@ async def run(transport: Literal["sse", "stdio"] = "stdio", port: int | None = N import uvicorn from mcp.server.sse import SseServerTransport from starlette.applications import Starlette + from starlette.middleware import Middleware + from starlette.middleware.trustedhost import TrustedHostMiddleware + from starlette.responses import PlainTextResponse from starlette.routing import Mount, Route + from starlette.types import ASGIApp, Receive, Scope, Send + + # A local MCP server is a security boundary, not a generic web server: it exposes + # tools, plugins and model providers backed by the developer's credentials. Without + # Host/Origin validation a malicious web page could use DNS rebinding to reach this + # loopback listener from the victim's browser and invoke the exposed MCP tools. + # The MCP spec therefore requires servers to validate Origin and bind to loopback. + allowed_hosts = [ + "localhost", + "127.0.0.1", + "[::1]", + f"localhost:{port}", + f"127.0.0.1:{port}", + f"[::1]:{port}", + ] + allowed_origins = { + "http://localhost", + "http://127.0.0.1", + "http://[::1]", + f"http://localhost:{port}", + f"http://127.0.0.1:{port}", + f"http://[::1]:{port}", + } + + class OriginValidationMiddleware: + """Reject requests with an untrusted Origin header (DNS-rebinding defense).""" + + def __init__(self, app: ASGIApp) -> None: + self.app = app + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] == "http": + origin = dict(scope["headers"]).get(b"origin") + if origin is not None: + try: + origin_value = origin.decode("ascii") + except UnicodeDecodeError: + origin_value = None + if origin_value not in allowed_origins: + response = PlainTextResponse("Forbidden: invalid Origin header", status_code=403) + await response(scope, receive, send) + return + await self.app(scope, receive, send) sse = SseServerTransport("/messages/") @@ -122,14 +192,27 @@ async def handle_sse(request): await server.run(read_stream, write_stream, server.create_initialization_options()) starlette_app = Starlette( - debug=True, + debug=False, routes=[ Route("/sse", endpoint=handle_sse), Mount("/messages/", app=sse.handle_post_message), ], + middleware=[ + Middleware(TrustedHostMiddleware, allowed_hosts=allowed_hosts), + Middleware(OriginValidationMiddleware), + ], ) + + if not is_loopback_host(host): + logger.warning( + "Binding the MCP SSE server to %s exposes it beyond loopback. The bundled Host/Origin " + "checks only allow loopback callers; for a network-reachable or credentialed deployment " + "add proper authentication (see the mcp_with_oauth sample) before doing this.", + host, + ) + nest_asyncio.apply() - uvicorn.run(starlette_app, host="0.0.0.0", port=port) # nosec + uvicorn.run(starlette_app, host=host, port=port) # nosec elif transport == "stdio": from mcp.server.stdio import stdio_server @@ -142,4 +225,4 @@ async def handle_stdin(stdin: Any | None = None, stdout: Any | None = None) -> N if __name__ == "__main__": args = parse_arguments() - anyio.run(run, args.transport, args.port) + anyio.run(run, args.transport, args.port, args.host) diff --git a/python/samples/demos/mcp_server/sk_mcp_server.py b/python/samples/demos/mcp_server/sk_mcp_server.py index 6b7b617d19df..bade18f4f301 100644 --- a/python/samples/demos/mcp_server/sk_mcp_server.py +++ b/python/samples/demos/mcp_server/sk_mcp_server.py @@ -5,6 +5,7 @@ # /// # Copyright (c) Microsoft. All rights reserved. import argparse +import ipaddress import logging from typing import Any, Literal @@ -54,6 +55,16 @@ """ +def is_loopback_host(host: str) -> bool: + """Return True if the host refers to a loopback interface (incl. IPv6 ::1).""" + if host == "localhost": + return True + try: + return ipaddress.ip_address(host).is_loopback + except ValueError: + return False + + def parse_arguments(): parser = argparse.ArgumentParser(description="Run the Semantic Kernel MCP server.") parser.add_argument( @@ -69,10 +80,23 @@ def parse_arguments(): default=None, help="Port to use for SSE transport (required if transport is 'sse').", ) - return parser.parse_args() + parser.add_argument( + "--host", + type=str, + default="127.0.0.1", + help=( + "Host/interface to bind the SSE server to (default: 127.0.0.1). " + "Binding to anything other than loopback (e.g. 0.0.0.0) exposes the server " + "to the network and should only be done on a trusted network with authentication added." + ), + ) + args = parser.parse_args() + if args.transport == "sse" and args.port is None: + parser.error("--port is required when --transport is 'sse'.") + return args -def run(transport: Literal["sse", "stdio"] = "stdio", port: int | None = None) -> None: +def run(transport: Literal["sse", "stdio"] = "stdio", port: int | None = None, host: str = "127.0.0.1") -> None: kernel = Kernel() @kernel_function() @@ -112,7 +136,53 @@ def echo_function(message: str, extra: str = "") -> str: import uvicorn from mcp.server.sse import SseServerTransport from starlette.applications import Starlette + from starlette.middleware import Middleware + from starlette.middleware.trustedhost import TrustedHostMiddleware + from starlette.responses import PlainTextResponse from starlette.routing import Mount, Route + from starlette.types import ASGIApp, Receive, Scope, Send + + # A local MCP server is a security boundary, not a generic web server: it exposes + # tools, plugins and model providers backed by the developer's credentials. Without + # Host/Origin validation a malicious web page could use DNS rebinding to reach this + # loopback listener from the victim's browser and invoke the exposed MCP tools. + # The MCP spec therefore requires servers to validate Origin and bind to loopback. + allowed_hosts = [ + "localhost", + "127.0.0.1", + "[::1]", + f"localhost:{port}", + f"127.0.0.1:{port}", + f"[::1]:{port}", + ] + allowed_origins = { + "http://localhost", + "http://127.0.0.1", + "http://[::1]", + f"http://localhost:{port}", + f"http://127.0.0.1:{port}", + f"http://[::1]:{port}", + } + + class OriginValidationMiddleware: + """Reject requests with an untrusted Origin header (DNS-rebinding defense).""" + + def __init__(self, app: ASGIApp) -> None: + self.app = app + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] == "http": + origin = dict(scope["headers"]).get(b"origin") + if origin is not None: + try: + origin_value = origin.decode("ascii") + except UnicodeDecodeError: + origin_value = None + if origin_value not in allowed_origins: + response = PlainTextResponse("Forbidden: invalid Origin header", status_code=403) + await response(scope, receive, send) + return + await self.app(scope, receive, send) sse = SseServerTransport("/messages/") @@ -121,14 +191,26 @@ async def handle_sse(request): await server.run(read_stream, write_stream, server.create_initialization_options()) starlette_app = Starlette( - debug=True, + debug=False, routes=[ Route("/sse", endpoint=handle_sse), Mount("/messages/", app=sse.handle_post_message), ], + middleware=[ + Middleware(TrustedHostMiddleware, allowed_hosts=allowed_hosts), + Middleware(OriginValidationMiddleware), + ], ) - uvicorn.run(starlette_app, host="0.0.0.0", port=port) # nosec + if not is_loopback_host(host): + logger.warning( + "Binding the MCP SSE server to %s exposes it beyond loopback. The bundled Host/Origin " + "checks only allow loopback callers; for a network-reachable or credentialed deployment " + "add proper authentication (see the mcp_with_oauth sample) before doing this.", + host, + ) + + uvicorn.run(starlette_app, host=host, port=port) # nosec elif transport == "stdio": import anyio from mcp.server.stdio import stdio_server @@ -142,4 +224,4 @@ async def handle_stdin(stdin: Any | None = None, stdout: Any | None = None) -> N if __name__ == "__main__": args = parse_arguments() - run(transport=args.transport, port=args.port) + run(transport=args.transport, port=args.port, host=args.host) From f25753be0a126138d2eea39b0ca2985252dde25a Mon Sep 17 00:00:00 2001 From: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> Date: Wed, 1 Jul 2026 19:44:43 +0100 Subject: [PATCH 29/33] Bump Scriban from 7.2.0 to 7.2.5 to fix NU1902 vulnerability (#14133) Fixes CI failure caused by NU1902 errors due to known moderate severity vulnerabilities in Scriban 7.2.0 (GHSA-6q7j-xr26-3h2c, GHSA-q6rr-fm2g-g5x8). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 4dcc213ea1f1..29d44c8fc753 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -107,7 +107,7 @@ - + From e6c9673684ca03621885083faff1644e1f42695e Mon Sep 17 00:00:00 2001 From: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> Date: Thu, 2 Jul 2026 17:59:44 +0100 Subject: [PATCH 30/33] .Net: Disable automatic HTTP redirects in HttpPlugin and WebFileDownloadPlugin default clients (#14132) The default HTTP clients used by `HttpPlugin` and `WebFileDownloadPlugin` now have `AllowAutoRedirect` set to `false`. This ensures the `AllowedDomains` restriction is enforced consistently regardless of server responses. - Added `GetNonRedirectingHttpClient()` to `HttpClientProvider` (all target frameworks) - Updated both plugins to use non-redirecting clients by default - Added unit tests verifying redirect responses are not followed - Updated XML documentation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/Http/HttpClientProvider.cs | 28 +++++--- dotnet/src/Plugins/Plugins.Core/HttpPlugin.cs | 7 +- .../Plugins.UnitTests/Core/HttpPluginTests.cs | 47 ++++++++++++++ .../Web/WebFileDownloadPluginTests.cs | 65 +++++++++++++++++++ .../Plugins.Web/WebFileDownloadPlugin.cs | 9 ++- 5 files changed, 146 insertions(+), 10 deletions(-) diff --git a/dotnet/src/InternalUtilities/src/Http/HttpClientProvider.cs b/dotnet/src/InternalUtilities/src/Http/HttpClientProvider.cs index 3a6b5b9fe111..e5f79b3bad21 100644 --- a/dotnet/src/InternalUtilities/src/Http/HttpClientProvider.cs +++ b/dotnet/src/InternalUtilities/src/Http/HttpClientProvider.cs @@ -26,6 +26,12 @@ internal static class HttpClientProvider /// An instance of HttpClient. public static HttpClient GetHttpClient() => new(NonDisposableHttpClientHandler.Instance, disposeHandler: false); + /// + /// Retrieves an instance of HttpClient that does not automatically follow HTTP redirects. + /// + /// An instance of HttpClient that does not follow redirects. + public static HttpClient GetNonRedirectingHttpClient() => new(NonDisposableHttpClientHandler.NonRedirectingInstance, disposeHandler: false); + /// /// Retrieves an instance of HttpClient. /// @@ -52,14 +58,19 @@ private sealed class NonDisposableHttpClientHandler : DelegatingHandler /// /// Private constructor to prevent direct instantiation of the class. /// - private NonDisposableHttpClientHandler() : base(CreateHandler()) + private NonDisposableHttpClientHandler(bool allowRedirect) : base(CreateHandler(allowRedirect)) { } /// - /// Gets the singleton instance of . + /// Gets the singleton instance of that follows HTTP redirects. + /// + public static NonDisposableHttpClientHandler Instance { get; } = new(allowRedirect: true); + + /// + /// Gets the singleton instance of that does not follow HTTP redirects. /// - public static NonDisposableHttpClientHandler Instance { get; } = new(); + public static NonDisposableHttpClientHandler NonRedirectingInstance { get; } = new(allowRedirect: false); /// /// Disposes the underlying resources held by the . @@ -74,7 +85,7 @@ protected override void Dispose(bool disposing) } #if NET - private static SocketsHttpHandler CreateHandler() + private static SocketsHttpHandler CreateHandler(bool allowRedirect) { return new SocketsHttpHandler() { @@ -86,12 +97,13 @@ private static SocketsHttpHandler CreateHandler() { CertificateRevocationCheckMode = X509RevocationMode.Online, }, + AllowAutoRedirect = allowRedirect, }; } #elif NETSTANDARD2_0_OR_GREATER - private static HttpClientHandler CreateHandler() + private static HttpClientHandler CreateHandler(bool allowRedirect) { - var handler = new HttpClientHandler(); + var handler = new HttpClientHandler() { AllowAutoRedirect = allowRedirect }; try { handler.CheckCertificateRevocationList = true; @@ -100,8 +112,8 @@ private static HttpClientHandler CreateHandler() return handler; } #elif NETFRAMEWORK - private static HttpClientHandler CreateHandler() - => new(); + private static HttpClientHandler CreateHandler(bool allowRedirect) + => new() { AllowAutoRedirect = allowRedirect }; #endif } } diff --git a/dotnet/src/Plugins/Plugins.Core/HttpPlugin.cs b/dotnet/src/Plugins/Plugins.Core/HttpPlugin.cs index 89f49d8d4705..ea11b17a258a 100644 --- a/dotnet/src/Plugins/Plugins.Core/HttpPlugin.cs +++ b/dotnet/src/Plugins/Plugins.Core/HttpPlugin.cs @@ -23,6 +23,9 @@ namespace Microsoft.SemanticKernel.Plugins.Core; /// When exposing this plugin to an LLM via auto function calling, ensure that /// is restricted to trusted values only. /// +/// +/// The default HTTP client does not follow redirects to prevent bypassing the allow-list. +/// /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1054:URI-like parameters should not be strings", Justification = "Semantic Kernel operates on strings")] @@ -43,10 +46,11 @@ public HttpPlugin() : this(null) /// The HTTP client to use. /// /// assumes ownership of the instance and will dispose it when the plugin is disposed. + /// When providing a custom client, configure it with AllowAutoRedirect = false to preserve the guarantee. /// [ActivatorUtilitiesConstructor] public HttpPlugin(HttpClient? client = null) => - this._client = client ?? HttpClientProvider.GetHttpClient(); + this._client = client ?? HttpClientProvider.GetNonRedirectingHttpClient(); /// /// List of allowed domains to send requests to. @@ -54,6 +58,7 @@ public HttpPlugin(HttpClient? client = null) => /// /// Defaults to an empty collection (no domains allowed). Must be explicitly populated /// with trusted domains before any requests will succeed. + /// HTTP redirects are not followed to prevent bypassing the allow-list. /// public IEnumerable? AllowedDomains { diff --git a/dotnet/src/Plugins/Plugins.UnitTests/Core/HttpPluginTests.cs b/dotnet/src/Plugins/Plugins.UnitTests/Core/HttpPluginTests.cs index d867e56c0630..f9a63f84264d 100644 --- a/dotnet/src/Plugins/Plugins.UnitTests/Core/HttpPluginTests.cs +++ b/dotnet/src/Plugins/Plugins.UnitTests/Core/HttpPluginTests.cs @@ -133,6 +133,53 @@ public async Task ItThrowsInvalidOperationExceptionForInvalidDomainAsync() await Assert.ThrowsAsync(async () => await plugin.DeleteAsync(invalidUri)); } + [Fact] + public async Task ItDoesNotFollowRedirectsAsync() + { + // Arrange - start a local server that always returns a 302 redirect + using var listener = new System.Net.HttpListener(); + var port = new Random().Next(49152, 65535); + listener.Prefixes.Add($"http://localhost:{port}/"); + listener.Start(); + bool redirectTargetContacted = false; + + _ = Task.Run(async () => + { + while (listener.IsListening) + { + try + { + var ctx = await listener.GetContextAsync(); + if (ctx.Request.Url!.AbsolutePath == "/start") + { + ctx.Response.StatusCode = 302; + ctx.Response.RedirectLocation = $"http://localhost:{port}/secret"; + ctx.Response.Close(); + } + else if (ctx.Request.Url.AbsolutePath == "/secret") + { + redirectTargetContacted = true; + ctx.Response.StatusCode = 200; + ctx.Response.Close(); + } + } + catch (ObjectDisposedException) { break; } + catch (System.Net.HttpListenerException) { break; } + } + }); + + var plugin = new HttpPlugin() + { + AllowedDomains = ["localhost"] + }; + + // Act & Assert - the plugin should throw because 302 is a non-success status + await Assert.ThrowsAsync(() => plugin.GetAsync($"http://localhost:{port}/start")); + Assert.False(redirectTargetContacted, "The redirect target should not have been contacted."); + + listener.Stop(); + } + private Mock CreateMock() { var mockHandler = new Mock(); diff --git a/dotnet/src/Plugins/Plugins.UnitTests/Web/WebFileDownloadPluginTests.cs b/dotnet/src/Plugins/Plugins.UnitTests/Web/WebFileDownloadPluginTests.cs index 6d0ce6f5aeb4..92a15be0c1df 100644 --- a/dotnet/src/Plugins/Plugins.UnitTests/Web/WebFileDownloadPluginTests.cs +++ b/dotnet/src/Plugins/Plugins.UnitTests/Web/WebFileDownloadPluginTests.cs @@ -5,6 +5,7 @@ using System.Net.Http; using System.Runtime.InteropServices; using System.Threading.Tasks; +using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Plugins.Web; using Xunit; @@ -77,6 +78,70 @@ public async Task DownloadToFileFailsForInvalidDomainAsync() await Assert.ThrowsAsync(async () => await webFileDownload.DownloadToFileAsync(uri, filePath)); } + [Fact] + public async Task DownloadToFileDoesNotFollowRedirectsAsync() + { + // Arrange - start a local server that returns a 302 redirect + using var listener = new System.Net.HttpListener(); + var port = new Random().Next(49152, 65535); + listener.Prefixes.Add($"http://localhost:{port}/"); + listener.Start(); + bool redirectTargetContacted = false; + + _ = Task.Run(async () => + { + while (listener.IsListening) + { + try + { + var ctx = await listener.GetContextAsync(); + if (ctx.Request.Url!.AbsolutePath == "/start") + { + ctx.Response.StatusCode = 302; + ctx.Response.RedirectLocation = $"http://localhost:{port}/secret.png"; + ctx.Response.Close(); + } + else if (ctx.Request.Url.AbsolutePath == "/secret.png") + { + redirectTargetContacted = true; + ctx.Response.StatusCode = 200; + ctx.Response.ContentType = "image/png"; + ctx.Response.OutputStream.Write(new byte[] { 0x89, 0x50, 0x4E, 0x47 }); + ctx.Response.Close(); + } + } + catch (ObjectDisposedException) { break; } + catch (System.Net.HttpListenerException) { break; } + } + }); + + var folderPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + var filePath = Path.Combine(folderPath, "file.png"); + Directory.CreateDirectory(folderPath); + + var webFileDownload = new WebFileDownloadPlugin() + { + AllowedDomains = ["localhost"], + AllowedFolders = [folderPath] + }; + + try + { + // Act & Assert - the plugin should throw because 302 is a non-success status + await Assert.ThrowsAsync(() => webFileDownload.DownloadToFileAsync(new Uri($"http://localhost:{port}/start"), filePath)); + Assert.False(redirectTargetContacted, "The redirect target should not have been contacted."); + Assert.False(Path.Exists(filePath)); + } + finally + { + listener.Stop(); + if (Path.Exists(folderPath)) + { + Directory.Delete(folderPath, true); + } + } + } + [Fact] public async Task DownloadToFileDeniesAllWithDefaultConfigAsync() { diff --git a/dotnet/src/Plugins/Plugins.Web/WebFileDownloadPlugin.cs b/dotnet/src/Plugins/Plugins.Web/WebFileDownloadPlugin.cs index d410bb8e22f0..acdcd9659fd6 100644 --- a/dotnet/src/Plugins/Plugins.Web/WebFileDownloadPlugin.cs +++ b/dotnet/src/Plugins/Plugins.Web/WebFileDownloadPlugin.cs @@ -29,6 +29,9 @@ namespace Microsoft.SemanticKernel.Plugins.Web; /// values only. Unrestricted configuration may allow unintended downloads to /// local paths. /// +/// +/// The default HTTP client does not follow redirects to prevent bypassing the allow-list. +/// /// public sealed class WebFileDownloadPlugin { @@ -42,7 +45,7 @@ public sealed class WebFileDownloadPlugin /// /// The to use for logging. If null, no logging will be performed. public WebFileDownloadPlugin(ILoggerFactory? loggerFactory = null) : - this(HttpClientProvider.GetHttpClient(), loggerFactory) + this(HttpClientProvider.GetNonRedirectingHttpClient(), loggerFactory) { } @@ -51,6 +54,9 @@ public WebFileDownloadPlugin(ILoggerFactory? loggerFactory = null) : /// /// The HTTP client to use for making requests. /// The to use for logging. If null, no logging will be performed. + /// + /// When providing a custom client, configure it with AllowAutoRedirect = false to preserve the guarantee. + /// public WebFileDownloadPlugin(HttpClient httpClient, ILoggerFactory? loggerFactory = null) { this._httpClient = httpClient; @@ -63,6 +69,7 @@ public WebFileDownloadPlugin(HttpClient httpClient, ILoggerFactory? loggerFactor /// /// Defaults to an empty collection (no domains allowed). Must be explicitly populated /// with trusted domains before any downloads will succeed. + /// HTTP redirects are not followed to prevent bypassing the allow-list. /// public IEnumerable? AllowedDomains { From f6391ad8b6b47b6de44e80d54ce9f3ffe4f3ed42 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Mon, 6 Jul 2026 17:43:25 +0100 Subject: [PATCH 31/33] Python: OpenApi: Harden operation path handling for consistent selection and request targeting (.Net & Python) (#14140) ## Motivation and Context The OpenAPI plugin imports operations from a spec and lets the host restrict which operations are exposed via an `OperationSelectionPredicate` (and via `OperationsToExclude`). Operation selection and request-URL construction should share one canonical interpretation of an operation path. This change closes two consistency gaps where a spec-supplied path could be interpreted differently at selection time than at request time. 1. **Selection vs. request path normalization.** The selection predicate received the raw operation path, while the request URL is built from a canonicalized path. An encoded dot-segment (for example `%2e%2e`) is textually different from the endpoint it canonicalizes to, so it could pass a path-based include/exclude filter yet resolve to a different route. Operations whose path contains an encoded or literal dot-segment are now excluded before the predicate is consulted, symmetric with the existing request-time dot-segment rejection. 2. **Request target reconciliation (defense in depth).** After the request URL is built, verify it did not move off the configured server. An operation path that is an absolute or authority-changing URI (for example `https://another-host/admin`) carries no dot-segment, so it passes path-segment validation, yet `System.Uri` / `urljoin` resolve it to a different scheme, host, or port. Such a request is now rejected before it is sent, so a credential-bearing request cannot be redirected to an unintended target. Both changes are applied symmetrically to the .NET and Python OpenAPI ports. ## Description - **.NET** - `OpenApiDocumentParser` skips operations whose path contains a dot-segment before invoking the selection predicate. - `RestApiOperation` extracts a shared `ContainsDotSegment` helper (reused by the existing `ValidatePathSegments`) and, after building the request URL, reconciles its scheme/host/port and base path against the configured server. - **Python** - `openapi_parser` skips dot-segment operations before the predicate runs. - `rest_api_operation` adds a shared `_contains_dot_segment` helper and a post-construction `_ensure_request_target_matches_server` reconciliation. ## Tests - .NET: added selection-exclusion and request-target reconciliation tests; full `Functions.UnitTests` OpenApi suite green (488). - Python: added parity tests for both behaviors; `tests/unit/connectors/openapi_plugin` green (173), ruff + ruff-format + mypy + pre-commit clean. ## Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the SK Contribution Guidelines - [x] All unit tests pass, and I have added new tests where possible --- .../Model/RestApiOperation.cs | 62 ++++++++- .../OpenApi/OpenApiDocumentParser.cs | 12 ++ .../OpenApi/OpenApiDocumentParserV20Tests.cs | 103 +++++++++++++++ .../OpenApi/RestApiOperationTests.cs | 80 +++++++++++ .../models/rest_api_operation.py | 73 +++++++++- .../openapi_plugin/openapi_parser.py | 12 ++ .../openapi_plugin/test_sk_openapi.py | 125 ++++++++++++++++++ 7 files changed, 461 insertions(+), 6 deletions(-) diff --git a/dotnet/src/Functions/Functions.OpenApi/Model/RestApiOperation.cs b/dotnet/src/Functions/Functions.OpenApi/Model/RestApiOperation.cs index 4f4cd2a48948..fc34fe8ea346 100644 --- a/dotnet/src/Functions/Functions.OpenApi/Model/RestApiOperation.cs +++ b/dotnet/src/Functions/Functions.OpenApi/Model/RestApiOperation.cs @@ -168,7 +168,42 @@ internal Uri BuildOperationUrl(IDictionary arguments, Uri? serv var path = this.BuildPath(this.Path, arguments); - return new Uri(serverUrl, $"{path.TrimStart('/')}"); + var url = new Uri(serverUrl, $"{path.TrimStart('/')}"); + + EnsureRequestTargetMatchesServer(serverUrl, url); + + return url; + } + + /// + /// Verifies that URI construction did not move the request off the configured server. A selected + /// operation path must resolve to a request on the same scheme, host, and port and within the + /// server's base path. Otherwise an absolute or authority-changing operation path (for example + /// "https://another-host/admin") could redirect a credential-bearing request to an unintended + /// target even though it carries no dot-segment. This complements + /// so operation selection, path validation, and request construction share one canonical target. + /// + /// The configured server URL. + /// The request URL produced by combining the server URL and operation path. + private static void EnsureRequestTargetMatchesServer(Uri serverUrl, Uri requestUrl) + { + var serverAuthority = serverUrl.GetLeftPart(UriPartial.Authority); + var requestAuthority = requestUrl.GetLeftPart(UriPartial.Authority); + + if (!string.Equals(serverAuthority, requestAuthority, StringComparison.OrdinalIgnoreCase)) + { + throw new KernelException($"The operation path resolves to '{requestAuthority}', which does not match the configured server '{serverAuthority}'."); + } + + // GetServerUrl guarantees a trailing slash, so the server's base path always ends with '/'. + var basePath = serverUrl.AbsolutePath; + var requestPath = requestUrl.AbsolutePath; + + if (!string.Equals(requestPath, basePath.TrimEnd('/'), StringComparison.Ordinal) && + !requestPath.StartsWith(basePath, StringComparison.Ordinal)) + { + throw new KernelException($"The operation path resolves to '{requestPath}', which is outside the configured server base path '{basePath}'."); + } } /// @@ -420,6 +455,27 @@ value is string { } strValue && /// The path to validate. private static void ValidatePathSegments(string path) { + if (ContainsDotSegment(path)) + { + throw new KernelException($"Path '{path}' contains a dot-segment, which could lead to path traversal."); + } + } + + /// + /// Determines whether the supplied path contains a dot-segment (. or ..), including percent-encoded + /// forms (e.g. "%2e%2e") that canonicalizes at request time. This is used both to + /// reject such paths when building a request URL and to exclude them during operation selection so an + /// encoded dot-segment cannot bypass an include/exclude operation-selection filter. + /// + /// The path to inspect. + /// if the path contains a dot-segment; otherwise, . + internal static bool ContainsDotSegment(string path) + { + if (string.IsNullOrEmpty(path)) + { + return false; + } + // Split on the structural path separator first. foreach (var rawSegment in path.Split('/')) { @@ -443,10 +499,12 @@ private static void ValidatePathSegments(string path) { if (segment == "." || segment == "..") { - throw new KernelException($"Path '{path}' contains a dot-segment, which could lead to path traversal."); + return true; } } } + + return false; } private IDictionary _extensions = s_emptyDictionary; diff --git a/dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs b/dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs index 2db2bf8ae18e..27cf837b0dbc 100644 --- a/dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs +++ b/dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs @@ -197,6 +197,18 @@ internal static List CreateRestApiOperations(OpenApiDocument d var operationItem = operationPair.Value; var operationServers = CreateRestApiOperationServers(operationItem.Servers); + // Exclude operations whose path contains an encoded or literal dot-segment before the + // selection predicate is consulted. Such a path is canonicalized into a different + // effective endpoint at request time, so offering it to an include/exclude predicate + // would let an encoded dot-segment bypass the operation-selection filter. Absolute or + // authority-changing path keys are already rejected by the OpenAPI reader, so a + // dot-segment check is sufficient here. + if (RestApiOperation.ContainsDotSegment(path)) + { + logger.LogWarning("Operation '{OperationId}' at path '{Path}' contains a dot-segment and will be skipped during operation selection.", operationItem.OperationId, path); + continue; + } + // Skip the operation parsing and don't add it to the result operations list if it's explicitly excluded by the predicate. if (!options?.OperationSelectionPredicate?.Invoke(new OperationSelectionPredicateContext(operationItem.OperationId, path, method, operationItem.Description)) ?? false) { diff --git a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV20Tests.cs b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV20Tests.cs index 40934fa4ff73..fe91d91e3365 100644 --- a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV20Tests.cs +++ b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV20Tests.cs @@ -438,6 +438,109 @@ public async Task ItCanFilterOutSpecifiedOperationsAsync() Assert.Contains(restApiSpec.Operations, o => o.Id == "GetSecret"); } + [Fact] + public async Task ItShouldNotOfferEncodedDotSegmentOperationsToSelectionPredicateAsync() + { + // Arrange - one regular operation and one whose path contains an encoded dot-segment + // ("%2e%2e") that canonicalizes to a path-traversal at request time. The selection + // predicate must compare a normalized value, so the encoded path cannot bypass an + // allow/deny operation-selection filter. + var document = + """ + { + "swagger": "2.0", + "info": { + "title": "Test API", + "version": "1.0.0" + }, + "paths": { + "/items": { + "get": { + "operationId": "GetItems", + "summary": "Get items", + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/resources/%2e%2e/admin": { + "get": { + "operationId": "GetAdmin", + "summary": "Get admin", + "responses": { + "200": { + "description": "Successful response" + } + } + } + } + } + } + """; + + var observedPaths = new List(); + var options = new OpenApiDocumentParserOptions + { + OperationSelectionPredicate = (context) => + { + observedPaths.Add(context.Path); + return true; + } + }; + + await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + + // Act + var restApiSpec = await this._sut.ParseAsync(stream, options); + + // Assert - the regular operation is offered to the predicate and imported. + Assert.Contains("/items", observedPaths); + Assert.Contains(restApiSpec.Operations, o => o.Path == "/items"); + + // The encoded dot-segment operation is excluded before the predicate is consulted, + // so it cannot slip past an include/exclude operation-selection filter. + Assert.DoesNotContain("/resources/%2e%2e/admin", observedPaths); + Assert.DoesNotContain(restApiSpec.Operations, o => o.Path == "/resources/%2e%2e/admin"); + } + + [Fact] + public async Task ItShouldRejectDocumentWithNonRelativeOperationPathAsync() + { + // Arrange - an absolute / authority-changing operation path key would resolve to a request off + // the configured server. The OpenAPI reader rejects such a non-relative path key so it can + // never reach operation selection or request construction. + var document = + """ + { + "swagger": "2.0", + "info": { + "title": "Test API", + "version": "1.0.0" + }, + "paths": { + "https://evil.com/admin": { + "get": { + "operationId": "GetAdmin", + "summary": "Get admin", + "responses": { + "200": { + "description": "Successful response" + } + } + } + } + } + } + """; + + await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + + // Act & Assert - a non-relative operation path key is rejected during parsing. + await Assert.ThrowsAsync(() => this._sut.ParseAsync(stream)); + } + [Fact] public async Task ItCanParsePathItemPathParametersAsync() { diff --git a/dotnet/src/Functions/Functions.UnitTests/OpenApi/RestApiOperationTests.cs b/dotnet/src/Functions/Functions.UnitTests/OpenApi/RestApiOperationTests.cs index 6273c80d494e..6342ee30c7ed 100644 --- a/dotnet/src/Functions/Functions.UnitTests/OpenApi/RestApiOperationTests.cs +++ b/dotnet/src/Functions/Functions.UnitTests/OpenApi/RestApiOperationTests.cs @@ -1553,6 +1553,86 @@ public void ItShouldAllowEncodedNonDotSegmentCharactersInPathTemplate() Assert.Equal("https://example.com/api/resources/a%20b/details", url.OriginalString); } + [Theory] + [InlineData("https://evil.com/admin")] + [InlineData("https://example.com:8443/admin")] + [InlineData("http://example.com/admin")] + [InlineData(@"\\evil.com\admin")] + [InlineData("https://user:pass@example.com/api/admin")] + [InlineData("https://user@example.com/api/data")] + [InlineData("https://example.com@evil.com/admin")] + public void ItShouldRejectOperationPathThatChangesRequestAuthority(string path) + { + // Arrange — an operation path that is an absolute URI (or otherwise changes the scheme, + // host, or port) resolves to a request off the configured server after URI construction. + // Such a path must be rejected so a credential-bearing request cannot be redirected to an + // unintended target even though it carries no dot-segment. + var sut = new RestApiOperation( + id: "fake_id", + servers: [new RestApiServer("https://example.com/api")], + path: path, + method: HttpMethod.Get, + description: "fake_description", + parameters: [], + responses: new Dictionary(), + securityRequirements: [] + ); + + var arguments = new Dictionary(); + + // Act & Assert — the resolved request target must stay on the configured server. + var ex = Assert.Throws(() => sut.BuildOperationUrl(arguments)); + Assert.Contains("does not match the configured server", ex.Message); + } + + [Fact] + public void ItShouldRejectSameAuthorityBasePathEscape() + { + // Arrange — an absolute path on the same authority but outside the configured base path must + // be rejected, so a request cannot be moved to a different route even when the scheme, host, + // and port all match the configured server. + var sut = new RestApiOperation( + id: "fake_id", + servers: [new RestApiServer("https://example.com/api")], + path: "https://example.com/other/admin", + method: HttpMethod.Get, + description: "fake_description", + parameters: [], + responses: new Dictionary(), + securityRequirements: [] + ); + + var arguments = new Dictionary(); + + // Act & Assert — the resolved request path must remain within the configured server base path. + var ex = Assert.Throws(() => sut.BuildOperationUrl(arguments)); + Assert.Contains("outside the configured server base path", ex.Message); + } + + [Fact] + public void ItShouldBuildUrlForOperationPathOnTheConfiguredServer() + { + // Arrange — a normal relative operation path on the configured server. + var sut = new RestApiOperation( + id: "fake_id", + servers: [new RestApiServer("https://example.com/api")], + path: "/resources/item", + method: HttpMethod.Get, + description: "fake_description", + parameters: [], + responses: new Dictionary(), + securityRequirements: [] + ); + + var arguments = new Dictionary(); + + // Act + var url = sut.BuildOperationUrl(arguments); + + // Assert — the reconciliation must not reject a legitimate same-server path. + Assert.Equal("https://example.com/api/resources/item", url.OriginalString); + } + [Fact] public void ItShouldEncodeServerVariableValuesLookedUpByArgumentName() { diff --git a/python/semantic_kernel/connectors/openapi_plugin/models/rest_api_operation.py b/python/semantic_kernel/connectors/openapi_plugin/models/rest_api_operation.py index 94480a81ae43..4905a7c2102f 100644 --- a/python/semantic_kernel/connectors/openapi_plugin/models/rest_api_operation.py +++ b/python/semantic_kernel/connectors/openapi_plugin/models/rest_api_operation.py @@ -224,9 +224,45 @@ def build_operation_url(self, arguments, server_url_override=None, api_host_url= server_url = self.get_server_url(server_url_override, api_host_url, arguments) path = self.build_path(self.path, arguments) try: - return urljoin(server_url, path.lstrip("/")) + request_url = urljoin(server_url, path.lstrip("/")) except Exception as e: raise FunctionExecutionException(f"Error building the URL for the operation {self.id}: {e!s}") from e + self._ensure_request_target_matches_server(server_url, request_url) + return request_url + + @staticmethod + def _ensure_request_target_matches_server(server_url: str, request_url: str) -> None: + """Verify URL construction did not move the request off the configured server. + + A selected operation path must resolve to a request on the same scheme, host, and port and + within the server's base path. Otherwise an absolute or authority-changing operation path + (for example "https://another-host/admin") could redirect a credential-bearing request to an + unintended target even though it carries no dot-segment. This complements + `_validate_path_segments` so operation selection, path validation, and request construction + share one canonical target. + """ + server = urlparse(server_url) + request = urlparse(request_url) + + if (request.scheme, request.username, request.password, request.hostname, request.port) != ( + server.scheme, + server.username, + server.password, + server.hostname, + server.port, + ): + raise FunctionExecutionException( + f"The operation path resolves to '{request.scheme}://{request.netloc}', which does not match " + f"the configured server '{server.scheme}://{server.netloc}'." + ) + + # get_server_url guarantees a trailing slash, so the server base path always ends with "/". + base_path = server.path + if request.path != base_path.rstrip("/") and not request.path.startswith(base_path): + raise FunctionExecutionException( + f"The operation path resolves to '{request.path}', which is outside the configured server " + f"base path '{base_path}'." + ) def get_server_url(self, server_url_override=None, api_host_url=None, arguments=None): """Get the server URL for the operation.""" @@ -299,6 +335,20 @@ def _validate_path_segments(path: str) -> None: The operation is selected using the raw path but the request URL is built from a canonicalized path, so encoded dot-segments such as "%2e%2e" must be rejected before the URL is constructed. """ + if RestApiOperation._contains_dot_segment(path): + raise FunctionExecutionException( + f"Path '{path}' contains a dot-segment, which could lead to path traversal." + ) + + @staticmethod + def _contains_dot_segment(path: str) -> bool: + """Return True if the path contains a dot-segment (. or ..), including percent-encoded forms. + + Used both to reject such paths when building a request URL and to exclude them during operation + selection so an encoded dot-segment cannot bypass an include/exclude operation-selection filter. + """ + if not path: + return False for segment in path.split("/"): decoded = segment for _ in range(5): @@ -310,9 +360,24 @@ def _validate_path_segments(path: str) -> None: # both "/" and "\" and reject any resulting dot-segment. for part in decoded.replace("\\", "/").split("/"): if part in (".", ".."): - raise FunctionExecutionException( - f"Path '{path}' contains a dot-segment, which could lead to path traversal." - ) + return True + return False + + @staticmethod + def _is_non_relative_path(path: str) -> bool: + """Return True if the path is non-relative (absolute or authority-changing). + + A conformant OpenAPI operation path is relative to the server URL. An absolute URI, a + protocol-relative reference ("//host"), or a backslash-authority reference changes the request + target once combined with the server URL, so such a path is excluded during operation selection + to keep selection and request construction on one canonical target. + """ + if not path: + return False + if path.startswith(("//", "\\\\", "/\\", "\\/")): + return True + parsed = urlparse(path) + return bool(parsed.scheme or parsed.netloc) def build_query_string(self, arguments: dict[str, Any]) -> str: """Build the query string for the operation.""" diff --git a/python/semantic_kernel/connectors/openapi_plugin/openapi_parser.py b/python/semantic_kernel/connectors/openapi_plugin/openapi_parser.py index 1f6aabe5eeff..34bea1bff2dd 100644 --- a/python/semantic_kernel/connectors/openapi_plugin/openapi_parser.py +++ b/python/semantic_kernel/connectors/openapi_plugin/openapi_parser.py @@ -265,6 +265,18 @@ def create_rest_api_operations( summary = details.get("summary", None) description = details.get("description", None) + # Exclude operations whose path would resolve to a different effective request target + # than the one offered to the selection predicate: a dot-segment (encoded or literal) + # or a non-relative (absolute / authority-changing) path. Excluding them here keeps + # operation selection and request construction on one canonical target so such a path + # cannot bypass an include/exclude operation-selection filter. + if RestApiOperation._contains_dot_segment(path) or RestApiOperation._is_non_relative_path(path): + logger.warning( + f"Skipping operation {operationId} at path '{path}' because it does not resolve to a " + f"relative path on the configured server." + ) + continue + context = OperationSelectionPredicateContext(operationId, path, method, description) if ( execution_settings diff --git a/python/tests/unit/connectors/openapi_plugin/test_sk_openapi.py b/python/tests/unit/connectors/openapi_plugin/test_sk_openapi.py index 1b44733562c9..20379131451d 100644 --- a/python/tests/unit/connectors/openapi_plugin/test_sk_openapi.py +++ b/python/tests/unit/connectors/openapi_plugin/test_sk_openapi.py @@ -524,6 +524,44 @@ def test_build_path_allows_encoded_non_dot_segment_characters(): assert operation.build_path(operation.path, {}) == "/resources/a%20b/details" +@pytest.mark.parametrize( + "path", + [ + "https://evil.com/admin", + "https://example.com:8443/admin", + "http://example.com/admin", + "https://user:pass@example.com/api/admin", + "https://user@example.com/api/data", + "https://example.com@evil.com/admin", + ], +) +def test_build_operation_url_rejects_authority_changing_path(path): + # An operation path that is an absolute URI (changing scheme, host, or port) resolves to a + # request off the configured server after URL construction, so a credential-bearing request + # could be redirected to an unintended target even though it carries no dot-segment. + operation = RestApiOperation(id="test", method="GET", servers=["https://example.com/api"], path=path, params=[]) + with pytest.raises(FunctionExecutionException, match="does not match the configured server"): + operation.build_operation_url({}) + + +def test_build_operation_url_allows_same_server_path(): + # A normal relative operation path on the configured server must not be rejected. + operation = RestApiOperation( + id="test", method="GET", servers=["https://example.com/api"], path="/resources/item", params=[] + ) + assert operation.build_operation_url({}) == "https://example.com/api/resources/item" + + +def test_build_operation_url_rejects_same_authority_base_path_escape(): + # An absolute path on the same authority but outside the configured base path must be rejected, + # so a request cannot be moved to a different route even when scheme, host, and port all match. + operation = RestApiOperation( + id="test", method="GET", servers=["https://example.com/api"], path="https://example.com/other/admin", params=[] + ) + with pytest.raises(FunctionExecutionException, match="outside the configured server base path"): + operation.build_operation_url({}) + + def test_build_query_string_with_required_parameter(): parameters = [ RestApiParameter(name="query", type="string", location=RestApiParameterLocation.QUERY, is_required=True) @@ -898,6 +936,93 @@ def test_predicate_callback_applied(openapi_runner_with_predicate_callback): ) +def test_encoded_dot_segment_operations_excluded_from_selection(): + # A regular operation and one whose path contains an encoded dot-segment ("%2e%2e") that + # canonicalizes to a path-traversal at request time. The encoded path must be excluded before + # the selection predicate is consulted so it cannot bypass an include/exclude filter. + parsed_document = { + "servers": [{"url": "https://example.com"}], + "paths": { + "/items": { + "get": { + "operationId": "getItems", + "summary": "Get items", + "responses": {"200": {"description": "OK"}}, + } + }, + "/resources/%2e%2e/admin": { + "get": { + "operationId": "getAdmin", + "summary": "Get admin", + "responses": {"200": {"description": "OK"}}, + } + }, + }, + } + + observed_paths: list[str] = [] + + def predicate_callback(context): + observed_paths.append(context.path) + return True + + parser = OpenApiParser() + exec_settings = OpenAPIFunctionExecutionParameters(operation_selection_predicate=predicate_callback) + operations = parser.create_rest_api_operations(parsed_document, execution_settings=exec_settings) + + # The regular operation is offered to the predicate and imported. + assert "/items" in observed_paths + assert "getItems" in operations + + # The encoded dot-segment operation is excluded before the predicate is consulted, + # so it cannot slip past an include/exclude operation-selection filter. + assert "/resources/%2e%2e/admin" not in observed_paths + assert "getAdmin" not in operations + + +def test_non_relative_path_operations_excluded_from_selection(): + # An operation whose path is an absolute / authority-changing URI resolves to a request off the + # configured server, so it must be excluded before the selection predicate is consulted rather + # than offered to a path-based filter and only rejected later at request construction. + parsed_document = { + "servers": [{"url": "https://example.com"}], + "paths": { + "/items": { + "get": { + "operationId": "getItems", + "summary": "Get items", + "responses": {"200": {"description": "OK"}}, + } + }, + "https://evil.com/admin": { + "get": { + "operationId": "getAdmin", + "summary": "Get admin", + "responses": {"200": {"description": "OK"}}, + } + }, + }, + } + + observed_paths: list[str] = [] + + def predicate_callback(context): + observed_paths.append(context.path) + return True + + parser = OpenApiParser() + exec_settings = OpenAPIFunctionExecutionParameters(operation_selection_predicate=predicate_callback) + operations = parser.create_rest_api_operations(parsed_document, execution_settings=exec_settings) + + # The regular operation is offered to the predicate and imported. + assert "/items" in observed_paths + assert "getItems" in operations + + # The absolute operation path is excluded before the predicate is consulted. + assert "https://evil.com/admin" not in observed_paths + assert "getAdmin" not in operations + + @patch("aiohttp.ClientSession.request") async def test_run_operation_with_invalid_request(mock_request, openapi_runner): runner, operations = openapi_runner From 3df33f7862dabb4d9107b1ead6a899c514df4e68 Mon Sep 17 00:00:00 2001 From: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> Date: Tue, 7 Jul 2026 04:22:20 +0100 Subject: [PATCH 32/33] Python: [Breaking] Update runtime handling (#14135) This PR updates Python runtime handling and related tests. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com> --- .../concepts/mcp/agent_with_mcp_sampling.py | 1 + .../ai/open_ai/services/_open_ai_realtime.py | 26 +++++++- python/semantic_kernel/connectors/mcp.py | 59 +++++++++++++++---- .../functions/kernel_function_extension.py | 19 ++++-- .../open_ai/services/test_openai_realtime.py | 32 ++++++++++ python/tests/unit/connectors/mcp/test_mcp.py | 25 +++++++- python/tests/unit/kernel/test_kernel.py | 31 ++++++++++ 7 files changed, 171 insertions(+), 22 deletions(-) diff --git a/python/samples/concepts/mcp/agent_with_mcp_sampling.py b/python/samples/concepts/mcp/agent_with_mcp_sampling.py index 9dc5aa65bb94..5bcc92536e5e 100644 --- a/python/samples/concepts/mcp/agent_with_mcp_sampling.py +++ b/python/samples/concepts/mcp/agent_with_mcp_sampling.py @@ -52,6 +52,7 @@ async def main(): "run", "mcp_server_with_sampling.py", ], + sampling_auto_approve=True, ) as plugin: agent = ChatCompletionAgent( service=OpenAIChatCompletion(), diff --git a/python/semantic_kernel/connectors/ai/open_ai/services/_open_ai_realtime.py b/python/semantic_kernel/connectors/ai/open_ai/services/_open_ai_realtime.py index cf1e1e618790..1c377a23899c 100644 --- a/python/semantic_kernel/connectors/ai/open_ai/services/_open_ai_realtime.py +++ b/python/semantic_kernel/connectors/ai/open_ai/services/_open_ai_realtime.py @@ -480,8 +480,29 @@ async def _parse_function_call_arguments_done( ) # Step 4: Invoke the function call - chat_history = ChatHistory() + # Fail closed: only invoke when a function choice behavior is available so the allowlist can be enforced. + # Without it, kernel.invoke_function_call would skip allowlist validation and execute any named function. function_behavior = self._current_settings.function_choice_behavior if self._current_settings else None + if function_behavior is None: + logger.warning( + "Skipping function call '%s-%s' because no function choice behavior is configured; " + "allowlist validation cannot be enforced.", + plugin_name, + function_name, + ) + created_output = FunctionResultContent.from_function_call_content_and_result( + function_call_content=item, + result="Function call was not invoked because function choice behavior is not configured.", + ) + result = RealtimeFunctionResultEvent( + service_type=SendEvents.CONVERSATION_ITEM_CREATE, + function_result=created_output, + ) + await self.send(result) + await self.send(RealtimeEvent(service_type=SendEvents.RESPONSE_CREATE)) + yield result + return + chat_history = ChatHistory() await self._kernel.invoke_function_call(item, chat_history, function_behavior=function_behavior) created_output: FunctionResultContent = chat_history.messages[-1].items[0] # type: ignore # Step 5: Create the function result event @@ -710,8 +731,7 @@ async def receive( if audio_output_callback: self.audio_output_callback = audio_output_callback while True: - event = await self._receive_buffer.get() - yield event + yield await self._receive_buffer.get() async def _send(self, event: RealtimeClientEvent) -> None: if not self.data_channel: diff --git a/python/semantic_kernel/connectors/mcp.py b/python/semantic_kernel/connectors/mcp.py index 9282e56c66af..0dd0935188dc 100644 --- a/python/semantic_kernel/connectors/mcp.py +++ b/python/semantic_kernel/connectors/mcp.py @@ -246,6 +246,7 @@ def __init__( kernel: Kernel | None = None, request_timeout: int | None = None, sampling_consent_callback: SamplingConsentCallback | None = None, + sampling_auto_approve: bool = False, ) -> None: """Initialize the MCP Plugin Base. @@ -259,8 +260,11 @@ def __init__( request_timeout: The default timeout used for all requests. sampling_consent_callback: Optional callback for approving MCP sampling requests. Receives the plugin name and MCP sampling request params. Return - False to deny the request. When omitted, sampling requests are - auto-approved and a warning is logged. + False to deny the request. Takes precedence over sampling_auto_approve. + sampling_auto_approve: Whether to auto-approve MCP sampling requests when no + sampling_consent_callback is configured. Defaults to False, meaning sampling + requests are denied unless a consent callback is provided or this flag is set + to True. Set to True only when connecting to a trusted MCP server. """ self.name = name self.description = description @@ -271,6 +275,7 @@ def __init__( self.kernel = kernel or None self.request_timeout = request_timeout self.sampling_consent_callback = sampling_consent_callback + self.sampling_auto_approve = sampling_auto_approve self._sampling_auto_approved_warning_logged = False self._mcp_reserved_attribute_names: set[str] | None = None self._current_task: asyncio.Task | None = None @@ -383,13 +388,25 @@ async def sampling_callback( If a sampling consent callback is configured, it is called before forwarding the request to the configured chat completion service. Returning False denies the request. If no callback is configured, requests are - auto-approved and a warning is logged. + denied unless sampling_auto_approve is set to True, in which case they are auto-approved and a warning is + logged. """ if self.sampling_consent_callback is None: + if not self.sampling_auto_approve: + logger.warning( + "MCP sampling request for plugin '%s' was denied because no sampling consent callback was " + "configured. Provide a sampling_consent_callback or set sampling_auto_approve=True to allow " + "sampling requests.", + self.name, + ) + return types.ErrorData( + code=types.INTERNAL_ERROR, + message="Sampling denied: no consent callback configured.", + ) if not self._sampling_auto_approved_warning_logged: logger.warning( - "MCP sampling request for plugin '%s' was auto-approved because no sampling consent callback " - "was configured.", + "MCP sampling request for plugin '%s' was auto-approved because sampling_auto_approve is " + "enabled and no sampling consent callback was configured.", self.name, ) self._sampling_auto_approved_warning_logged = True @@ -620,6 +637,7 @@ def __init__( encoding: str | None = None, kernel: Kernel | None = None, sampling_consent_callback: SamplingConsentCallback | None = None, + sampling_auto_approve: bool = False, **kwargs: Any, ) -> None: """Initialize the MCP stdio plugin. @@ -643,8 +661,10 @@ def __init__( kernel: The kernel instance with one or more Chat Completion clients. sampling_consent_callback: Optional callback for approving MCP sampling requests. Receives the plugin name and MCP sampling request params. Return - False to deny the request. When omitted, sampling requests are - auto-approved and a warning is logged. + False to deny the request. Takes precedence over sampling_auto_approve. + sampling_auto_approve: Whether to auto-approve MCP sampling requests when no + sampling_consent_callback is configured. Defaults to False (requests are denied). + Set to True only when connecting to a trusted MCP server. kwargs: Any extra arguments to pass to the stdio client. """ @@ -657,6 +677,7 @@ def __init__( load_prompts=load_prompts, request_timeout=request_timeout, sampling_consent_callback=sampling_consent_callback, + sampling_auto_approve=sampling_auto_approve, ) self.command = command self.args = args or [] @@ -696,6 +717,7 @@ def __init__( sse_read_timeout: float | None = None, kernel: Kernel | None = None, sampling_consent_callback: SamplingConsentCallback | None = None, + sampling_auto_approve: bool = False, **kwargs: Any, ) -> None: """Initialize the MCP sse plugin. @@ -720,8 +742,10 @@ def __init__( kernel: The kernel instance with one or more Chat Completion clients. sampling_consent_callback: Optional callback for approving MCP sampling requests. Receives the plugin name and MCP sampling request params. Return - False to deny the request. When omitted, sampling requests are - auto-approved and a warning is logged. + False to deny the request. Takes precedence over sampling_auto_approve. + sampling_auto_approve: Whether to auto-approve MCP sampling requests when no + sampling_consent_callback is configured. Defaults to False (requests are denied). + Set to True only when connecting to a trusted MCP server. kwargs: Any extra arguments to pass to the sse client. """ @@ -734,6 +758,7 @@ def __init__( load_prompts=load_prompts, request_timeout=request_timeout, sampling_consent_callback=sampling_consent_callback, + sampling_auto_approve=sampling_auto_approve, ) self.url = url self.headers = headers or {} @@ -776,6 +801,7 @@ def __init__( terminate_on_close: bool | None = None, kernel: Kernel | None = None, sampling_consent_callback: SamplingConsentCallback | None = None, + sampling_auto_approve: bool = False, **kwargs: Any, ) -> None: """Initialize the MCP streamable http plugin. @@ -801,8 +827,10 @@ def __init__( kernel: The kernel instance with one or more Chat Completion clients. sampling_consent_callback: Optional callback for approving MCP sampling requests. Receives the plugin name and MCP sampling request params. Return - False to deny the request. When omitted, sampling requests are - auto-approved and a warning is logged. + False to deny the request. Takes precedence over sampling_auto_approve. + sampling_auto_approve: Whether to auto-approve MCP sampling requests when no + sampling_consent_callback is configured. Defaults to False (requests are denied). + Set to True only when connecting to a trusted MCP server. kwargs: Any extra arguments to pass to the sse client. """ super().__init__( @@ -814,6 +842,7 @@ def __init__( load_prompts=load_prompts, request_timeout=request_timeout, sampling_consent_callback=sampling_consent_callback, + sampling_auto_approve=sampling_auto_approve, ) self.url = url self.headers = headers or {} @@ -855,6 +884,7 @@ def __init__( description: str | None = None, kernel: Kernel | None = None, sampling_consent_callback: SamplingConsentCallback | None = None, + sampling_auto_approve: bool = False, **kwargs: Any, ) -> None: """Initialize the MCP websocket plugin. @@ -876,8 +906,10 @@ def __init__( kernel: The kernel instance with one or more Chat Completion clients. sampling_consent_callback: Optional callback for approving MCP sampling requests. Receives the plugin name and MCP sampling request params. Return - False to deny the request. When omitted, sampling requests are - auto-approved and a warning is logged. + False to deny the request. Takes precedence over sampling_auto_approve. + sampling_auto_approve: Whether to auto-approve MCP sampling requests when no + sampling_consent_callback is configured. Defaults to False (requests are denied). + Set to True only when connecting to a trusted MCP server. kwargs: Any extra arguments to pass to the websocket client. """ @@ -890,6 +922,7 @@ def __init__( load_prompts=load_prompts, request_timeout=request_timeout, sampling_consent_callback=sampling_consent_callback, + sampling_auto_approve=sampling_auto_approve, ) self.url = url self._client_kwargs = kwargs diff --git a/python/semantic_kernel/functions/kernel_function_extension.py b/python/semantic_kernel/functions/kernel_function_extension.py index 562e3d132a4c..cacccdf3eb08 100644 --- a/python/semantic_kernel/functions/kernel_function_extension.py +++ b/python/semantic_kernel/functions/kernel_function_extension.py @@ -289,10 +289,21 @@ def get_function(self, plugin_name: str | None, function_name: str) -> "KernelFu """ if plugin_name is None: - for plugin in self.plugins.values(): - if function_name in plugin: - return plugin[function_name] - raise KernelFunctionNotFoundError(f"Function '{function_name}' not found in any plugin.") + matches = [ + (name, plugin[function_name]) for name, plugin in self.plugins.items() if function_name in plugin + ] + if not matches: + raise KernelFunctionNotFoundError(f"Function '{function_name}' not found in any plugin.") + if len(matches) > 1: + logger.warning( + "Function '%s' is ambiguous: it exists in multiple plugins (%s). Resolving to '%s-%s' " + "(first registered). Specify a plugin_name for security-relevant lookups to avoid shadowing.", + function_name, + ", ".join(name for name, _ in matches), + matches[0][0], + function_name, + ) + return matches[0][1] if plugin_name not in self.plugins: raise KernelPluginNotFoundError(f"Plugin '{plugin_name}' not found") if function_name not in self.plugins[plugin_name]: diff --git a/python/tests/unit/connectors/ai/open_ai/services/test_openai_realtime.py b/python/tests/unit/connectors/ai/open_ai/services/test_openai_realtime.py index eb7be349fcb5..d94827989633 100644 --- a/python/tests/unit/connectors/ai/open_ai/services/test_openai_realtime.py +++ b/python/tests/unit/connectors/ai/open_ai/services/test_openai_realtime.py @@ -636,6 +636,38 @@ async def test_parse_function_call_arguments_done_filters_block_unallowed(OpenAI assert "not part of the provided" in str(result_event.function_result.result) +async def test_parse_function_call_arguments_done_no_settings_fails_closed(OpenAIWebsocket, kernel): + """When no settings/function choice behavior is present, the call must not be invoked (fail closed).""" + event = ResponseFunctionCallArgumentsDoneEvent( + call_id="call_id", + arguments='{"x": "result"}', + event_id="event_id", + output_index=0, + item_id="item_id", + name="plugin_name-function_name", + response_id="response_id", + type="response.function_call_arguments.done", + ) + # No current settings -> function_behavior would be None -> allowlist cannot be enforced. + OpenAIWebsocket._current_settings = None + OpenAIWebsocket._call_id_to_function_map["call_id"] = "plugin_name-function_name" + func = kernel_function(name="function_name", description="function_description")(lambda x: x) + kernel.add_function(plugin_name="plugin_name", function_name="function_name", function=func) + OpenAIWebsocket._kernel = kernel + + with ( + patch.object(Kernel, "invoke_function_call") as mock_invoke, + patch.object(OpenAIWebsocket, "_send") as mock_send, + ): + events_received = [evt async for evt in OpenAIWebsocket._parse_function_call_arguments_done(event)] + + # The function is never invoked, but a safe result is still sent back to the service. + mock_invoke.assert_not_awaited() + assert mock_send.await_count == 2 + assert isinstance(events_received[-1], RealtimeFunctionResultEvent) + assert "not invoked" in str(events_received[-1].function_result.result) + + async def test_send_audio(OpenAIWebsocket): audio_event = RealtimeAudioEvent( audio=AudioContent(data=b"audio data", mime_type="audio/wav"), diff --git a/python/tests/unit/connectors/mcp/test_mcp.py b/python/tests/unit/connectors/mcp/test_mcp.py index 2fe5052c6f61..2e2eee7d8403 100644 --- a/python/tests/unit/connectors/mcp/test_mcp.py +++ b/python/tests/unit/connectors/mcp/test_mcp.py @@ -132,7 +132,7 @@ async def test_mcp_sampling_consent_callback_error_denies_request(caplog): assert "MCP sampling consent callback failed" in caplog.text -async def test_mcp_sampling_without_consent_callback_logs_auto_approve_warning(caplog): +async def test_mcp_sampling_without_consent_callback_denies_by_default(caplog): plugin = MCPSsePlugin(name="TestMCPPlugin", url="http://localhost:8080/sse") params = types.CreateMessageRequestParams( messages=[types.SamplingMessage(role="user", content=types.TextContent(type="text", text="hello"))], @@ -144,7 +144,28 @@ async def test_mcp_sampling_without_consent_callback_logs_auto_approve_warning(c result = await plugin.sampling_callback(MagicMock(), params) assert isinstance(result, types.ErrorData) - assert "auto-approved because no sampling consent callback was configured" in caplog.text + assert result.message == "Sampling denied: no consent callback configured." + assert "denied because no sampling consent callback was configured" in caplog.text + + +async def test_mcp_sampling_auto_approve_logs_warning(caplog): + plugin = MCPSsePlugin( + name="TestMCPPlugin", + url="http://localhost:8080/sse", + sampling_auto_approve=True, + ) + params = types.CreateMessageRequestParams( + messages=[types.SamplingMessage(role="user", content=types.TextContent(type="text", text="hello"))], + systemPrompt="server instructions", + maxTokens=100, + ) + + with caplog.at_level(logging.WARNING, logger="semantic_kernel.connectors.mcp"): + result = await plugin.sampling_callback(MagicMock(), params) + + # No kernel configured, so the request is approved but then fails for lack of a chat service. + assert isinstance(result, types.ErrorData) + assert "auto-approved because sampling_auto_approve is enabled" in caplog.text async def test_mcp_tool_and_prompt_names_do_not_shadow_plugin_attributes(): diff --git a/python/tests/unit/kernel/test_kernel.py b/python/tests/unit/kernel/test_kernel.py index ea3413f4842f..729aca5840d8 100644 --- a/python/tests/unit/kernel/test_kernel.py +++ b/python/tests/unit/kernel/test_kernel.py @@ -973,6 +973,37 @@ def test_get_function_from_fqn_wo_plugin(kernel: Kernel, custom_plugin_class): assert func +def test_get_function_bare_name_single_match(kernel: Kernel, custom_plugin_class): + kernel.add_plugin(custom_plugin_class(), "TestPlugin") + func = kernel.get_function(None, "getLightStatus") + assert func + + +def test_get_function_bare_name_ambiguous_warns(kernel: Kernel, caplog): + import logging + + class PluginA: + @kernel_function(name="check_permissions") + def check_permissions(self) -> str: + return "a" + + class PluginB: + @kernel_function(name="check_permissions") + def check_permissions(self) -> str: + return "b" + + kernel.add_plugin(PluginA(), "PluginA") + kernel.add_plugin(PluginB(), "PluginB") + + with caplog.at_level(logging.WARNING, logger="semantic_kernel.functions.kernel_function_extension"): + func = kernel.get_function(None, "check_permissions") + + # Warn-only: resolves to the first-registered match, but logs the ambiguity. + assert func is kernel.get_function("PluginA", "check_permissions") + assert "ambiguous" in caplog.text + assert "PluginA" in caplog.text and "PluginB" in caplog.text + + # endregion # region Services From e4025c3446479bff5de0906161620033d6e15d7a Mon Sep 17 00:00:00 2001 From: Evan Mattson <35585003+moonbox3@users.noreply.github.com> Date: Tue, 7 Jul 2026 17:45:30 +0900 Subject: [PATCH 33/33] Python: Bump Python version to 1.44.0 for a release (#14141) ### Motivation and Context Bumps the Python package version for the next release. ### Description Updates `semantic_kernel.__version__` from `1.43.1` to `1.44.0`. ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the SK Contribution Guidelines and the pre-submission formatting script raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I did not break anyone :smile: --- python/semantic_kernel/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/semantic_kernel/__init__.py b/python/semantic_kernel/__init__.py index 00fafbc1bae6..42ef8a7d80d7 100644 --- a/python/semantic_kernel/__init__.py +++ b/python/semantic_kernel/__init__.py @@ -2,7 +2,7 @@ from semantic_kernel.kernel import Kernel -__version__ = "1.43.1" +__version__ = "1.44.0" DEFAULT_RC_VERSION = f"{__version__}-rc9"