app
Pup - the AI's own browser
Public Made by Adomby adom
pup gives your AI a real browser on your desktop that it drives completely, in the background, signed in as you: windows that never jump in front of your work, one shared profile that learns your logins, and every window labeled on the taskbar with its AI thread's name.
← Commit history
identity in-process via koffi (win32.js); no-wiggle skill documents the final mechanism
4 files changed
+643−174
dev-skills/pup-no-wiggle/SKILL.md+13@@ -92,6 +92,19 @@ NOT the identity signal. The set-diff ("windows-after minus windows-before under the mutex") is the OLD birth capture and is DELETED — it could not disambiguate simultaneous births and refused. Do not bring it back. +### How it is implemented now (v2.0.313+): in-process, zero ab calls, zero PowerShell++`src/win32.js` binds user32 through **koffi** (prebuilt FFI, installed by AD's `npm install` on+spawn, no build step). Birth: `findChromeWindowByTitle(token)` polls EnumWindows + GetWindowText+every 50ms (2.5s cap) for the unique `PUPBIRTH-<seq>-<rand>` token, then the caller runs+`win32.setProp(hwnd, "AdomPupSid=<sessionId>")` the instant it knows the sessionId (measured:+match in ~130ms, tag 6ms later). Recovery: `findWindowByProp(name)` is one EnumWindows + GetProp+sweep. The 30s visibility sweep (`fixHiddenOrOffscreen`) is in-process too. PowerShell survives+only as the fallback when koffi fails to load (`/status` reports `win32.inProcess`). John's rule:+"i frown upon running powershell scripts cuz they're heavy and slow" - do not add new ones.+`desktop_enum_windows` is never used for identity; it remains only as the cached geometry snapshot+the periodic sweeps read (45s TTL when every session is resolved).+ ### Re-finding a window (runtime, and after a restart) - **Fast path:** the in-memory hwnd, validated with `hwndBelongsToPup` before use.
src/package-lock.json+443−171@@ -1,18 +1,19 @@ { "name": "adom-puppeteer-bridge",- "version": "1.9.291",+ "version": "2.0.248", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "adom-puppeteer-bridge",- "version": "1.9.291",+ "version": "2.0.248", "dependencies": {+ "koffi": "^3.1.6", "puppeteer": "^24.43.1" }, "optionalDependencies": { "keytar": "^7.9.0",- "sharp": "^0.34.5"+ "sharp": "^0.35.0" } }, "node_modules/@babel/code-frame": {@@ -39,10 +40,9 @@ } }, "node_modules/@emnapi/runtime": {- "version": "1.9.0",- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.0.tgz",- "integrity": "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==",- "license": "MIT",+ "version": "1.11.3",+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",+ "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", "optional": true, "dependencies": { "tslib": "^2.4.0"@@ -59,57 +59,72 @@ } }, "node_modules/@img/sharp-darwin-arm64": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",- "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz",+ "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", "cpu": [ "arm64" ],- "license": "Apache-2.0", "optional": true, "os": [ "darwin" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": {- "@img/sharp-libvips-darwin-arm64": "1.2.4"+ "@img/sharp-libvips-darwin-arm64": "1.3.2" } }, "node_modules/@img/sharp-darwin-x64": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",- "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz",+ "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", "cpu": [ "x64" ],- "license": "Apache-2.0", "optional": true, "os": [ "darwin" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": {- "@img/sharp-libvips-darwin-x64": "1.2.4"+ "@img/sharp-libvips-darwin-x64": "1.3.2"+ }+ },+ "node_modules/@img/sharp-freebsd-wasm32": {+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz",+ "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==",+ "optional": true,+ "os": [+ "freebsd"+ ],+ "dependencies": {+ "@img/sharp-wasm32": "0.35.3"+ },+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-libvips-darwin-arm64": {- "version": "1.2.4",- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",- "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",+ "version": "1.3.2",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz",+ "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", "cpu": [ "arm64" ],- "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin"@@ -119,13 +134,12 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": {- "version": "1.2.4",- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",- "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",+ "version": "1.3.2",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz",+ "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", "cpu": [ "x64" ],- "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin"@@ -135,13 +149,12 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": {- "version": "1.2.4",- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",- "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",+ "version": "1.3.2",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz",+ "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", "cpu": [ "arm" ],- "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux"@@ -151,13 +164,12 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": {- "version": "1.2.4",- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",- "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",+ "version": "1.3.2",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz",+ "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", "cpu": [ "arm64" ],- "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux"@@ -167,13 +179,12 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": {- "version": "1.2.4",- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",- "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",+ "version": "1.3.2",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz",+ "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", "cpu": [ "ppc64" ],- "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux"@@ -183,13 +194,12 @@ } }, "node_modules/@img/sharp-libvips-linux-riscv64": {- "version": "1.2.4",- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",- "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",+ "version": "1.3.2",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz",+ "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", "cpu": [ "riscv64" ],- "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux"@@ -199,13 +209,12 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": {- "version": "1.2.4",- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",- "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",+ "version": "1.3.2",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz",+ "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", "cpu": [ "s390x" ],- "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux"@@ -215,13 +224,12 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": {- "version": "1.2.4",- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",- "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",+ "version": "1.3.2",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz",+ "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", "cpu": [ "x64" ],- "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux"@@ -231,13 +239,12 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": {- "version": "1.2.4",- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",- "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",+ "version": "1.3.2",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz",+ "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", "cpu": [ "arm64" ],- "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux"@@ -247,13 +254,12 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": {- "version": "1.2.4",- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",- "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",+ "version": "1.3.2",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz",+ "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", "cpu": [ "x64" ],- "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux"@@ -263,257 +269,485 @@ } }, "node_modules/@img/sharp-linux-arm": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",- "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz",+ "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", "cpu": [ "arm" ],- "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": {- "@img/sharp-libvips-linux-arm": "1.2.4"+ "@img/sharp-libvips-linux-arm": "1.3.2" } }, "node_modules/@img/sharp-linux-arm64": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",- "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz",+ "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", "cpu": [ "arm64" ],- "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": {- "@img/sharp-libvips-linux-arm64": "1.2.4"+ "@img/sharp-libvips-linux-arm64": "1.3.2" } }, "node_modules/@img/sharp-linux-ppc64": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",- "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz",+ "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", "cpu": [ "ppc64" ],- "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": {- "@img/sharp-libvips-linux-ppc64": "1.2.4"+ "@img/sharp-libvips-linux-ppc64": "1.3.2" } }, "node_modules/@img/sharp-linux-riscv64": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",- "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz",+ "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", "cpu": [ "riscv64" ],- "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": {- "@img/sharp-libvips-linux-riscv64": "1.2.4"+ "@img/sharp-libvips-linux-riscv64": "1.3.2" } }, "node_modules/@img/sharp-linux-s390x": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",- "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz",+ "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", "cpu": [ "s390x" ],- "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": {- "@img/sharp-libvips-linux-s390x": "1.2.4"+ "@img/sharp-libvips-linux-s390x": "1.3.2" } }, "node_modules/@img/sharp-linux-x64": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",- "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz",+ "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", "cpu": [ "x64" ],- "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": {- "@img/sharp-libvips-linux-x64": "1.2.4"+ "@img/sharp-libvips-linux-x64": "1.3.2" } }, "node_modules/@img/sharp-linuxmusl-arm64": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",- "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz",+ "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", "cpu": [ "arm64" ],- "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": {- "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" } }, "node_modules/@img/sharp-linuxmusl-x64": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",- "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz",+ "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", "cpu": [ "x64" ],- "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": {- "@img/sharp-libvips-linuxmusl-x64": "1.2.4"+ "@img/sharp-libvips-linuxmusl-x64": "1.3.2" } }, "node_modules/@img/sharp-wasm32": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",- "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz",+ "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==",+ "optional": true,+ "dependencies": {+ "@emnapi/runtime": "^1.11.1"+ },+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-webcontainers-wasm32": {+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz",+ "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", "cpu": [ "wasm32" ],- "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": {- "@emnapi/runtime": "^1.7.0"+ "@img/sharp-wasm32": "0.35.3" }, "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-arm64": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",- "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz",+ "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", "cpu": [ "arm64" ],- "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-ia32": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",- "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz",+ "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", "cpu": [ "ia32" ],- "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": "^20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-x64": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",- "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz",+ "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", "cpu": [ "x64" ],- "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } },+ "node_modules/@koromix/koffi-darwin-arm64": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-darwin-arm64/-/koffi-darwin-arm64-3.1.6.tgz",+ "integrity": "sha512-8FHyXGCZN7/iQf4f7W5BRysmtdlAFvSx6FpmX4u6wmkZiX/2e9hIRdGLiZYlHGudlcA18UmXB/cMiyhJ7fJkzA==",+ "cpu": [+ "arm64"+ ],+ "optional": true,+ "os": [+ "darwin"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-darwin-x64": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-darwin-x64/-/koffi-darwin-x64-3.1.6.tgz",+ "integrity": "sha512-uzx/jqFQuSHqgg1zaRidTBTCfj8Y9M0SDTO8HeoI9s9fJhiJ1mbB9TTwJO5c2hiMnuWg2m1byczC8BaIH6cG/w==",+ "cpu": [+ "x64"+ ],+ "optional": true,+ "os": [+ "darwin"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-freebsd-arm64": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-freebsd-arm64/-/koffi-freebsd-arm64-3.1.6.tgz",+ "integrity": "sha512-PjpTVrsCK5YTtixOw7VsseYXJOyoY6k0qBt+bf0T9h3wyV06y73rALsorFDDEoYpLUBZO7R6EIMs6CpUrEkNTQ==",+ "cpu": [+ "arm64"+ ],+ "optional": true,+ "os": [+ "freebsd"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-freebsd-ia32": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-freebsd-ia32/-/koffi-freebsd-ia32-3.1.6.tgz",+ "integrity": "sha512-ETYwL820HtFwYoOVzgyvmFmzTHRo9DJtGYTxa5Nb7ajaa5ldCum0jbmUJ3PMECxFTLxD5Q6PYZ8Xbp101bGeSg==",+ "cpu": [+ "ia32"+ ],+ "optional": true,+ "os": [+ "freebsd"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-freebsd-x64": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-freebsd-x64/-/koffi-freebsd-x64-3.1.6.tgz",+ "integrity": "sha512-BkqxkNXhAAT9toU2stvLwx1iKHPDx7h08NCICyBbjYEXkCAEr84igTkpE5V3XJ9xZZ2gKll7VvdhxorHtHUqZw==",+ "cpu": [+ "x64"+ ],+ "optional": true,+ "os": [+ "freebsd"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-linux-arm64": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-linux-arm64/-/koffi-linux-arm64-3.1.6.tgz",+ "integrity": "sha512-cM4XPm9ljbCrcPgXjzFYjDNxDUvvuR7TCYaEoo1AKjwZT/vmWhu2xN3pomfbsHh6aVn80SFA3enufQnaETW1rQ==",+ "cpu": [+ "arm64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-linux-ia32": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-linux-ia32/-/koffi-linux-ia32-3.1.6.tgz",+ "integrity": "sha512-l1SVTpO10iaQt8slbowJpzK4fbwQZ7ufj9tmCyAcIwWUpyAbPS83mJMctU72If6N9/gCS2wuRqwnYB2uPLLhLg==",+ "cpu": [+ "ia32"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-linux-loong64": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-linux-loong64/-/koffi-linux-loong64-3.1.6.tgz",+ "integrity": "sha512-KpTJpMSbIdCVFU26ynt0xy4x15h+y6AwPJxj2+iVxJhCzJf4oisCPc0YH2VnutuLV2nVzSrFm7sL/WSOqPgkXw==",+ "cpu": [+ "loong64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-linux-riscv64": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-linux-riscv64/-/koffi-linux-riscv64-3.1.6.tgz",+ "integrity": "sha512-YdFNpsywnXiYOYQlDAatf7TJLnspbGXdmfwIZhf82kbKSflYUsq4tI6NmoUOzM89oIWDGpYqd4Hz3xL7tsyXsw==",+ "cpu": [+ "riscv64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-linux-x64": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-linux-x64/-/koffi-linux-x64-3.1.6.tgz",+ "integrity": "sha512-Xx5mpr9VcaMCXfvbqIiLIWIL9Iuu6F4r3iMXg7+zZCqYUFZPFwJgiDQBLxctHv2OYgIfAoaaHMW0GC1cJkHfbA==",+ "cpu": [+ "x64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-openbsd-ia32": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-openbsd-ia32/-/koffi-openbsd-ia32-3.1.6.tgz",+ "integrity": "sha512-39Np4QTxhTlTT6RRveIeP+TnbzrwuDJ0UMyHxEZ+oGtzmb9GqWhl9T1oyehG6v/O+c4BffafG2NwLkCZ7tDKWw==",+ "cpu": [+ "ia32"+ ],+ "optional": true,+ "os": [+ "openbsd"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-openbsd-x64": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-openbsd-x64/-/koffi-openbsd-x64-3.1.6.tgz",+ "integrity": "sha512-3EynGn3ycQRqaMWGmUJ0tdtuQdStByqSy/tJ0ZGKWizbMGdFAE73YpgLsyd8BDvwnKWytVG/OLNb5nDHpfd9Dg==",+ "cpu": [+ "x64"+ ],+ "optional": true,+ "os": [+ "openbsd"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-win32-arm64": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-win32-arm64/-/koffi-win32-arm64-3.1.6.tgz",+ "integrity": "sha512-27FdPPRtT4xbO9bsd2OZa95M5YQ7bcJ8QjCRO57UUMI21REfkDegjqKwqo/CFlugxXlJf5IYtG2rq4BEYIrvxg==",+ "cpu": [+ "arm64"+ ],+ "optional": true,+ "os": [+ "win32"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-win32-ia32": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-win32-ia32/-/koffi-win32-ia32-3.1.6.tgz",+ "integrity": "sha512-5mVelLKVDup4eoxZOpCzCyMPxoctsg+Qe4J9O5BP4KbBEdqoOEqaNEBBRgNzXcdr2g+GGfmIUo+oVR1NvIdiJw==",+ "cpu": [+ "ia32"+ ],+ "optional": true,+ "os": [+ "win32"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ },+ "node_modules/@koromix/koffi-win32-x64": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/@koromix/koffi-win32-x64/-/koffi-win32-x64-3.1.6.tgz",+ "integrity": "sha512-lPKjAaHz0aoiZXT/wDVqH+joR5y3lCZj1s9Bk5qx/DGRq+0MK8Ib8VoqiBOrJ69NG5AsJSvn0tQDcSqfRgLmBQ==",+ "cpu": [+ "x64"+ ],+ "optional": true,+ "os": [+ "win32"+ ],+ "funding": {+ "url": "https://liberapay.com/Koromix"+ }+ }, "node_modules/@puppeteer/browsers": { "version": "2.13.2", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.13.2.tgz",@@ -1190,9 +1424,9 @@ "optional": true }, "node_modules/ip-address": {- "version": "10.2.0",- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",- "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",+ "version": "10.5.0",+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.5.0.tgz",+ "integrity": "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==", "engines": { "node": ">= 12" }@@ -1218,10 +1452,19 @@ "license": "MIT" }, "node_modules/js-yaml": {- "version": "4.1.1",- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",- "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",- "license": "MIT",+ "version": "4.3.1",+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz",+ "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==",+ "funding": [+ {+ "type": "github",+ "url": "https://github.com/sponsors/puzrin"+ },+ {+ "type": "github",+ "url": "https://github.com/sponsors/nodeca"+ }+ ], "dependencies": { "argparse": "^2.0.1" },@@ -1247,6 +1490,32 @@ "prebuild-install": "^7.0.1" } },+ "node_modules/koffi": {+ "version": "3.1.6",+ "resolved": "https://registry.npmjs.org/koffi/-/koffi-3.1.6.tgz",+ "integrity": "sha512-ln60chEb3o7Du1ayjwl6BFiNN1wZK+3cTM2wWGiHLEzCY/FdTIN1ER5VWDwHq7J/j4tSnnrHaH5ABS1EO6+6ag==",+ "hasInstallScript": true,+ "funding": {+ "url": "https://liberapay.com/Koromix"+ },+ "optionalDependencies": {+ "@koromix/koffi-darwin-arm64": "3.1.6",+ "@koromix/koffi-darwin-x64": "3.1.6",+ "@koromix/koffi-freebsd-arm64": "3.1.6",+ "@koromix/koffi-freebsd-ia32": "3.1.6",+ "@koromix/koffi-freebsd-x64": "3.1.6",+ "@koromix/koffi-linux-arm64": "3.1.6",+ "@koromix/koffi-linux-ia32": "3.1.6",+ "@koromix/koffi-linux-loong64": "3.1.6",+ "@koromix/koffi-linux-riscv64": "3.1.6",+ "@koromix/koffi-linux-x64": "3.1.6",+ "@koromix/koffi-openbsd-ia32": "3.1.6",+ "@koromix/koffi-openbsd-x64": "3.1.6",+ "@koromix/koffi-win32-arm64": "3.1.6",+ "@koromix/koffi-win32-ia32": "3.1.6",+ "@koromix/koffi-win32-x64": "3.1.6"+ }+ }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",@@ -1622,10 +1891,9 @@ "optional": true }, "node_modules/semver": {- "version": "7.7.4",- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",- "license": "ISC",+ "version": "7.8.5",+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "bin": { "semver": "bin/semver.js" },@@ -1634,48 +1902,52 @@ } }, "node_modules/sharp": {- "version": "0.34.5",- "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",- "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",- "hasInstallScript": true,- "license": "Apache-2.0",+ "version": "0.35.3",+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz",+ "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", "optional": true, "dependencies": {- "@img/colour": "^1.0.0",+ "@img/colour": "^1.1.0", "detect-libc": "^2.1.2",- "semver": "^7.7.3"+ "semver": "^7.8.5" }, "engines": {- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"+ "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": {- "@img/sharp-darwin-arm64": "0.34.5",- "@img/sharp-darwin-x64": "0.34.5",- "@img/sharp-libvips-darwin-arm64": "1.2.4",- "@img/sharp-libvips-darwin-x64": "1.2.4",- "@img/sharp-libvips-linux-arm": "1.2.4",- "@img/sharp-libvips-linux-arm64": "1.2.4",- "@img/sharp-libvips-linux-ppc64": "1.2.4",- "@img/sharp-libvips-linux-riscv64": "1.2.4",- "@img/sharp-libvips-linux-s390x": "1.2.4",- "@img/sharp-libvips-linux-x64": "1.2.4",- "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",- "@img/sharp-libvips-linuxmusl-x64": "1.2.4",- "@img/sharp-linux-arm": "0.34.5",- "@img/sharp-linux-arm64": "0.34.5",- "@img/sharp-linux-ppc64": "0.34.5",- "@img/sharp-linux-riscv64": "0.34.5",- "@img/sharp-linux-s390x": "0.34.5",- "@img/sharp-linux-x64": "0.34.5",- "@img/sharp-linuxmusl-arm64": "0.34.5",- "@img/sharp-linuxmusl-x64": "0.34.5",- "@img/sharp-wasm32": "0.34.5",- "@img/sharp-win32-arm64": "0.34.5",- "@img/sharp-win32-ia32": "0.34.5",- "@img/sharp-win32-x64": "0.34.5"+ "@img/sharp-darwin-arm64": "0.35.3",+ "@img/sharp-darwin-x64": "0.35.3",+ "@img/sharp-freebsd-wasm32": "0.35.3",+ "@img/sharp-libvips-darwin-arm64": "1.3.2",+ "@img/sharp-libvips-darwin-x64": "1.3.2",+ "@img/sharp-libvips-linux-arm": "1.3.2",+ "@img/sharp-libvips-linux-arm64": "1.3.2",+ "@img/sharp-libvips-linux-ppc64": "1.3.2",+ "@img/sharp-libvips-linux-riscv64": "1.3.2",+ "@img/sharp-libvips-linux-s390x": "1.3.2",+ "@img/sharp-libvips-linux-x64": "1.3.2",+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.2",+ "@img/sharp-libvips-linuxmusl-x64": "1.3.2",+ "@img/sharp-linux-arm": "0.35.3",+ "@img/sharp-linux-arm64": "0.35.3",+ "@img/sharp-linux-ppc64": "0.35.3",+ "@img/sharp-linux-riscv64": "0.35.3",+ "@img/sharp-linux-s390x": "0.35.3",+ "@img/sharp-linux-x64": "0.35.3",+ "@img/sharp-linuxmusl-arm64": "0.35.3",+ "@img/sharp-linuxmusl-x64": "0.35.3",+ "@img/sharp-webcontainers-wasm32": "0.35.3",+ "@img/sharp-win32-arm64": "0.35.3",+ "@img/sharp-win32-ia32": "0.35.3",+ "@img/sharp-win32-x64": "0.35.3"+ },+ "peerDependenciesMeta": {+ "@types/node": {+ "optional": true+ } } }, "node_modules/simple-concat": {
src/package.json+13−3@@ -1,16 +1,26 @@ { "name": "adom-puppeteer-bridge",- "version": "1.9.291",+ "version": "2.0.248", "description": "Puppeteer Bridge \u2014 persistent browser instance for visual debugging via Adom Desktop", "main": "server.js", "scripts": { "start": "node server.js" }, "dependencies": {- "puppeteer": "^24.43.1"+ "puppeteer": "^24.43.1",+ "koffi": "^3.1.6" }, "optionalDependencies": { "keytar": "^7.9.0",- "sharp": "^0.34.5"+ "sharp": "^0.35.0"+ },+ "overrides": {+ "js-yaml": "^4.3.1",+ "ip-address": "^10.3.1"+ },+ "_securityNotes": {+ "why": "adom/pup-bridge#57 (dependabot). sharp is ours (optional dep) so it is bumped directly; js-yaml (via cosmiconfig) and ip-address (via socks) are TRANSITIVE under puppeteer, so they are pinned with overrides rather than by forking the tree.",+ "extract-zip": "GHSA-jmr9-qjv8-65gv has NO patched release upstream. It reaches us only through @puppeteer/browsers, which uses it to unpack the Chrome-for-Testing archive that pup itself downloads from Google's CDN over HTTPS \u2014 never user-supplied or third-party zips \u2014 so the symlink-traversal path is not reachable in this bridge. Re-evaluate if that ever changes.",+ "reviewed": "2026-08-19" } }
src/win32.jsadded+174@@ -0,0 +1,174 @@+'use strict';+// In-process Win32 calls for window identity (v2.0.310). John: "i frown upon running powershell+// scripts cuz they're heavy and slow." Every PowerShell spawn cost a process + an Add-Type compile+// (hundreds of ms). These are direct user32 calls through koffi (prebuilt FFI, no build step): a+// SetProp or a full EnumWindows+GetProp sweep is microseconds, synchronous, and leaves no trace in+// ab's activity log. Identity doctrine (dev-skills/pup-no-wiggle): the window PROPERTY is the id.+//+// Every export degrades to null/false when koffi is unavailable (non-Windows, or the module failed+// to install), so callers can fall back to the PowerShell path and nothing hard-fails.++let user32 = null;+let fn = null;+let loadError = null;++function load() {+ if (fn || loadError) return !!fn;+ if (process.platform !== 'win32') { loadError = 'not win32'; return false; }+ try {+ const koffi = require('koffi');+ user32 = koffi.load('user32.dll');+ const EnumProc = koffi.proto('bool __stdcall PupEnumProc(intptr_t hwnd, intptr_t lparam)');+ fn = {+ koffi,+ SetPropW: user32.func('bool __stdcall SetPropW(intptr_t hwnd, const char16_t* name, intptr_t data)'),+ GetPropW: user32.func('intptr_t __stdcall GetPropW(intptr_t hwnd, const char16_t* name)'),+ RemovePropW: user32.func('intptr_t __stdcall RemovePropW(intptr_t hwnd, const char16_t* name)'),+ EnumWindows: user32.func('bool __stdcall EnumWindows(PupEnumProc* cb, intptr_t lparam)'),+ IsWindow: user32.func('bool __stdcall IsWindow(intptr_t hwnd)'),+ GetWindowThreadProcessId: user32.func('uint32_t __stdcall GetWindowThreadProcessId(intptr_t hwnd, _Out_ uint32_t* pid)'),+ GetWindowTextW: user32.func('int __stdcall GetWindowTextW(intptr_t hwnd, void* buf, int n)'),+ GetClassNameW: user32.func('int __stdcall GetClassNameW(intptr_t hwnd, void* buf, int n)'),+ IsWindowVisible: user32.func('bool __stdcall IsWindowVisible(intptr_t hwnd)'),+ IsIconic: user32.func('bool __stdcall IsIconic(intptr_t hwnd)'),+ ShowWindow: user32.func('bool __stdcall ShowWindow(intptr_t hwnd, int cmd)'),+ GetWindowLongW: user32.func('int32_t __stdcall GetWindowLongW(intptr_t hwnd, int idx)'),+ GetSystemMetrics: user32.func('int __stdcall GetSystemMetrics(int idx)'),+ SetWindowPos: user32.func('bool __stdcall SetWindowPos(intptr_t hwnd, intptr_t after, int x, int y, int cx, int cy, uint32_t flags)'),+ GetWindowRect: user32.func('bool __stdcall GetWindowRect(intptr_t hwnd, void* rect)'),+ GetWindowPlacement: user32.func('bool __stdcall GetWindowPlacement(intptr_t hwnd, void* wp)'),+ EnumProc,+ };+ return true;+ } catch (e) { loadError = e && e.message ? e.message : String(e); fn = null; return false; }+}++// Tag a window with a named property (value 1). The property lives with the window, in Chrome's+// process, so it outlives pup restarts. Returns true on success, null when koffi is unavailable.+function setProp(hwnd, name) {+ if (!load()) return null;+ try { return !!fn.SetPropW(Number(hwnd), String(name), 1); } catch (e) { return false; }+}++function hasProp(hwnd, name) {+ if (!load()) return null;+ try { return Number(fn.GetPropW(Number(hwnd), String(name))) !== 0; } catch (e) { return false; }+}++function removeProp(hwnd, name) {+ if (!load()) return null;+ try { fn.RemovePropW(Number(hwnd), String(name)); return true; } catch (e) { return false; }+}++function isWindow(hwnd) {+ if (!load()) return null;+ try { return !!fn.IsWindow(Number(hwnd)); } catch (e) { return false; }+}++function windowPid(hwnd) {+ if (!load()) return null;+ try { const out = [0]; fn.GetWindowThreadProcessId(Number(hwnd), out); return Number(out[0]) || null; } catch (e) { return null; }+}++// Find the ONE top-level window carrying the property. Only pup ever sets these names, so no class+// or geometry test is needed: the property IS the proof. Returns the hwnd, 0 when none, null when+// koffi is unavailable.+function findWindowByProp(name) {+ if (!load()) return null;+ let found = 0;+ const cb = fn.koffi.register((hwnd) => {+ try { if (Number(fn.GetPropW(Number(hwnd), String(name))) !== 0) { found = Number(hwnd); return false; } } catch (e) {}+ return true;+ }, fn.koffi.pointer(fn.EnumProc));+ try { fn.EnumWindows(cb, 0); } catch (e) {} finally { try { fn.koffi.unregister(cb); } catch (e) {} }+ return found;+}++// Rebuild the whole sessionId -> hwnd map in one sweep: every top-level window whose property+// name starts with the prefix. Used at recovery so a restart never enumerates more than once.+function findAllByPropPrefix(prefix, candidates) {+ // Win32 has no "list my props by prefix" without EnumPropsEx; callers pass the sessionIds they+ // want resolved (cheap: one GetProp per (window, sessionId) pair, all in-process).+ if (!load()) return null;+ const out = new Map();+ const names = candidates.map(s => [s, prefix + s]);+ const cb = fn.koffi.register((hwnd) => {+ for (const [sid, nm] of names) {+ try { if (!out.has(sid) && Number(fn.GetPropW(Number(hwnd), nm)) !== 0) { out.set(sid, Number(hwnd)); break; } } catch (e) {}+ }+ return out.size < names.length;+ }, fn.koffi.pointer(fn.EnumProc));+ try { fn.EnumWindows(cb, 0); } catch (e) {} finally { try { fn.koffi.unregister(cb); } catch (e) {} }+ return out;+}++// UTF-16 out-buffers: pass a Buffer as the void* and decode exactly the returned length.+function windowText(hwnd) {+ if (!load()) return null;+ try { const buf = Buffer.alloc(1024); const n = fn.GetWindowTextW(Number(hwnd), buf, 512); return n > 0 ? buf.toString('utf16le', 0, n * 2) : ''; } catch (e) { return ''; }+}+function className(hwnd) {+ if (!load()) return null;+ try { const buf = Buffer.alloc(256); const n = fn.GetClassNameW(Number(hwnd), buf, 128); return n > 0 ? buf.toString('utf16le', 0, n * 2) : ''; } catch (e) { return ''; }+}+// Find the top-level Chrome frame whose title contains `token` (the unique birth title). Returns+// {hwnd, pid} or null when none; undefined when koffi is unavailable. One in-process pass.+function findChromeWindowByTitle(token) {+ if (!load()) return undefined;+ let hit = null;+ const cb = fn.koffi.register((hwnd) => {+ try {+ if (className(hwnd) !== 'Chrome_WidgetWin_1') return true;+ const t = windowText(hwnd);+ if (t && t.includes(token)) { hit = { hwnd: Number(hwnd), pid: windowPid(hwnd) }; return false; }+ } catch (e) {}+ return true;+ }, fn.koffi.pointer(fn.EnumProc));+ try { fn.EnumWindows(cb, 0); } catch (e) {} finally { try { fn.koffi.unregister(cb); } catch (e) {} }+ return hit;+}+function windowRect(hwnd) {+ if (!load()) return null;+ try { const b = Buffer.alloc(16); if (!fn.GetWindowRect(Number(hwnd), b)) return null; return { L: b.readInt32LE(0), T: b.readInt32LE(4), R: b.readInt32LE(8), B: b.readInt32LE(12) }; } catch (e) { return null; }+}+// The restore rect from WINDOWPLACEMENT (a minimized window reports the -32000 placeholder from+// GetWindowRect, so position must be judged from the placement's rcNormalPosition).+function normalRect(hwnd) {+ if (!load()) return null;+ try { const b = Buffer.alloc(44); b.writeInt32LE(44, 0); if (!fn.GetWindowPlacement(Number(hwnd), b)) return null; return { L: b.readInt32LE(28), T: b.readInt32LE(32), R: b.readInt32LE(36), B: b.readInt32LE(40) }; } catch (e) { return null; }+}+// The visibility invariant, in-process (v2.0.314; was one PowerShell + Add-Type per 30s sweep): no+// titled, captioned top-level window of a pup-owned Chrome process may be HIDDEN or OFF-SCREEN.+// Hidden -> SW_SHOWNOACTIVATE. Off the virtual desktop -> moved back at (vx+10, vy+10) without+// activation or z-change. Minimized is the user's choice and is left alone. Returns repair records.+function fixHiddenOrOffscreen(pids) {+ if (!load()) return null;+ const pidSet = new Set(pids.map(Number));+ const out = [];+ const vx = fn.GetSystemMetrics(76), vy = fn.GetSystemMetrics(77), vw = fn.GetSystemMetrics(78), vh = fn.GetSystemMetrics(79);+ const cb = fn.koffi.register((hwnd) => {+ try {+ const h = Number(hwnd);+ if (!pidSet.has(windowPid(h))) return true;+ if ((fn.GetWindowLongW(h, -16) & 0x00C00000) === 0) return true; // WS_CAPTION: real windows only+ const title = windowText(h); if (!title) return true;+ if (!fn.IsWindowVisible(h)) { fn.ShowWindow(h, 4); out.push({ kind: fn.IsWindowVisible(h) ? 'RESHOWN' : 'RESHOW-FAILED', hwnd: h, title }); return true; }+ if (fn.IsIconic(h)) return true;+ const r = normalRect(h); if (!r) return true;+ const L = r.L, T = r.T, W = r.R - r.L, H = r.B - r.T;+ if (L < vx + vw && L + W > vx && T < vy + vh && T + H > vy) return true; // overlaps the desktop: fine+ const nw = (W > 200 && W <= vw) ? W : (vw - 20), nh = (H > 200 && H <= vh) ? H : (vh - 20);+ fn.SetWindowPos(h, 0, vx + 10, vy + 10, nw, nh, 0x14); // NOACTIVATE | NOZORDER+ const c = windowRect(h);+ const fixedNow = !!(c && c.L < vx + vw && c.R > vx && c.T < vy + vh && c.B > vy);+ out.push({ kind: fixedNow ? 'MOVED-ONSCREEN' : 'MOVE-FAILED', hwnd: h, title });+ } catch (e) {}+ return true;+ }, fn.koffi.pointer(fn.EnumProc));+ try { fn.EnumWindows(cb, 0); } catch (e) {} finally { try { fn.koffi.unregister(cb); } catch (e) {} }+ return out;+}+function available() { return load(); }+function why() { return loadError; }++module.exports = { available, why, setProp, hasProp, removeProp, isWindow, windowPid, windowText, className, findWindowByProp, findAllByPropPrefix, findChromeWindowByTitle, windowRect, normalRect, fixHiddenOrOffscreen };