diff --git a/.npmrc b/.npmrc index 98fd4adc9e0e..3d79d10ff8f1 100644 --- a/.npmrc +++ b/.npmrc @@ -1,7 +1,8 @@ disturl="https://electronjs.org/headers" target="35.5.1" -ms_build_id="11708675" +ms_build_id="11727614" runtime="electron" build_from_source="true" legacy-peer-deps="true" timeout=180000 +npm_config_node_gyp="node build/npm/gyp/node_modules/node-gyp/bin/node-gyp.js" diff --git a/build/.cachesalt b/build/.cachesalt index 2d02e2ba768d..a3213b850c31 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2025-05-14T16:33:46.494Z +2025-06-09T07:16:15.626Z diff --git a/build/npm/gyp/package-lock.json b/build/npm/gyp/package-lock.json index a20d85c70dca..08b6ae29b01c 100644 --- a/build/npm/gyp/package-lock.json +++ b/build/npm/gyp/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "node-gyp": "^10.1.0" + "node-gyp": "^11.2.0" } }, "node_modules/@isaacs/cliui": { @@ -30,10 +30,23 @@ "node": ">=12" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@npmcli/agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", - "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", + "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", "dev": true, "license": "ISC", "dependencies": { @@ -44,20 +57,20 @@ "socks-proxy-agent": "^8.0.3" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", - "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, "license": "ISC", "dependencies": { "semver": "^7.3.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@pkgjs/parseargs": { @@ -72,46 +85,29 @@ } }, "node_modules/abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, "engines": { "node": ">= 14" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", "engines": { @@ -152,13 +148,13 @@ } }, "node_modules/cacache": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.3.tgz", - "integrity": "sha512-qXCd4rh6I07cnDqh8V48/94Tc/WSfj+o3Gn6NZ0aZovS255bUx8O13uKxRFd2eWG0xgsco7+YItQNPaa5E85hg==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^3.1.0", + "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", @@ -166,33 +162,23 @@ "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=10" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" + "node": ">=18" } }, "node_modules/color-convert": { @@ -216,9 +202,9 @@ "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -254,13 +240,13 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -320,14 +306,29 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/fdir": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", + "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -351,9 +352,9 @@ } }, "node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "license": "ISC", "dependencies": { @@ -367,9 +368,6 @@ "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -382,9 +380,9 @@ "license": "ISC" }, "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "dev": true, "license": "BSD-2-Clause" }, @@ -403,13 +401,13 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { @@ -440,16 +438,6 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/ip-address": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", @@ -474,13 +462,6 @@ "node": ">=8" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/isexe": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", @@ -492,17 +473,14 @@ } }, "node_modules/jackspeak": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", - "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -518,47 +496,33 @@ "license": "MIT" }, "node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "ISC", - "engines": { - "node": "14 || >=16.14" - } + "license": "ISC" }, "node_modules/make-fetch-happen": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", - "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", + "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "ssri": "^10.0.0" + "ssri": "^12.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/proc-log": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", - "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/minimatch": { @@ -601,18 +565,18 @@ } }, "node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz", + "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==", "dev": true, "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "minizlib": "^3.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" }, "optionalDependencies": { "encoding": "^0.1.13" @@ -644,6 +608,13 @@ "node": ">=8" } }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", @@ -670,6 +641,13 @@ "node": ">=8" } }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", @@ -696,57 +674,53 @@ "node": ">=8" } }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", "dev": true, "license": "MIT", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "minipass": "^7.1.2" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" + "node": ">= 18" } }, "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true, "license": "MIT", "bin": { - "mkdirp": "bin/cmd.js" + "mkdirp": "dist/cjs/src/bin.js" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "dev": true, "license": "MIT", "engines": { @@ -754,66 +728,63 @@ } }, "node_modules/node-gyp": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.1.0.tgz", - "integrity": "sha512-B4J5M1cABxPc5PwfjhbV5hoy2DP9p8lFXASnEN6hugXOa61416tnTZ29x9sSwAd0o99XNIcpvDDy1swAExsVKA==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.2.0.tgz", + "integrity": "sha512-T0S1zqskVUSxcsSTkAsLc7xCycrRYmtDHadDinzocrThjyQCn5kMlEBSj6H4qDbgsIOSLmmlRIeb0lZXj+UArA==", "dev": true, "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^4.0.0" + "tar": "^7.4.3", + "tinyglobby": "^0.2.12", + "which": "^5.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/nopt": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", - "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", "dev": true, "license": "ISC", "dependencies": { - "abbrev": "^2.0.0" + "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", "dev": true, "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, "license": "BlueOak-1.0.0" }, @@ -844,14 +815,27 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/promise-retry": { @@ -887,14 +871,11 @@ "optional": true }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -902,19 +883,6 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -963,9 +931,9 @@ } }, "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", + "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", "dev": true, "license": "MIT", "dependencies": { @@ -978,13 +946,13 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.1", + "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" }, @@ -1000,16 +968,16 @@ "license": "BSD-3-Clause" }, "node_modules/ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/string-width": { @@ -1117,89 +1085,70 @@ } }, "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", "dev": true, "license": "ISC", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^3.0.0" + "fdir": "^6.4.4", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" + "node": ">=12.0.0" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^4.0.0" + "unique-slug": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { @@ -1209,7 +1158,7 @@ "node-which": "bin/which.js" }, "engines": { - "node": "^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/wrap-ansi": { @@ -1311,11 +1260,14 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", "dev": true, - "license": "ISC" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } } } } diff --git a/build/npm/gyp/package.json b/build/npm/gyp/package.json index a1564133a1ee..2fee83064b69 100644 --- a/build/npm/gyp/package.json +++ b/build/npm/gyp/package.json @@ -4,7 +4,7 @@ "private": true, "license": "MIT", "devDependencies": { - "node-gyp": "^10.1.0" + "node-gyp": "^11.2.0" }, "scripts": {} } diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index be0c6c24282f..1033e4ecf68a 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -77,6 +77,12 @@ function setNpmrcConfig(dir, env) { } } + // Use our bundled node-gyp version + env['npm_config_node_gyp'] = + process.platform === 'win32' + ? path.join(__dirname, 'gyp', 'node_modules', '.bin', 'node-gyp.cmd') + : path.join(__dirname, 'gyp', 'node_modules', '.bin', 'node-gyp'); + // Force node-gyp to use process.config on macOS // which defines clang variable as expected. Otherwise we // run into compilation errors due to incorrect compiler diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts index 106ef702d693..e2105f2e017f 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts @@ -295,4 +295,19 @@ suite('vscode API - editors', () => { assert.strictEqual(document.getText(), Buffer.from(await workspace.fs.readFile(file)).toString()); } + + test('extEditor.selection can be empty #18075', async function () { + await withRandomFileEditor('foo', async editor => { + + assert.ok(editor.selections.length > 0); + + editor.selections = []; + + assert.strictEqual(editor.selections.length, 1); + assert.strictEqual(editor.selections[0].start.line, 0); + assert.strictEqual(editor.selections[0].start.character, 0); + assert.strictEqual(editor.selections[0].end.line, 0); + assert.strictEqual(editor.selections[0].end.character, 0); + }); + }); }); diff --git a/package.json b/package.json index 49da9b08d692..d78d007e5800 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.102.0", - "distro": "1f9299d1fbccfb501bade57b42c8d343c1e4b5a5", + "distro": "3c2b3776c5752c7f7dd69d3f1a9b6079ae890a16", "author": { "name": "Microsoft Corporation" }, diff --git a/src/vs/base/common/policy.ts b/src/vs/base/common/policy.ts index 8600c43854e6..befbff127944 100644 --- a/src/vs/base/common/policy.ts +++ b/src/vs/base/common/policy.ts @@ -28,7 +28,10 @@ export interface IPolicy { readonly previewFeature?: boolean; /** - * Default value when enabled. Default is `false`. + * Default value for a 'previewFeature' policy. Default is `false`. + * Remarks: + * A default value is only relevant when previewFeature is `true`. + * In all other instances, a value is required when setting a policy. */ readonly defaultValue?: string | number | boolean; } diff --git a/src/vs/base/node/nodeStreams.ts b/src/vs/base/node/nodeStreams.ts index 0dba130a07df..a7516e1e598d 100644 --- a/src/vs/base/node/nodeStreams.ts +++ b/src/vs/base/node/nodeStreams.ts @@ -28,7 +28,7 @@ export class StreamSplitter extends Transform { } } - override _transform(chunk: Buffer, _encoding: string, callback: (error?: Error | null, data?: any) => void): void { + override _transform(chunk: Buffer, _encoding: string, callback: (error?: Error | null, data?: Buffer) => void): void { if (!this.buffer) { this.buffer = chunk; } else { @@ -52,7 +52,7 @@ export class StreamSplitter extends Transform { callback(); } - override _flush(callback: (error?: Error | null, data?: any) => void): void { + override _flush(callback: (error?: Error | null, data?: Buffer) => void): void { if (this.buffer) { this.push(this.buffer); } diff --git a/src/vs/base/node/ports.ts b/src/vs/base/node/ports.ts index b664a8a0f4e1..a237f433ea03 100644 --- a/src/vs/base/node/ports.ts +++ b/src/vs/base/node/ports.ts @@ -64,7 +64,7 @@ function doFindFreePort(startPort: number, giveUpAfter: number, stride: number, } // Reference: https://chromium.googlesource.com/chromium/src.git/+/refs/heads/main/net/base/port_util.cc#56 -export const BROWSER_RESTRICTED_PORTS: any = { +export const BROWSER_RESTRICTED_PORTS: Record = { 1: true, // tcpmux 7: true, // echo 9: true, // discard diff --git a/src/vs/code/browser/workbench/workbench.ts b/src/vs/code/browser/workbench/workbench.ts index 3928342a0492..f9ee35ab3705 100644 --- a/src/vs/code/browser/workbench/workbench.ts +++ b/src/vs/code/browser/workbench/workbench.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { isStandalone } from '../../../base/browser/browser.js'; +import { addDisposableListener } from '../../../base/browser/dom.js'; import { mainWindow } from '../../../base/browser/window.js'; import { VSBuffer, decodeBase64, encodeBase64 } from '../../../base/common/buffer.js'; import { Emitter } from '../../../base/common/event.js'; @@ -340,9 +341,7 @@ class LocalStorageURLCallbackProvider extends Disposable implements IURLCallback return; } - const fn = () => this.onDidChangeLocalStorage(); - mainWindow.addEventListener('storage', fn); - this.onDidChangeLocalStorageDisposable = { dispose: () => mainWindow.removeEventListener('storage', fn) }; + this.onDidChangeLocalStorageDisposable = addDisposableListener(mainWindow, 'storage', () => this.onDidChangeLocalStorage()); } private stopListening(): void { diff --git a/src/vs/editor/common/languageFeatureRegistry.ts b/src/vs/editor/common/languageFeatureRegistry.ts index 6bf6f8517206..3728cad3c41a 100644 --- a/src/vs/editor/common/languageFeatureRegistry.ts +++ b/src/vs/editor/common/languageFeatureRegistry.ts @@ -139,7 +139,7 @@ export class LanguageFeatureRegistry { return result; } - private _orderedForEach(model: ITextModel, recursive: boolean, callback: (provider: Entry) => any): void { + private _orderedForEach(model: ITextModel, recursive: boolean, callback: (provider: Entry) => void): void { this._updateScores(model, recursive); @@ -191,7 +191,7 @@ export class LanguageFeatureRegistry { this._entries.sort(LanguageFeatureRegistry._compareByScoreAndTime); } - private static _compareByScoreAndTime(a: Entry, b: Entry): number { + private static _compareByScoreAndTime(a: Entry, b: Entry): number { if (a._score < b._score) { return 1; } else if (a._score > b._score) { diff --git a/src/vs/editor/common/services/textResourceConfiguration.ts b/src/vs/editor/common/services/textResourceConfiguration.ts index da2c0a8b653f..709752874247 100644 --- a/src/vs/editor/common/services/textResourceConfiguration.ts +++ b/src/vs/editor/common/services/textResourceConfiguration.ts @@ -72,7 +72,7 @@ export interface ITextResourceConfigurationService { * @param configurationTarget Optional target into which the configuration has to be updated. * If not specified, target will be derived by checking where the configuration is defined. */ - updateValue(resource: URI | undefined, key: string, value: any, configurationTarget?: ConfigurationTarget): Promise; + updateValue(resource: URI | undefined, key: string, value: unknown, configurationTarget?: ConfigurationTarget): Promise; } diff --git a/src/vs/editor/common/services/textResourceConfigurationService.ts b/src/vs/editor/common/services/textResourceConfigurationService.ts index 85ef41882c4c..6eda008b6efb 100644 --- a/src/vs/editor/common/services/textResourceConfigurationService.ts +++ b/src/vs/editor/common/services/textResourceConfigurationService.ts @@ -30,14 +30,14 @@ export class TextResourceConfigurationService extends Disposable implements ITex getValue(resource: URI | undefined, section?: string): T; getValue(resource: URI | undefined, at?: IPosition, section?: string): T; - getValue(resource: URI | undefined, arg2?: any, arg3?: any): T { + getValue(resource: URI | undefined, arg2?: unknown, arg3?: unknown): T { if (typeof arg3 === 'string') { return this._getValue(resource, Position.isIPosition(arg2) ? arg2 : null, arg3); } return this._getValue(resource, null, typeof arg2 === 'string' ? arg2 : undefined); } - updateValue(resource: URI | undefined, key: string, value: any, configurationTarget?: ConfigurationTarget): Promise { + updateValue(resource: URI | undefined, key: string, value: unknown, configurationTarget?: ConfigurationTarget): Promise { const language = resource ? this.getLanguage(resource, null) : null; const configurationValue = this.configurationService.inspect(key, { resource, overrideIdentifier: language }); if (configurationTarget === undefined) { @@ -47,7 +47,7 @@ export class TextResourceConfigurationService extends Disposable implements ITex return this.configurationService.updateValue(key, value, { resource, overrideIdentifier }, configurationTarget); } - private deriveConfigurationTarget(configurationValue: IConfigurationValue, language: string | null): ConfigurationTarget { + private deriveConfigurationTarget(configurationValue: IConfigurationValue, language: string | null): ConfigurationTarget { if (language) { if (configurationValue.memory?.override !== undefined) { return ConfigurationTarget.MEMORY; diff --git a/src/vs/editor/common/textModelEvents.ts b/src/vs/editor/common/textModelEvents.ts index 3123b120b285..8f9ab67df704 100644 --- a/src/vs/editor/common/textModelEvents.ts +++ b/src/vs/editor/common/textModelEvents.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IRange } from './core/range.js'; +import { IPosition } from './core/position.js'; +import { IRange, Range } from './core/range.js'; import { Selection } from './core/selection.js'; import { IModelDecoration, InjectedTextOptions } from './model.js'; @@ -403,6 +404,24 @@ export class ModelLineHeightChangedEvent { constructor(changes: ModelLineHeightChanged[]) { this.changes = changes; } + + public affects(rangeOrPosition: IRange | IPosition) { + if (Range.isIRange(rangeOrPosition)) { + for (const change of this.changes) { + if (change.lineNumber >= rangeOrPosition.startLineNumber && change.lineNumber <= rangeOrPosition.endLineNumber) { + return true; + } + } + return false; + } else { + for (const change of this.changes) { + if (change.lineNumber === rangeOrPosition.lineNumber) { + return true; + } + } + return false; + } + } } /** diff --git a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts index 9f443e037d69..736492e7292e 100644 --- a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts +++ b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts @@ -310,26 +310,18 @@ export class StickyScrollController extends Disposable implements IEditorContrib } this._revealPosition(position); })); - const mouseMoveListener = (mouseEvent: MouseEvent) => { + this._register(dom.addDisposableListener(mainWindow, dom.EventType.MOUSE_MOVE, mouseEvent => { this._mouseTarget = mouseEvent.target; this._onMouseMoveOrKeyDown(mouseEvent); - }; - const keyDownListener = (mouseEvent: KeyboardEvent) => { + })); + this._register(dom.addDisposableListener(mainWindow, dom.EventType.KEY_DOWN, mouseEvent => { this._onMouseMoveOrKeyDown(mouseEvent); - }; - const keyUpListener = (e: KeyboardEvent) => { + })); + this._register(dom.addDisposableListener(mainWindow, dom.EventType.KEY_UP, () => { if (this._showEndForLine !== undefined) { this._showEndForLine = undefined; this._renderStickyScroll(); } - }; - mainWindow.addEventListener(dom.EventType.MOUSE_MOVE, mouseMoveListener); - mainWindow.addEventListener(dom.EventType.KEY_DOWN, keyDownListener); - mainWindow.addEventListener(dom.EventType.KEY_UP, keyUpListener); - this._register(toDisposable(() => { - mainWindow.removeEventListener(dom.EventType.MOUSE_MOVE, mouseMoveListener); - mainWindow.removeEventListener(dom.EventType.KEY_DOWN, keyDownListener); - mainWindow.removeEventListener(dom.EventType.KEY_UP, keyUpListener); })); this._register(gesture.onMouseMoveOrRelevantKeyDown(([mouseEvent, _keyboardEvent]) => { diff --git a/src/vs/editor/editor.worker.start.ts b/src/vs/editor/editor.worker.start.ts index 9906249af9d5..a7304493087b 100644 --- a/src/vs/editor/editor.worker.start.ts +++ b/src/vs/editor/editor.worker.start.ts @@ -20,7 +20,7 @@ export function start(client: TCli if (typeof prop !== 'string') { throw new Error(`Not supported`); } - return (...args: any[]) => { + return (...args: unknown[]) => { return editorWorkerHost.$fhr(prop, args); }; } diff --git a/src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts b/src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts index e4382f461f86..8bc11939b10c 100644 --- a/src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts +++ b/src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts @@ -3,10 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { addDisposableListener } from '../../../base/browser/dom.js'; import { CachedFunction } from '../../../base/common/cache.js'; import { getStructuralKey } from '../../../base/common/equals.js'; import { Event, IValueWithChangeEvent } from '../../../base/common/event.js'; -import { Disposable, IDisposable, toDisposable } from '../../../base/common/lifecycle.js'; +import { Disposable, DisposableStore, IDisposable, toDisposable } from '../../../base/common/lifecycle.js'; import { FileAccess } from '../../../base/common/network.js'; import { derived, observableFromEvent, ValueWithChangeEventFromObservable } from '../../../base/common/observable.js'; import { localize } from '../../../nls.js'; @@ -277,17 +278,26 @@ function checkEnabledState(state: EnabledState, getScreenReaderAttached: () => b * Play the given audio url. * @volume value between 0 and 1 */ -function playAudio(url: string, volume: number): Promise { - return new Promise((resolve, reject) => { +async function playAudio(url: string, volume: number): Promise { + const disposables = new DisposableStore(); + try { + return await doPlayAudio(url, volume, disposables); + } finally { + disposables.dispose(); + } +} + +function doPlayAudio(url: string, volume: number, disposables: DisposableStore): Promise { + return new Promise((resolve, reject) => { const audio = new Audio(url); audio.volume = volume; - audio.addEventListener('ended', () => { + disposables.add(addDisposableListener(audio, 'ended', () => { resolve(audio); - }); - audio.addEventListener('error', (e) => { + })); + disposables.add(addDisposableListener(audio, 'error', (e) => { // When the error event fires, ended might not be called reject(e.error); - }); + })); audio.play().catch(e => { // When play fails, the error event is not fired. reject(e); diff --git a/src/vs/platform/native/electron-main/nativeHostMainService.ts b/src/vs/platform/native/electron-main/nativeHostMainService.ts index 7e1dda7b1a49..37ecd52d6289 100644 --- a/src/vs/platform/native/electron-main/nativeHostMainService.ts +++ b/src/vs/platform/native/electron-main/nativeHostMainService.ts @@ -558,9 +558,9 @@ export class NativeHostMainService extends Disposable implements INativeHostMain this.environmentMainService.unsetSnapExportedVariables(); try { if (matchesSomeScheme(url, Schemas.http, Schemas.https)) { - this.openExternalBrowser(url, defaultApplication); + this.openExternalBrowser(windowId, url, defaultApplication); } else { - shell.openExternal(url); + this.doOpenShellExternal(windowId, url); } } finally { this.environmentMainService.restoreSnapExportedVariables(); @@ -569,17 +569,17 @@ export class NativeHostMainService extends Disposable implements INativeHostMain return true; } - private async openExternalBrowser(url: string, defaultApplication?: string): Promise { + private async openExternalBrowser(windowId: number | undefined, url: string, defaultApplication?: string): Promise { const configuredBrowser = defaultApplication ?? this.configurationService.getValue('workbench.externalBrowser'); if (!configuredBrowser) { - return shell.openExternal(url); + return this.doOpenShellExternal(windowId, url); } if (configuredBrowser.includes(posix.sep) || configuredBrowser.includes(win32.sep)) { const browserPathExists = await Promises.exists(configuredBrowser); if (!browserPathExists) { this.logService.error(`Configured external browser path does not exist: ${configuredBrowser}`); - return shell.openExternal(url); + return this.doOpenShellExternal(windowId, url); } } @@ -602,12 +602,46 @@ export class NativeHostMainService extends Disposable implements INativeHostMain // (see also https://github.com/microsoft/vscode/issues/230636) res.stderr?.once('data', (data: Buffer) => { this.logService.error(`Error openening external URL '${url}' using browser '${configuredBrowser}': ${data.toString()}`); - return shell.openExternal(url); + return this.doOpenShellExternal(windowId, url); }); } } catch (error) { this.logService.error(`Unable to open external URL '${url}' using browser '${configuredBrowser}' due to ${error}.`); - return shell.openExternal(url); + return this.doOpenShellExternal(windowId, url); + } + } + + private async doOpenShellExternal(windowId: number | undefined, url: string): Promise { + try { + await shell.openExternal(url); + } catch (error) { + let isLink: boolean; + let message: string; + if (matchesSomeScheme(url, Schemas.http, Schemas.https)) { + isLink = true; + message = localize('openExternalErrorLinkMessage', "An error occurred opening a link in your default browser."); + } else { + isLink = false; + message = localize('openExternalProgramErrorMessage', "An error occurred opening an external program."); + } + + const { response } = await this.dialogMainService.showMessageBox({ + type: 'error', + message, + detail: error.message, + buttons: isLink ? [ + localize({ key: 'copyLink', comment: ['&& denotes a mnemonic'] }, "&&Copy Link"), + localize('cancel', "Cancel") + ] : [ + localize({ key: 'ok', comment: ['&& denotes a mnemonic'] }, "&&OK") + ] + }, this.windowById(windowId)?.win ?? undefined); + + if (response === 1 /* Cancel */) { + return; + } + + this.writeClipboardText(windowId, url); } } diff --git a/src/vs/platform/notification/common/notification.ts b/src/vs/platform/notification/common/notification.ts index f11015208566..a2f59a71fab8 100644 --- a/src/vs/platform/notification/common/notification.ts +++ b/src/vs/platform/notification/common/notification.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { localize } from '../../../nls.js'; import { IAction } from '../../../base/common/actions.js'; import { Event } from '../../../base/common/event.js'; import BaseSeverity from '../../../base/common/severity.js'; @@ -472,3 +473,19 @@ export class NoOpProgress implements INotificationProgress { total(value: number): void { } worked(value: number): void { } } + +export function withSeverityPrefix(label: string, severity: Severity): string { + + // Add severity prefix to match WCAG 4.1.3 Status + // Messages requirements. + + if (severity === Severity.Error) { + return localize('severityPrefix.error', "Error: {0}", label); + } + + if (severity === Severity.Warning) { + return localize('severityPrefix.warning', "Warning: {0}", label); + } + + return localize('severityPrefix.info', "Info: {0}", label); +} diff --git a/src/vs/workbench/api/browser/mainThreadMcp.ts b/src/vs/workbench/api/browser/mainThreadMcp.ts index 491cc5d25812..407a8d232b48 100644 --- a/src/vs/workbench/api/browser/mainThreadMcp.ts +++ b/src/vs/workbench/api/browser/mainThreadMcp.ts @@ -3,13 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from '../../../nls.js'; import { disposableTimeout } from '../../../base/common/async.js'; +import { CancellationError } from '../../../base/common/errors.js'; import { Emitter } from '../../../base/common/event.js'; import { Disposable, DisposableMap } from '../../../base/common/lifecycle.js'; +import { IAuthorizationProtectedResourceMetadata, IAuthorizationServerMetadata } from '../../../base/common/oauth.js'; import { ISettableObservable, observableValue } from '../../../base/common/observable.js'; import Severity from '../../../base/common/severity.js'; import { URI, UriComponents } from '../../../base/common/uri.js'; +import * as nls from '../../../nls.js'; import { IDialogService, IPromptButton } from '../../../platform/dialogs/common/dialogs.js'; import { LogLevel } from '../../../platform/log/common/log.js'; import { IMcpMessageTransport, IMcpRegistry } from '../../contrib/mcp/common/mcpRegistryTypes.js'; @@ -23,8 +25,6 @@ import { ExtensionHostKind, extensionHostKindToString } from '../../services/ext import { IExtHostContext, extHostNamedCustomer } from '../../services/extensions/common/extHostCustomers.js'; import { Proxied } from '../../services/extensions/common/proxyIdentifier.js'; import { ExtHostContext, ExtHostMcpShape, MainContext, MainThreadMcpShape } from '../common/extHost.protocol.js'; -import { CancellationError } from '../../../base/common/errors.js'; -import { IAuthorizationProtectedResourceMetadata, IAuthorizationServerMetadata } from '../../../base/common/oauth.js'; @extHostNamedCustomer(MainContext.MainThreadMcp) export class MainThreadMcp extends Disposable implements MainThreadMcpShape { diff --git a/src/vs/workbench/api/common/extHostTextEditor.ts b/src/vs/workbench/api/common/extHostTextEditor.ts index 86a322348a8d..b523bf14a828 100644 --- a/src/vs/workbench/api/common/extHostTextEditor.ts +++ b/src/vs/workbench/api/common/extHostTextEditor.ts @@ -456,6 +456,9 @@ export class ExtHostTextEditor { if (!Array.isArray(value) || value.some(a => !(a instanceof Selection))) { throw illegalArgument('selections'); } + if (value.length === 0) { + value = [new Selection(0, 0, 0, 0)]; + } that._selections = value; that._trySetSelection(); }, diff --git a/src/vs/workbench/browser/parts/notifications/notificationAccessibleView.ts b/src/vs/workbench/browser/parts/notifications/notificationAccessibleView.ts index 723c97a134c9..62cd08fa022f 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationAccessibleView.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationAccessibleView.ts @@ -16,6 +16,7 @@ import { IListService, WorkbenchList } from '../../../../platform/list/browser/l import { getNotificationFromContext } from './notificationsCommands.js'; import { NotificationFocusedContext } from '../../../common/contextkeys.js'; import { INotificationViewItem } from '../../../common/notifications.js'; +import { withSeverityPrefix } from '../../../../platform/notification/common/notification.js'; export class NotificationAccessibleView implements IAccessibleViewImplementation { readonly priority = 90; @@ -56,10 +57,10 @@ export class NotificationAccessibleView implements IAccessibleViewImplementation function getContentForNotification(): string | undefined { const notification = getNotificationFromContext(listService); const message = notification?.message.original.toString(); - if (!notification) { + if (!notification || !message) { return; } - return notification.source ? localize('notification.accessibleViewSrc', '{0} Source: {1}', message, notification.source) : localize('notification.accessibleView', '{0}', message); + return withSeverityPrefix(notification.source ? localize('notification.accessibleViewSrc', '{0} Source: {1}', message, notification.source) : message, notification.severity); } const content = getContentForNotification(); if (!content) { diff --git a/src/vs/workbench/browser/parts/notifications/notificationsList.ts b/src/vs/workbench/browser/parts/notifications/notificationsList.ts index cd5c2f5b6a5a..5cefc3153251 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsList.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsList.ts @@ -21,6 +21,7 @@ import { AriaRole } from '../../../../base/browser/ui/aria/aria.js'; import { NotificationActionRunner } from './notificationsCommands.js'; import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js'; import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js'; +import { withSeverityPrefix } from '../../../../platform/notification/common/notification.js'; export interface INotificationsListOptions extends IListOptions { readonly widgetAriaLabel?: string; @@ -244,27 +245,32 @@ export class NotificationsList extends Disposable { } } -class NotificationAccessibilityProvider implements IListAccessibilityProvider { +export class NotificationAccessibilityProvider implements IListAccessibilityProvider { + constructor( private readonly _options: INotificationsListOptions, @IKeybindingService private readonly _keybindingService: IKeybindingService, @IConfigurationService private readonly _configurationService: IConfigurationService ) { } + getAriaLabel(element: INotificationViewItem): string { let accessibleViewHint: string | undefined; const keybinding = this._keybindingService.lookupKeybinding('editor.action.accessibleView')?.getAriaLabel(); if (this._configurationService.getValue('accessibility.verbosity.notification')) { accessibleViewHint = keybinding ? localize('notificationAccessibleViewHint', "Inspect the response in the accessible view with {0}", keybinding) : localize('notificationAccessibleViewHintNoKb', "Inspect the response in the accessible view via the command Open Accessible View which is currently not triggerable via keybinding"); } + if (!element.source) { - return accessibleViewHint ? localize('notificationAriaLabelHint', "{0}, notification, {1}", element.message.raw, accessibleViewHint) : localize('notificationAriaLabel', "{0}, notification", element.message.raw); + return withSeverityPrefix(accessibleViewHint ? localize('notificationAriaLabelHint', "{0}, notification, {1}", element.message.raw, accessibleViewHint) : localize('notificationAriaLabel', "{0}, notification", element.message.raw), element.severity); } - return accessibleViewHint ? localize('notificationWithSourceAriaLabelHint', "{0}, source: {1}, notification, {2}", element.message.raw, element.source, accessibleViewHint) : localize('notificationWithSourceAriaLabel', "{0}, source: {1}, notification", element.message.raw, element.source); + return withSeverityPrefix(accessibleViewHint ? localize('notificationWithSourceAriaLabelHint', "{0}, source: {1}, notification, {2}", element.message.raw, element.source, accessibleViewHint) : localize('notificationWithSourceAriaLabel', "{0}, source: {1}, notification", element.message.raw, element.source), element.severity); } + getWidgetAriaLabel(): string { return this._options.widgetAriaLabel ?? localize('notificationsList', "Notifications List"); } + getRole(): AriaRole { return 'dialog'; // https://github.com/microsoft/vscode/issues/82728 } diff --git a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts index 42fffede3414..b74fdf563711 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts @@ -18,7 +18,7 @@ import { widgetShadow } from '../../../../platform/theme/common/colorRegistry.js import { IEditorGroupsService } from '../../../services/editor/common/editorGroupsService.js'; import { INotificationsToastController } from './notificationsCommands.js'; import { IContextKey, IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js'; -import { Severity, NotificationsFilter, NotificationPriority } from '../../../../platform/notification/common/notification.js'; +import { Severity, NotificationsFilter, NotificationPriority, withSeverityPrefix } from '../../../../platform/notification/common/notification.js'; import { ScrollbarVisibility } from '../../../../base/common/scrollable.js'; import { ILifecycleService, LifecyclePhase } from '../../../services/lifecycle/common/lifecycle.js'; import { IHostService } from '../../../services/host/browser/host.js'; @@ -200,11 +200,11 @@ export class NotificationsToasts extends Themable implements INotificationsToast const notificationList = this.instantiationService.createInstance(NotificationsList, notificationToast, { verticalScrollMode: ScrollbarVisibility.Hidden, widgetAriaLabel: (() => { - if (!item.source) { - return localize('notificationAriaLabel', "{0}, notification", item.message.raw); + return withSeverityPrefix(localize('notificationAriaLabel', "{0}, notification", item.message.raw), item.severity); } - return localize('notificationWithSourceAriaLabel', "{0}, source: {1}, notification", item.message.raw, item.source); + + return withSeverityPrefix(localize('notificationWithSourceAriaLabel', "{0}, source: {1}, notification", item.message.raw, item.source), item.severity); })() }); itemDisposables.add(notificationList); diff --git a/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingActions.ts b/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingActions.ts index f50b6b77b579..c1aebb455531 100644 --- a/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingActions.ts +++ b/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingActions.ts @@ -101,58 +101,6 @@ abstract class WorkingSetAction extends EditingSessionAction { abstract runWorkingSetAction(accessor: ServicesAccessor, editingSession: IChatEditingSession, chatWidget: IChatWidget | undefined, ...uris: URI[]): any; } -registerAction2(class RemoveFileFromWorkingSet extends WorkingSetAction { - constructor() { - super({ - id: 'chatEditing.removeFileFromWorkingSet', - title: localize2('removeFileFromWorkingSet', 'Remove File'), - icon: Codicon.close, - precondition: ChatContextKeys.requestInProgress.negate(), - menu: [{ - id: MenuId.ChatEditingWidgetModifiedFilesToolbar, - // when: ContextKeyExpr.or(ContextKeyExpr.equals(chatEditingWidgetFileStateContextKey.key, WorkingSetEntryState.Attached), ContextKeyExpr.equals(chatEditingWidgetFileStateContextKey.key, WorkingSetEntryState.Suggested), ContextKeyExpr.equals(chatEditingWidgetFileStateContextKey.key, WorkingSetEntryState.Transient)), - order: 5, - group: 'navigation' - }], - }); - } - - async runWorkingSetAction(accessor: ServicesAccessor, currentEditingSession: IChatEditingSession, chatWidget: IChatWidget, ...uris: URI[]): Promise { - const dialogService = accessor.get(IDialogService); - - const pendingEntries = currentEditingSession.entries.get().filter((entry) => uris.includes(entry.modifiedURI) && entry.state.get() === ModifiedFileEntryState.Modified); - if (pendingEntries.length > 0) { - // Ask for confirmation if there are any pending edits - const file = pendingEntries.length > 1 - ? localize('chat.editing.removeFile.confirmationmanyFiles', "{0} files", pendingEntries.length) - : basename(pendingEntries[0].modifiedURI); - const confirmation = await dialogService.confirm({ - title: localize('chat.editing.removeFile.confirmation.title', "Remove {0} from working set?", file), - message: localize('chat.editing.removeFile.confirmation.message', "This will remove {0} from your working set and undo the edits made to it. Do you want to proceed?", file), - primaryButton: localize('chat.editing.removeFile.confirmation.primaryButton', "Yes"), - type: 'info' - }); - if (!confirmation.confirmed) { - return; - } - } - - // Remove from working set - await currentEditingSession.reject(...uris); - currentEditingSession.remove(...uris); - - // Remove from chat input part - for (const uri of uris) { - chatWidget.attachmentModel.delete(uri.toString()); - } - - // Clear all related file suggestions - if (chatWidget.attachmentModel.fileAttachments.length === 0) { - chatWidget.input.relatedFiles?.clear(); - } - } -}); - registerAction2(class OpenFileInDiffAction extends WorkingSetAction { constructor() { super({ @@ -328,41 +276,6 @@ export async function discardAllEditsWithConfirmation(accessor: ServicesAccessor return true; } -// TODO@roblourens this may be obsolete? -export class ChatEditingRemoveAllFilesAction extends EditingSessionAction { - static readonly ID = 'chatEditing.clearWorkingSet'; - - constructor() { - super({ - id: ChatEditingRemoveAllFilesAction.ID, - title: localize('clearWorkingSet', 'Clear Working Set'), - icon: Codicon.clearAll, - tooltip: localize('clearWorkingSet', 'Clear Working Set'), - precondition: ContextKeyExpr.and(ChatContextKeys.requestInProgress.negate()), - menu: [ - { - id: MenuId.ChatEditingWidgetToolbar, - group: 'navigation', - order: 5, - when: hasAppliedChatEditsContextKey.negate() - } - ] - }); - } - - override async runEditingSessionAction(accessor: ServicesAccessor, editingSession: IChatEditingSession, chatWidget: IChatWidget, ...args: any[]): Promise { - // Remove all files from working set - const uris = [...editingSession.entries.get()].map((e) => e.modifiedURI); - editingSession.remove(...uris); - - // Remove all file attachments - const fileAttachments = chatWidget.attachmentModel ? chatWidget.attachmentModel.fileAttachments : []; - const attachmentIdsToRemove = fileAttachments.map(attachment => attachment.toString()); - chatWidget.attachmentModel.delete(...attachmentIdsToRemove); - } -} -registerAction2(ChatEditingRemoveAllFilesAction); - export class ChatEditingShowChangesAction extends EditingSessionAction { static readonly ID = 'chatEditing.viewChanges'; static readonly LABEL = localize('chatEditing.viewChanges', 'View All Edits'); diff --git a/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts b/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts index edc6531ff889..422c4045c429 100644 --- a/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts +++ b/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts @@ -529,28 +529,6 @@ export class ChatEditingSession extends Disposable implements IChatEditingSessio this._entriesObs.set(entriesArr, undefined); } - remove(...uris: URI[]): void { - this._assertNotDisposed(); - - let didRemoveUris = false; - for (const uri of uris) { - - const entry = this._entriesObs.get().find(e => isEqual(e.modifiedURI, uri)); - if (entry) { - entry.dispose(); - const newEntries = this._entriesObs.get().filter(e => !isEqual(e.modifiedURI, uri)); - this._entriesObs.set(newEntries, undefined); - didRemoveUris = true; - } - - } - - if (!didRemoveUris) { - return; // noop - } - - } - private _assertNotDisposed(): void { if (this._state.get() === ChatEditingSessionState.Disposed) { throw new BugIndicatingError(`Cannot access a disposed editing session`); diff --git a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts index b923b333c78c..3cbca481b936 100644 --- a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts @@ -93,7 +93,7 @@ import { DefaultChatAttachmentWidget, ElementChatAttachmentWidget, FileAttachmen import { IDisposableReference } from './chatContentParts/chatCollections.js'; import { CollapsibleListPool, IChatCollapsibleListItem } from './chatContentParts/chatReferencesContentPart.js'; import { ChatDragAndDrop } from './chatDragAndDrop.js'; -import { ChatEditingRemoveAllFilesAction, ChatEditingShowChangesAction, ViewPreviousEditsAction } from './chatEditing/chatEditingActions.js'; +import { ChatEditingShowChangesAction, ViewPreviousEditsAction } from './chatEditing/chatEditingActions.js'; import { ChatFollowups } from './chatFollowups.js'; import { ChatSelectedTools } from './chatSelectedTools.js'; import { IChatViewState } from './chatWidget.js'; @@ -1493,7 +1493,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge arg: { sessionId: chatEditingSession.chatSessionId }, }, buttonConfigProvider: (action) => { - if (action.id === ChatEditingShowChangesAction.ID || action.id === ChatEditingRemoveAllFilesAction.ID || action.id === ViewPreviousEditsAction.Id) { + if (action.id === ChatEditingShowChangesAction.ID || action.id === ViewPreviousEditsAction.Id) { return { showIcon: true, showLabel: false, isSecondary: true }; } return undefined; diff --git a/src/vs/workbench/contrib/chat/common/chatEditingService.ts b/src/vs/workbench/contrib/chat/common/chatEditingService.ts index 3b67848e26cc..97a3f3a499fa 100644 --- a/src/vs/workbench/contrib/chat/common/chatEditingService.ts +++ b/src/vs/workbench/contrib/chat/common/chatEditingService.ts @@ -108,7 +108,6 @@ export interface IChatEditingSession extends IDisposable { readonly state: IObservable; readonly entries: IObservable; show(previousChanges?: boolean): Promise; - remove(...uris: URI[]): void; accept(...uris: URI[]): Promise; reject(...uris: URI[]): Promise; getEntry(uri: URI): IModifiedFileEntry | undefined; diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/frontMatterDecoder.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/frontMatterDecoder.ts index 89a6517e5f9c..704e10f17541 100644 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/frontMatterDecoder.ts +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/frontMatterDecoder.ts @@ -11,8 +11,11 @@ import { ReadableStream } from '../../../../../../../../base/common/stream.js'; import { FrontMatterToken, FrontMatterRecord } from './tokens/index.js'; import { BaseDecoder } from '../baseDecoder.js'; import { SimpleDecoder, type TSimpleDecoderToken } from '../simpleCodec/simpleDecoder.js'; -import { PartialFrontMatterRecord, PartialFrontMatterRecordName, PartialFrontMatterRecordNameWithDelimiter } from './parsers/frontMatterRecord/index.js'; import { ObjectStream } from '../utils/objectStream.js'; +import { PartialFrontMatterRecordNameWithDelimiter } from './parsers/frontMatterRecord/frontMatterRecordNameWithDelimiter.js'; +import { PartialFrontMatterRecord } from './parsers/frontMatterRecord/frontMatterRecord.js'; +import { PartialFrontMatterRecordName } from './parsers/frontMatterRecord/frontMatterRecordName.js'; +import { FrontMatterParserFactory } from './parsers/frontMatterParserFactory.js'; /** * Tokens produced by this decoder. @@ -29,16 +32,17 @@ export class FrontMatterDecoder extends BaseDecoder | ObjectStream, ) { if (stream instanceof ObjectStream) { super(stream); - - return; + } else { + super(new SimpleDecoder(stream)); } - - super(new SimpleDecoder(stream)); + this.parserFactory = new FrontMatterParserFactory(); } protected override onStreamData(token: TSimpleDecoderToken): void { @@ -92,7 +96,7 @@ export class FrontMatterDecoder extends BaseDecoder { // comma or a closing square bracket must stop the parsing // process of the value represented by a generic sequence of tokens diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterParserFactory.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterParserFactory.ts new file mode 100644 index 000000000000..0be65371449d --- /dev/null +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterParserFactory.ts @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { BaseToken } from '../../baseToken.js'; +import { LeftBracket } from '../../simpleCodec/tokens/brackets.js'; +import { Word } from '../../simpleCodec/tokens/word.js'; +import { FrontMatterRecordDelimiter, FrontMatterRecordName } from '../tokens/frontMatterRecord.js'; +import { TQuoteToken } from '../tokens/frontMatterString.js'; +import { PartialFrontMatterArray } from './frontMatterArray.js'; +import { PartialFrontMatterRecord } from './frontMatterRecord/frontMatterRecord.js'; +import { PartialFrontMatterRecordName } from './frontMatterRecord/frontMatterRecordName.js'; +import { PartialFrontMatterRecordNameWithDelimiter, TNameStopToken } from './frontMatterRecord/frontMatterRecordNameWithDelimiter.js'; +import { PartialFrontMatterSequence } from './frontMatterSequence.js'; +import { PartialFrontMatterString } from './frontMatterString.js'; +import { PartialFrontMatterValue } from './frontMatterValue.js'; + +export class FrontMatterParserFactory { + createRecord(tokens: [FrontMatterRecordName, FrontMatterRecordDelimiter]): PartialFrontMatterRecord { + return new PartialFrontMatterRecord(this, tokens); + } + createRecordName(startToken: Word): PartialFrontMatterRecordName { + return new PartialFrontMatterRecordName(this, startToken); + } + createRecordNameWithDelimiter(tokens: readonly [FrontMatterRecordName, TNameStopToken]): PartialFrontMatterRecordNameWithDelimiter { + return new PartialFrontMatterRecordNameWithDelimiter(this, tokens); + } + createArray(startToken: LeftBracket) { + return new PartialFrontMatterArray(this, startToken); + } + createValue(shouldStop: (token: BaseToken) => boolean): PartialFrontMatterValue { + return new PartialFrontMatterValue(this, shouldStop); + } + createString(startToken: TQuoteToken): PartialFrontMatterString { + return new PartialFrontMatterString(startToken); + } + createSequence(shouldStop: (token: BaseToken) => boolean): PartialFrontMatterSequence { + return new PartialFrontMatterSequence(shouldStop); + } +} diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterRecord/frontMatterRecord.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterRecord/frontMatterRecord.ts index 5ea54b010459..e4afee055b5e 100644 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterRecord/frontMatterRecord.ts +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterRecord/frontMatterRecord.ts @@ -14,6 +14,7 @@ import { type TSimpleDecoderToken } from '../../../simpleCodec/simpleDecoder.js' import { Word, FormFeed, SpacingToken } from '../../../simpleCodec/tokens/tokens.js'; import { assertNotConsumed, ParserBase, type TAcceptTokenResult } from '../../../simpleCodec/parserBase.js'; import { FrontMatterValueToken, FrontMatterRecordName, FrontMatterRecordDelimiter, FrontMatterRecord } from '../../tokens/index.js'; +import { type FrontMatterParserFactory } from '../frontMatterParserFactory.js'; /** * Type of a next parser that can be returned by {@link PartialFrontMatterRecord}. @@ -44,6 +45,7 @@ export class PartialFrontMatterRecord extends ParserBase { constructor( + private readonly factory: FrontMatterParserFactory, startToken: Word, ) { super([startToken]); @@ -57,7 +59,7 @@ export class PartialFrontMatterRecordName extends ParserBase { constructor( + private readonly factory: FrontMatterParserFactory, tokens: readonly [FrontMatterRecordName, TNameStopToken], ) { super([...tokens]); @@ -63,7 +65,7 @@ export class PartialFrontMatterRecordNameWithDelimiter extends ParserBase< this.isConsumed = true; return { result: 'success', - nextParser: new PartialFrontMatterRecord( + nextParser: this.factory.createRecord( [recordName, recordDelimiter], ), wasTokenConsumed: true, diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterRecord/index.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterRecord/index.ts deleted file mode 100644 index 5518e6ee0c5f..000000000000 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterRecord/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export { PartialFrontMatterRecord } from './frontMatterRecord.js'; -export { PartialFrontMatterRecordName } from './frontMatterRecordName.js'; -export { PartialFrontMatterRecordNameWithDelimiter } from './frontMatterRecordNameWithDelimiter.js'; diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterValue.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterValue.ts index 668a757c827c..710767aed404 100644 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterValue.ts +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/codecs/base/frontMatterCodec/parsers/frontMatterValue.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { BaseToken } from '../../baseToken.js'; -import { PartialFrontMatterArray } from './frontMatterArray.js'; -import { PartialFrontMatterString } from './frontMatterString.js'; +import { type PartialFrontMatterArray } from './frontMatterArray.js'; +import { type PartialFrontMatterString } from './frontMatterString.js'; import { asBoolean, FrontMatterBoolean } from '../tokens/frontMatterBoolean.js'; import { FrontMatterValueToken } from '../tokens/frontMatterToken.js'; import { PartialFrontMatterSequence } from './frontMatterSequence.js'; @@ -13,6 +13,7 @@ import { FrontMatterSequence } from '../tokens/frontMatterSequence.js'; import { TSimpleDecoderToken } from '../../simpleCodec/simpleDecoder.js'; import { Word, Quote, DoubleQuote, LeftBracket } from '../../simpleCodec/tokens/tokens.js'; import { assertNotConsumed, ParserBase, TAcceptTokenResult } from '../../simpleCodec/parserBase.js'; +import { type FrontMatterParserFactory } from './frontMatterParserFactory.js'; /** * List of tokens that can start a "value" sequence. @@ -54,6 +55,7 @@ export class PartialFrontMatterValue extends ParserBase { - const lineHeight = this.editor.getOption(EditorOption.lineHeight); - this.domNode.style.height = `${lineHeight}px`; - this.domNode.style.width = `${Math.ceil(0.8 * lineHeight)}px`; - this.domNode.style.marginLeft = `4px`; - }; - updateSize(); + this.updateSize(); this.toDispose.push(this.editor.onDidChangeConfiguration(c => { if (c.hasChanged(EditorOption.fontSize) || c.hasChanged(EditorOption.lineHeight)) { - updateSize(); + this.updateSize(); } })); } + private updateSize() { + const lineHeight = this.range ? this.editor.getLineHeightForPosition(this.range.getStartPosition()) : this.editor.getOption(EditorOption.lineHeight); + this.domNode.style.height = `${lineHeight}px`; + this.domNode.style.width = `${Math.ceil(0.8 * lineHeight)}px`; + this.domNode.style.marginLeft = `4px`; + } + @memoize getId(): string { return generateUuid(); diff --git a/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts b/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts index 07b92710f724..84524c76602d 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointWidget.ts @@ -421,6 +421,7 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi options.lineHeight = editorConfig.lineHeight; options.fontLigatures = editorConfig.fontLigatures; options.ariaLabel = this.placeholder; + options.allowVariableLineHeights = false; return options; } diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 930812de0f99..ce1622935268 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -737,6 +737,7 @@ export class Repl extends FilterViewPane implements IHistoryNavigationWidget { const config = this.configurationService.getValue('debug'); options.acceptSuggestionOnEnter = config.console.acceptSuggestionOnEnter === 'on' ? 'on' : 'off'; options.ariaLabel = this.getAriaLabel(); + options.allowVariableLineHeights = false; this.replInput = this.scopedInstantiationService.createInstance(CodeEditorWidget, this.replInputContainer, options, getSimpleCodeEditorWidgetOptions()); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionFeaturesTab.ts b/src/vs/workbench/contrib/extensions/browser/extensionFeaturesTab.ts index bcef6a198c03..0b7daf56e120 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionFeaturesTab.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionFeaturesTab.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable, DisposableStore, IDisposable, MutableDisposable, toDisposable } from '../../../../base/common/lifecycle.js'; -import { $, append, clearNode } from '../../../../base/browser/dom.js'; +import { $, append, clearNode, addDisposableListener, EventType } from '../../../../base/browser/dom.js'; import { Emitter, Event } from '../../../../base/common/event.js'; import { ExtensionIdentifier, IExtensionManifest } from '../../../../platform/extensions/common/extensions.js'; import { Orientation, Sizing, SplitView } from '../../../../base/browser/ui/splitview/splitview.js'; @@ -304,15 +304,13 @@ class RuntimeStatusMarkdownRenderer extends Disposable implements IExtensionFeat hoverDisposable.value = undefined; } }; - svg.addEventListener('mousemove', mouseMoveListener); - disposables.add(toDisposable(() => svg.removeEventListener('mousemove', mouseMoveListener))); + disposables.add(addDisposableListener(svg, EventType.MOUSE_MOVE, mouseMoveListener)); const mouseLeaveListener = () => { highlightCircle.style.display = 'none'; hoverDisposable.value = undefined; }; - svg.addEventListener('mouseleave', mouseLeaveListener); - disposables.add(toDisposable(() => svg.removeEventListener('mouseleave', mouseLeaveListener))); + disposables.add(addDisposableListener(svg, EventType.MOUSE_LEAVE, mouseLeaveListener)); } } diff --git a/src/vs/workbench/contrib/interactive/browser/replInputHintContentWidget.ts b/src/vs/workbench/contrib/interactive/browser/replInputHintContentWidget.ts index dec54b24f4b1..de429e98bcf9 100644 --- a/src/vs/workbench/contrib/interactive/browser/replInputHintContentWidget.ts +++ b/src/vs/workbench/contrib/interactive/browser/replInputHintContentWidget.ts @@ -27,6 +27,7 @@ export class ReplInputHintContentWidget extends Disposable implements IContentWi private domNode: HTMLElement | undefined; private ariaLabel: string = ''; + private label: KeybindingLabel | undefined; constructor( private readonly editor: ICodeEditor, @@ -111,10 +112,13 @@ export class ReplInputHintContentWidget extends Disposable implements IContentWi hintElement.appendChild(before); - const label = new KeybindingLabel(hintElement, OS); - label.set(keybinding); - label.element.style.width = 'min-content'; - label.element.style.display = 'inline'; + if (this.label) { + this.label.dispose(); + } + this.label = this._register(new KeybindingLabel(hintElement, OS)); + this.label.set(keybinding); + this.label.element.style.width = 'min-content'; + this.label.element.style.display = 'inline'; hintElement.appendChild(after); this.domNode.append(hintElement); @@ -161,5 +165,6 @@ export class ReplInputHintContentWidget extends Disposable implements IContentWi override dispose(): void { super.dispose(); this.editor.removeContentWidget(this); + this.label?.dispose(); } } diff --git a/src/vs/workbench/contrib/mcp/common/mcpServer.ts b/src/vs/workbench/contrib/mcp/common/mcpServer.ts index 43660f303fa4..4a5da51d7b4e 100644 --- a/src/vs/workbench/contrib/mcp/common/mcpServer.ts +++ b/src/vs/workbench/contrib/mcp/common/mcpServer.ts @@ -9,7 +9,7 @@ import * as json from '../../../../base/common/json.js'; import { Disposable, DisposableStore, IDisposable, toDisposable } from '../../../../base/common/lifecycle.js'; import { LRUCache } from '../../../../base/common/map.js'; import { mapValues } from '../../../../base/common/objects.js'; -import { autorun, autorunWithStore, derived, disposableObservableValue, IDerivedReader, IObservable, ITransaction, observableFromEvent, ObservablePromise, observableValue, transaction } from '../../../../base/common/observable.js'; +import { autorun, derived, disposableObservableValue, IDerivedReader, IObservable, ITransaction, observableFromEvent, ObservablePromise, observableValue, transaction } from '../../../../base/common/observable.js'; import { basename } from '../../../../base/common/resources.js'; import { URI } from '../../../../base/common/uri.js'; import { generateUuid } from '../../../../base/common/uuid.js'; @@ -19,6 +19,7 @@ import { IInstantiationService } from '../../../../platform/instantiation/common import { ILogger, ILoggerService } from '../../../../platform/log/common/log.js'; import { INotificationService, IPromptChoice, Severity } from '../../../../platform/notification/common/notification.js'; import { IOpenerService } from '../../../../platform/opener/common/opener.js'; +import { IRemoteAuthorityResolverService } from '../../../../platform/remote/common/remoteAuthorityResolver.js'; import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js'; import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js'; import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js'; @@ -312,6 +313,7 @@ export class McpServer extends Disposable implements IMcpServer { @INotificationService private readonly _notificationService: INotificationService, @IOpenerService private readonly _openerService: IOpenerService, @IMcpSamplingService private readonly _samplingService: IMcpSamplingService, + @IRemoteAuthorityResolverService private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService, ) { super(); @@ -335,24 +337,37 @@ export class McpServer extends Disposable implements IMcpServer { () => workspacesService.getWorkspace().folders, ); - this._register(autorunWithStore(reader => { + const workspacesWithCanonicalURIs = derived(reader => { + const folders = workspaces.read(reader); + return new ObservablePromise((async () => { + let uris = folders.map(f => f.uri); + try { + uris = await Promise.all(uris.map(u => this._remoteAuthorityResolverService.getCanonicalURI(u))); + } catch (error) { + this._logger.error(`Failed to resolve workspace folder URIs: ${error}`); + } + return uris.map((uri, i): MCP.Root => ({ uri: uri.toString(), name: folders[i].name })); + })()); + }).recomputeInitiallyAndOnChange(this._store); + + this._register(autorun(reader => { const cnx = this._connection.read(reader)?.handler.read(reader); if (!cnx) { return; } - cnx.roots = workspaces.read(reader).map(wf => ({ - uri: wf.uri.toString(), - name: wf.name, - })); + const roots = workspacesWithCanonicalURIs.read(reader).promiseResult.read(reader); + if (roots?.data) { + cnx.roots = roots.data; + } })); // 2. Populate this.tools when we connect to a server. - this._register(autorunWithStore((reader, store) => { + this._register(autorun(reader => { const cnx = this._connection.read(reader); const handler = cnx?.handler.read(reader); if (handler) { - this.populateLiveData(handler, cnx?.definition.cacheNonce, store); + this.populateLiveData(handler, cnx?.definition.cacheNonce, reader.store); } else if (this._tools) { this.resetLiveData(); } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookAccessibleView.ts b/src/vs/workbench/contrib/notebook/browser/notebookAccessibleView.ts index 56e6d347e4e2..96ea911c866f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookAccessibleView.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookAccessibleView.ts @@ -24,7 +24,6 @@ export class NotebookAccessibleView implements IAccessibleViewImplementation { } } - export function getAccessibleOutputProvider(editorService: IEditorService) { const activePane = editorService.activeEditorPane; const notebookEditor = getNotebookEditorFromEditorPane(activePane); diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts index ea8227a1a690..813faae93521 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts @@ -6,7 +6,7 @@ import * as DOM from '../../../../../base/browser/dom.js'; import { EventType as TouchEventType } from '../../../../../base/browser/touch.js'; import { CancellationToken } from '../../../../../base/common/cancellation.js'; -import { StandardMouseEvent } from '../../../../../base/browser/mouseEvent.js'; +import { IMouseWheelEvent, StandardMouseEvent } from '../../../../../base/browser/mouseEvent.js'; import { Emitter, Event } from '../../../../../base/common/event.js'; import { Disposable, DisposableStore, type IReference } from '../../../../../base/common/lifecycle.js'; import { MenuId } from '../../../../../platform/actions/common/actions.js'; @@ -164,6 +164,11 @@ export class NotebookStickyScroll extends Disposable { this._register(DOM.addDisposableListener(this.domNode, DOM.EventType.CONTEXT_MENU, async (event: MouseEvent) => { this.onContextMenu(event); })); + + // Forward wheel events to the notebook editor to enable scrolling when hovering over sticky scroll + this._register(DOM.addDisposableListener(this.domNode, DOM.EventType.WHEEL, (event: WheelEvent) => { + this.notebookCellList.triggerScrollFromMouseWheelEvent(event as any as IMouseWheelEvent); + })); } private onContextMenu(e: MouseEvent) { diff --git a/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css b/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css index fe8258a1ce4d..a4f800ab02f4 100644 --- a/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css +++ b/src/vs/workbench/contrib/preferences/browser/media/settingsEditor2.css @@ -60,19 +60,24 @@ top: 0; right: 0; height: 100%; - width: 43px; + width: 44px; } .settings-editor > .settings-header > .search-container.with-ai-toggle > .settings-clear-widget { - width: 62px; + width: 66px; } .settings-editor > .settings-header > .search-container > .settings-clear-widget .action-label { - padding: 2px; + padding: 3px; margin-left: 0px; box-sizing: content-box; } +.settings-editor > .settings-header > .search-container > .settings-clear-widget .action-label.monaco-custom-toggle { + /* To offset the border width. */ + padding: 2.3px; +} + .settings-editor > .settings-header > .settings-header-controls { display: flex; flex-wrap: wrap; diff --git a/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts b/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts index 674ff723e53a..70fa68788124 100644 --- a/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts +++ b/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts @@ -30,7 +30,7 @@ interface IConfiguration extends IWindowsConfiguration { editor?: { accessibilitySupport?: 'on' | 'off' | 'auto' }; security?: { workspace?: { trust?: { enabled?: boolean } }; restrictUNCAccess?: boolean }; window: IWindowSettings; - workbench?: { enableExperiments?: boolean; settings?: { showSuggestions?: boolean } }; + workbench?: { enableExperiments?: boolean; settings?: { showAISearchToggle?: boolean } }; telemetry?: { feedback?: { enabled?: boolean } }; _extensionsGallery?: { enablePPE?: boolean }; accessibility?: { verbosity?: { debug?: boolean } }; @@ -73,7 +73,7 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo private readonly accessibilityVerbosityDebug = new ChangeObserver('boolean'); private readonly useFileStorage = new ChangeObserver('boolean'); private readonly telemetryFeedbackEnabled = new ChangeObserver('boolean'); - private readonly showSuggestions = new ChangeObserver('boolean'); + private readonly showAISearchToggle = new ChangeObserver('boolean'); constructor( @IHostService private readonly hostService: IHostService, @@ -169,7 +169,7 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo processChanged(this.telemetryFeedbackEnabled.handleChange(config.telemetry?.feedback?.enabled)); // Settings editor suggestions - processChanged(this.showSuggestions.handleChange(config.workbench?.settings?.showSuggestions)); + processChanged(this.showAISearchToggle.handleChange(config.workbench?.settings?.showAISearchToggle)); if (askToRelaunch && changed && this.hostService.hasFocus) { this.doConfirm( diff --git a/src/vs/workbench/contrib/replNotebook/browser/repl.contribution.ts b/src/vs/workbench/contrib/replNotebook/browser/repl.contribution.ts index 61e6351ad262..ec41740e8d7e 100644 --- a/src/vs/workbench/contrib/replNotebook/browser/repl.contribution.ts +++ b/src/vs/workbench/contrib/replNotebook/browser/repl.contribution.ts @@ -147,7 +147,7 @@ export class ReplDocumentContribution extends Disposable implements IWorkbenchCo // untitled notebooks are disposed when they get saved. we should not hold a reference // to such a disposed notebook and therefore dispose the reference as well - ref.object.notebook.onWillDispose(() => { + Event.once(ref.object.notebook.onWillDispose)(() => { ref.dispose(); }); const label = (options as INotebookEditorOptions)?.label ?? undefined; diff --git a/src/vs/workbench/contrib/replNotebook/browser/replEditor.ts b/src/vs/workbench/contrib/replNotebook/browser/replEditor.ts index b6ff66566c17..667b9c48d46a 100644 --- a/src/vs/workbench/contrib/replNotebook/browser/replEditor.ts +++ b/src/vs/workbench/contrib/replNotebook/browser/replEditor.ts @@ -485,11 +485,11 @@ export class ReplEditor extends EditorPane implements IEditorPaneWithScrolling { } })); - this._codeEditorWidget.onDidChangeModelDecorations(() => { + this._widgetDisposableStore.add(this._codeEditorWidget.onDidChangeModelDecorations(() => { if (this.isVisible()) { this._updateInputHint(); } - }); + })); const cursorAtBoundaryContext = INTERACTIVE_INPUT_CURSOR_BOUNDARY.bindTo(this._contextKeyService); if (input.resource && input.historyService.has(input.resource)) { diff --git a/src/vs/workbench/contrib/testing/browser/testingDecorations.ts b/src/vs/workbench/contrib/testing/browser/testingDecorations.ts index ac47408247d1..3c3a2f50f359 100644 --- a/src/vs/workbench/contrib/testing/browser/testingDecorations.ts +++ b/src/vs/workbench/contrib/testing/browser/testingDecorations.ts @@ -1367,11 +1367,17 @@ class TestErrorContentWidget extends Disposable implements IContentWidget { super(); const setMarginTop = () => { - const lineHeight = editor.getOption(EditorOption.lineHeight); + const lineHeight = editor.getLineHeightForPosition(position); this.node.root.style.marginTop = (lineHeight - ERROR_CONTENT_WIDGET_HEIGHT) / 2 + 'px'; }; setMarginTop(); + this._register(editor.onDidChangeLineHeight(e => { + if (e.affects(position)) { + setMarginTop(); + } + })); + this._register(editor.onDidChangeConfiguration(e => { if (e.hasChanged(EditorOption.lineHeight)) { setMarginTop(); @@ -1387,10 +1393,10 @@ class TestErrorContentWidget extends Disposable implements IContentWidget { text = lf === -1 ? msg : msg.slice(0, lf); } - this.node.root.addEventListener('click', e => { + this._register(dom.addDisposableListener(this.node.root, dom.EventType.CLICK, e => { this.peekOpener.peekUri(uri); e.preventDefault(); - }); + })); const ctrl = TestingOutputPeekController.get(editor); if (ctrl) { diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts index 2f4b15dc6e36..70d8b2ac1f77 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts @@ -158,6 +158,7 @@ export class GettingStartedPage extends EditorPane { private categoriesSlide!: HTMLElement; private stepsContent!: HTMLElement; private stepMediaComponent!: HTMLElement; + private nextButton!: HTMLButtonElement; private webview!: IWebviewElement; private layoutMarkdown: (() => void) | undefined; @@ -1504,6 +1505,20 @@ export class GettingStartedPage extends EditorPane { prevButton.removeAttribute('tabindex'); } } + + // Update next button text for final slide + if (this.nextButton) { + const isLastSlide = newIndex === steps.length - 1; + const textNode = this.nextButton.firstChild as Text; + if (textNode && textNode.nodeType === Node.TEXT_NODE) { + textNode.textContent = isLastSlide + ? localize('last', "Start coding") + : localize('next', "Next"); + } + this.nextButton.setAttribute('aria-label', isLastSlide + ? localize('lastStep', "Start coding") + : localize('nextStep', "Next")); + } } private buildNewCategorySlide(categoryID: string, selectedStep?: string) { @@ -1653,11 +1668,11 @@ export class GettingStartedPage extends EditorPane { }); // Add next button - const nextButton = $('button.button-link.navigation.next', { + this.nextButton = $('button.button-link.navigation.next', { 'aria-label': localize('nextStep', "Next"), }, localize('next', "Next"), $('span.codicon.codicon-arrow-right')); - navigationContainer.appendChild(nextButton); + navigationContainer.appendChild(this.nextButton); this.detailsPageDisposables.add(addDisposableListener(prevButton, 'click', () => { const currentIndex = this.getCurrentSlideIndex(allSlides); if (currentIndex > 0) { @@ -1665,7 +1680,7 @@ export class GettingStartedPage extends EditorPane { } })); - this.detailsPageDisposables.add(addDisposableListener(nextButton, 'click', () => { + this.detailsPageDisposables.add(addDisposableListener(this.nextButton, 'click', () => { const currentIndex = this.getCurrentSlideIndex(allSlides); if (currentIndex < allSlides.length - 1) { this.selectStepByIndex(currentIndex + 1, allSlides.map(s => s.steps[0]), 1); diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts b/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts index 15600ccb5688..fad3c94a4c5b 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/common/gettingStartedContent.ts @@ -730,16 +730,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ type: 'svg', altText: 'Language extensions', path: 'languages.svg' }, }, - { - id: 'newSettingsAndSync', - title: localize('newgettingStarted.settings.title', "Customize every aspect of VS Code"), - description: localize('newgettingStarted.settingsAndSync.description.interpolated', "[Back up and sync](command:workbench.userDataSync.actions.turnOn) settings across all your devices.\n{0}", Button(localize('tweakSettings', "Open Settings"), 'command:toSide:workbench.action.openSettings')), - when: 'syncStatus != uninitialized', - completionEvents: ['onEvent:sync-enabled'], - media: { - type: 'svg', altText: 'VS Code Settings', path: 'settings.svg' - }, - }, + ] } } diff --git a/src/vs/workbench/test/browser/notificationsList.test.ts b/src/vs/workbench/test/browser/notificationsList.test.ts new file mode 100644 index 000000000000..c975c6533afd --- /dev/null +++ b/src/vs/workbench/test/browser/notificationsList.test.ts @@ -0,0 +1,102 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert from 'assert'; +import { NotificationAccessibilityProvider } from '../../browser/parts/notifications/notificationsList.js'; +import { NotificationViewItem, INotificationsFilter, INotificationViewItem } from '../../common/notifications.js'; +import { Severity, NotificationsFilter } from '../../../platform/notification/common/notification.js'; +import { IKeybindingService } from '../../../platform/keybinding/common/keybinding.js'; +import { IConfigurationService } from '../../../platform/configuration/common/configuration.js'; +import { TestConfigurationService } from '../../../platform/configuration/test/common/testConfigurationService.js'; +import { MockKeybindingService } from '../../../platform/keybinding/test/common/mockKeybindingService.js'; +import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../base/test/common/utils.js'; + +suite('NotificationsList AccessibilityProvider', () => { + + const noFilter: INotificationsFilter = { global: NotificationsFilter.OFF, sources: new Map() }; + let configurationService: IConfigurationService; + let keybindingService: IKeybindingService; + let accessibilityProvider: NotificationAccessibilityProvider; + const createdNotifications: INotificationViewItem[] = []; + + setup(() => { + configurationService = new TestConfigurationService(); + keybindingService = new MockKeybindingService(); + accessibilityProvider = new NotificationAccessibilityProvider({}, keybindingService, configurationService); + }); + + teardown(() => { + // Close all created notifications to prevent disposable leaks + for (const notification of createdNotifications) { + notification.close(); + } + createdNotifications.length = 0; + }); + + ensureNoDisposablesAreLeakedInTestSuite(); + + test('getAriaLabel includes severity prefix for Error notifications', () => { + const notification = NotificationViewItem.create({ severity: Severity.Error, message: 'Something went wrong' }, noFilter)!; + createdNotifications.push(notification); + const ariaLabel = accessibilityProvider.getAriaLabel(notification); + + assert.ok(ariaLabel.startsWith('Error: '), `Expected aria label to start with "Error: ", but got: ${ariaLabel}`); + assert.ok(ariaLabel.includes('Something went wrong'), 'Expected aria label to include original message'); + assert.ok(ariaLabel.includes('notification'), 'Expected aria label to include "notification"'); + }); + + test('getAriaLabel includes severity prefix for Warning notifications', () => { + const notification = NotificationViewItem.create({ severity: Severity.Warning, message: 'This is a warning' }, noFilter)!; + createdNotifications.push(notification); + const ariaLabel = accessibilityProvider.getAriaLabel(notification); + + assert.ok(ariaLabel.startsWith('Warning: '), `Expected aria label to start with "Warning: ", but got: ${ariaLabel}`); + assert.ok(ariaLabel.includes('This is a warning'), 'Expected aria label to include original message'); + assert.ok(ariaLabel.includes('notification'), 'Expected aria label to include "notification"'); + }); + + test('getAriaLabel includes severity prefix for Info notifications', () => { + const notification = NotificationViewItem.create({ severity: Severity.Info, message: 'Information message' }, noFilter)!; + createdNotifications.push(notification); + const ariaLabel = accessibilityProvider.getAriaLabel(notification); + + assert.ok(ariaLabel.startsWith('Info: '), `Expected aria label to start with "Info: ", but got: ${ariaLabel}`); + assert.ok(ariaLabel.includes('Information message'), 'Expected aria label to include original message'); + assert.ok(ariaLabel.includes('notification'), 'Expected aria label to include "notification"'); + }); + + test('getAriaLabel includes source when present', () => { + const notification = NotificationViewItem.create({ + severity: Severity.Error, + message: 'Error with source', + source: 'TestExtension' + }, noFilter)!; + createdNotifications.push(notification); + const ariaLabel = accessibilityProvider.getAriaLabel(notification); + + assert.ok(ariaLabel.startsWith('Error: '), 'Expected aria label to start with severity prefix'); + assert.ok(ariaLabel.includes('Error with source'), 'Expected aria label to include original message'); + assert.ok(ariaLabel.includes('source: TestExtension'), 'Expected aria label to include source information'); + assert.ok(ariaLabel.includes('notification'), 'Expected aria label to include "notification"'); + }); + + test('severity prefix consistency', () => { + // Test that the severity prefixes are consistent with the ARIA alerts + const errorNotification = NotificationViewItem.create({ severity: Severity.Error, message: 'Error message' }, noFilter)!; + const warningNotification = NotificationViewItem.create({ severity: Severity.Warning, message: 'Warning message' }, noFilter)!; + const infoNotification = NotificationViewItem.create({ severity: Severity.Info, message: 'Info message' }, noFilter)!; + + createdNotifications.push(errorNotification, warningNotification, infoNotification); + + const errorLabel = accessibilityProvider.getAriaLabel(errorNotification); + const warningLabel = accessibilityProvider.getAriaLabel(warningNotification); + const infoLabel = accessibilityProvider.getAriaLabel(infoNotification); + + // Check that each severity type gets the correct prefix + assert.ok(errorLabel.includes('Error: Error message'), 'Error notifications should have Error prefix'); + assert.ok(warningLabel.includes('Warning: Warning message'), 'Warning notifications should have Warning prefix'); + assert.ok(infoLabel.includes('Info: Info message'), 'Info notifications should have Info prefix'); + }); +}); diff --git a/src/vscode-dts/vscode.proposed.chatProvider.d.ts b/src/vscode-dts/vscode.proposed.chatProvider.d.ts index 59d832a1faa7..47eb21e54f9e 100644 --- a/src/vscode-dts/vscode.proposed.chatProvider.d.ts +++ b/src/vscode-dts/vscode.proposed.chatProvider.d.ts @@ -5,10 +5,6 @@ declare module 'vscode' { - export interface ChatResponseFragment2 { - index: number; - part: LanguageModelTextPart | LanguageModelToolCallPart; - } // @API extension ship a d.ts files for their options @@ -16,6 +12,38 @@ declare module 'vscode' { // concrete models. The `provideLanguageModelChatData` would do the discovery and auth dances and later // the model data is passed to the concrete function for making a requested or counting token + + // TODO@API name scheme + export interface LanguageModelChatResponseOptions { + + // initiator + readonly extensionId: string; + + /** + * A set of options that control the behavior of the language model. These options are specific to the language model + * and need to be looked up in the respective documentation. + */ + readonly modelOptions: { [name: string]: any }; + + /** + * An optional list of tools that are available to the language model. These could be registered tools available via + * {@link lm.tools}, or private tools that are just implemented within the calling extension. + * + * If the LLM requests to call one of these tools, it will return a {@link LanguageModelToolCallPart} in + * {@link LanguageModelChatResponse.stream}. It's the caller's responsibility to invoke the tool. If it's a tool + * registered in {@link lm.tools}, that means calling {@link lm.invokeTool}. + * + * Then, the tool result can be provided to the LLM by creating an Assistant-type {@link LanguageModelChatMessage} with a + * {@link LanguageModelToolCallPart}, followed by a User-type message with a {@link LanguageModelToolResultPart}. + */ + tools?: LanguageModelChatTool[]; + + /** + * The tool-selecting mode to use. {@link LanguageModelChatToolMode.Auto} by default. + */ + toolMode?: LanguageModelChatToolMode; + } + export interface LanguageModelChatData { // like ChatResponseProviderMetadata } @@ -24,11 +52,19 @@ declare module 'vscode' { provideLanguageModelChatData(options: { force: boolean }, token: CancellationToken): ProviderResult; - provideResponse(model: LanguageModelChatData, messages: Array, options: LanguageModelChatRequestOptions, extensionId: string, progress: Progress, token: CancellationToken): Thenable; + provideResponse(model: LanguageModelChatData, messages: Array, options: LanguageModelChatResponseOptions, progress: Progress, token: CancellationToken): Thenable; provideTokenCount(model: LanguageModelChatData, text: string | LanguageModelChatMessage | LanguageModelChatMessage2, token: CancellationToken): Thenable; } + + + export interface ChatResponseFragment2 { + index: number; + part: LanguageModelTextPart | LanguageModelToolCallPart; + } + + /** * Represents a large language model that accepts ChatML messages and produces a streaming response */ @@ -37,6 +73,8 @@ declare module 'vscode' { // TODO@API remove or keep proposed? onDidReceiveLanguageModelResponse2?: Event<{ readonly extensionId: string; readonly participant?: string; readonly tokenCount?: number }>; + // TODO@API + // have dedicated options, don't reuse the LanguageModelChatRequestOptions so that consumer and provider part of the API can develop independently provideLanguageModelResponse(messages: Array, options: LanguageModelChatRequestOptions, extensionId: string, progress: Progress, token: CancellationToken): Thenable; provideTokenCount(text: string | LanguageModelChatMessage | LanguageModelChatMessage2, token: CancellationToken): Thenable; @@ -88,10 +126,18 @@ declare module 'vscode' { // TODO@API maybe an enum, LanguageModelChatProviderPickerAvailability? readonly isDefault?: boolean; readonly isUserSelectable?: boolean; + readonly capabilities?: { readonly vision?: boolean; + + // TODO@API should be `boolean | number` so extensions can express how many tools they support readonly toolCalling?: boolean; + + // TODO@API WHY is agentMode a capability? This seems wrong? readonly agentMode?: boolean; + + // TODO@API support prompt TSX style messages + // readonly promptTsx?:boolean }; /** @@ -105,6 +151,7 @@ declare module 'vscode' { export interface ChatResponseProviderMetadata { // limit this provider to some extensions + // TODO@API remove? unused? extensions?: string[]; }