diff --git a/README.demo.md b/README.demo.md index ab6d0ca3..575135ab 100644 --- a/README.demo.md +++ b/README.demo.md @@ -4,7 +4,7 @@ The Brainy interactive demo showcases the library's features in a web browser. F ## Prerequisites -- Make sure you have Node.js installed (version 24.3.0 or higher) +- Make sure you have Node.js installed (version 24.4.0 or higher) - Ensure the project is built (run both `npm run build` and `npm run build:browser`) ## Running the Demo diff --git a/README.md b/README.md index e57bf234..2c125afb 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) -[![Node.js](https://img.shields.io/badge/node-%3E%3D24.3.0-brightgreen.svg)](https://nodejs.org/) +[![Node.js](https://img.shields.io/badge/node-%3E%3D24.4.0-brightgreen.svg)](https://nodejs.org/) [![TypeScript](https://img.shields.io/badge/TypeScript-5.4.5-blue.svg)](https://www.typescriptlang.org/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) [![npm](https://img.shields.io/badge/npm-v0.10.0-blue.svg)](https://www.npmjs.com/package/@soulcraft/brainy) @@ -1246,10 +1246,6 @@ terabyte-scale data that can't fit entirely in memory, we provide several approa For detailed information on how to scale Brainy for large datasets, see our comprehensive [Scaling Strategy](scalingStrategy.md) document. -## Requirements - -- Node.js >= 24.3.0 - ## Contributing For detailed contribution guidelines, please see [CONTRIBUTING.md](CONTRIBUTING.md). diff --git a/cli-package/README.md b/cli-package/README.md index b94d9c44..f1c1d7f8 100644 --- a/cli-package/README.md +++ b/cli-package/README.md @@ -47,7 +47,7 @@ brainy generate-random-graph --noun-count 20 --verb-count 30 --clear ## Requirements -- Node.js >= 24.3.0 +- Node.js >= 24.4.0 ## License diff --git a/cli-package/brainy-wrapper.js b/cli-package/brainy-wrapper.js index 5bc00563..b9bb914a 100755 --- a/cli-package/brainy-wrapper.js +++ b/cli-package/brainy-wrapper.js @@ -18,10 +18,25 @@ if ( // Define a PlatformNode class that uses the global TextEncoder/TextDecoder directly class PlatformNode { constructor() { - // Create a util object (empty but kept for compatibility) - this.util = {} + // Create a util object with necessary methods + this.util = { + // Add isFloat32Array and isTypedArray directly to util + isFloat32Array: (arr) => { + return !!( + arr instanceof Float32Array || + (arr && + Object.prototype.toString.call(arr) === '[object Float32Array]') + ) + }, + isTypedArray: (arr) => { + return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView)) + }, + // Use native TextEncoder and TextDecoder + TextEncoder: TextEncoder, + TextDecoder: TextDecoder + } - // Initialize TextEncoder/TextDecoder instances directly from global + // Initialize TextEncoder/TextDecoder instances this.textEncoder = new TextEncoder() this.textDecoder = new TextDecoder() } @@ -46,6 +61,30 @@ if ( // Also create an instance and assign it to global.platformNode (lowercase p) global.platformNode = new PlatformNode() + + // Ensure global.util exists and has the necessary methods + // This is needed because TensorFlow.js might look for these methods in global.util + if (!global.util) { + global.util = {} + } + + // Add isFloat32Array method if it doesn't exist + if (!global.util.isFloat32Array) { + global.util.isFloat32Array = (arr) => { + return !!( + arr instanceof Float32Array || + (arr && + Object.prototype.toString.call(arr) === '[object Float32Array]') + ) + } + } + + // Add isTypedArray method if it doesn't exist + if (!global.util.isTypedArray) { + global.util.isTypedArray = (arr) => { + return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView)) + } + } } catch (error) { console.warn('Failed to define global PlatformNode class:', error) } diff --git a/cli-package/package-lock.json b/cli-package/package-lock.json index e3b1e9d0..4c976d44 100644 --- a/cli-package/package-lock.json +++ b/cli-package/package-lock.json @@ -1,16 +1,16 @@ { "name": "@soulcraft/brainy-cli", - "version": "0.9.37", + "version": "0.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@soulcraft/brainy-cli", - "version": "0.9.37", + "version": "0.10.0", "hasInstallScript": true, "license": "MIT", "dependencies": { - "@soulcraft/brainy": "0.9.37", + "@soulcraft/brainy": "0.10.0", "commander": "^14.0.0", "omelette": "^0.4.17" }, @@ -29,7 +29,7 @@ "typescript": "^5.4.5" }, "engines": { - "node": ">=24.3.0" + "node": ">=24.4.0" } }, "node_modules/@aws-crypto/crc32": { @@ -235,64 +235,64 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.842.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.842.0.tgz", - "integrity": "sha512-T5Rh72Rcq1xIaM8KkTr1Wpr7/WPCYO++KrM+/Em0rq2jxpjMMhj77ITpgH7eEmNxWmwIndTwqpgfmbpNfk7Gbw==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.844.0.tgz", + "integrity": "sha512-Yhp8+U4KFVQqL6phZ5yrHF5PdCvKWbYtLSS+egAfAW+N5w78amhbZcctervj59uqOZHMGDWXuDBklN+7eVfasg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.840.0", - "@aws-sdk/credential-provider-node": "3.840.0", + "@aws-sdk/core": "3.844.0", + "@aws-sdk/credential-provider-node": "3.844.0", "@aws-sdk/middleware-bucket-endpoint": "3.840.0", "@aws-sdk/middleware-expect-continue": "3.840.0", - "@aws-sdk/middleware-flexible-checksums": "3.840.0", + "@aws-sdk/middleware-flexible-checksums": "3.844.0", "@aws-sdk/middleware-host-header": "3.840.0", "@aws-sdk/middleware-location-constraint": "3.840.0", "@aws-sdk/middleware-logger": "3.840.0", "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-sdk-s3": "3.840.0", + "@aws-sdk/middleware-sdk-s3": "3.844.0", "@aws-sdk/middleware-ssec": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.844.0", "@aws-sdk/region-config-resolver": "3.840.0", - "@aws-sdk/signature-v4-multi-region": "3.840.0", + "@aws-sdk/signature-v4-multi-region": "3.844.0", "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", + "@aws-sdk/util-endpoints": "3.844.0", "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.844.0", "@aws-sdk/xml-builder": "3.821.0", "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.6.0", + "@smithy/core": "^3.7.0", "@smithy/eventstream-serde-browser": "^4.0.4", "@smithy/eventstream-serde-config-resolver": "^4.1.2", "@smithy/eventstream-serde-node": "^4.0.4", - "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/fetch-http-handler": "^5.1.0", "@smithy/hash-blob-browser": "^4.0.4", "@smithy/hash-node": "^4.0.4", "@smithy/hash-stream-node": "^4.0.4", "@smithy/invalid-dependency": "^4.0.4", "@smithy/md5-js": "^4.0.4", "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.13", - "@smithy/middleware-retry": "^4.1.14", + "@smithy/middleware-endpoint": "^4.1.14", + "@smithy/middleware-retry": "^4.1.15", "@smithy/middleware-serde": "^4.0.8", "@smithy/middleware-stack": "^4.0.4", "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", + "@smithy/node-http-handler": "^4.1.0", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.21", - "@smithy/util-defaults-mode-node": "^4.0.21", + "@smithy/util-defaults-mode-browser": "^4.0.22", + "@smithy/util-defaults-mode-node": "^4.0.22", "@smithy/util-endpoints": "^3.0.6", "@smithy/util-middleware": "^4.0.4", "@smithy/util-retry": "^4.0.6", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "@smithy/util-utf8": "^4.0.0", "@smithy/util-waiter": "^4.0.6", "@types/uuid": "^9.0.1", @@ -304,44 +304,44 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.840.0.tgz", - "integrity": "sha512-3Zp+FWN2hhmKdpS0Ragi5V2ZPsZNScE3jlbgoJjzjI/roHZqO+e3/+XFN4TlM0DsPKYJNp+1TAjmhxN6rOnfYA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.844.0.tgz", + "integrity": "sha512-FktodSx+pfUfIqMjoNwZ6t1xqq/G3cfT7I4JJ0HKHoIIZdoCHQB52x0OzKDtHDJAnEQPInasdPS8PorZBZtHmg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/middleware-host-header": "3.840.0", "@aws-sdk/middleware-logger": "3.840.0", "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.844.0", "@aws-sdk/region-config-resolver": "3.840.0", "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", + "@aws-sdk/util-endpoints": "3.844.0", "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.844.0", "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.6.0", - "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/core": "^3.7.0", + "@smithy/fetch-http-handler": "^5.1.0", "@smithy/hash-node": "^4.0.4", "@smithy/invalid-dependency": "^4.0.4", "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.13", - "@smithy/middleware-retry": "^4.1.14", + "@smithy/middleware-endpoint": "^4.1.14", + "@smithy/middleware-retry": "^4.1.15", "@smithy/middleware-serde": "^4.0.8", "@smithy/middleware-stack": "^4.0.4", "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", + "@smithy/node-http-handler": "^4.1.0", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.21", - "@smithy/util-defaults-mode-node": "^4.0.21", + "@smithy/util-defaults-mode-browser": "^4.0.22", + "@smithy/util-defaults-mode-node": "^4.0.22", "@smithy/util-endpoints": "^3.0.6", "@smithy/util-middleware": "^4.0.4", "@smithy/util-retry": "^4.0.6", @@ -353,25 +353,25 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.840.0.tgz", - "integrity": "sha512-x3Zgb39tF1h2XpU+yA4OAAQlW6LVEfXNlSedSYJ7HGKXqA/E9h3rWQVpYfhXXVVsLdYXdNw5KBUkoAoruoZSZA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.844.0.tgz", + "integrity": "sha512-pfpI54bG5Xf2NkqrDBC2REStXlDXNCw/whORhkEs+Tp5exU872D5QKguzjPA6hH+8Pvbq1qgt5zXMbduISTHJw==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.840.0", "@aws-sdk/xml-builder": "3.821.0", - "@smithy/core": "^3.6.0", + "@smithy/core": "^3.7.0", "@smithy/node-config-provider": "^4.1.3", "@smithy/property-provider": "^4.0.4", "@smithy/protocol-http": "^5.1.2", "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-middleware": "^4.0.4", "@smithy/util-utf8": "^4.0.0", - "fast-xml-parser": "4.4.1", + "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" }, "engines": { @@ -379,12 +379,12 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.840.0.tgz", - "integrity": "sha512-EzF6VcJK7XvQ/G15AVEfJzN2mNXU8fcVpXo4bRyr1S6t2q5zx6UPH/XjDbn18xyUmOq01t+r8gG+TmHEVo18fA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.844.0.tgz", + "integrity": "sha512-WB94Ox86MqcZ4CnRjKgopzaSuZH4hMP0GqdOxG4s1it1lRWOIPOHOC1dPiM0Zbj1uqITIhbXUQVXyP/uaJeNkw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/property-provider": "^4.0.4", "@smithy/types": "^4.3.1", @@ -395,20 +395,20 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.840.0.tgz", - "integrity": "sha512-wbnUiPGLVea6mXbUh04fu+VJmGkQvmToPeTYdHE8eRZq3NRDi3t3WltT+jArLBKD/4NppRpMjf2ju4coMCz91g==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.844.0.tgz", + "integrity": "sha512-e+efVqfkhpM8zxYeiLNgTUlX+tmtXzVm3bw1A02U9Z9cWBHyQNb8pi90M7QniLoqRURY1B0C2JqkOE61gd4KNg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/node-http-handler": "^4.0.6", + "@smithy/fetch-http-handler": "^5.1.0", + "@smithy/node-http-handler": "^4.1.0", "@smithy/property-provider": "^4.0.4", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "tslib": "^2.6.2" }, "engines": { @@ -416,18 +416,18 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.840.0.tgz", - "integrity": "sha512-7F290BsWydShHb+7InXd+IjJc3mlEIm9I0R57F/Pjl1xZB69MdkhVGCnuETWoBt4g53ktJd6NEjzm/iAhFXFmw==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.844.0.tgz", + "integrity": "sha512-jc5ArGz2HfAx5QPXD+Ep36+QWyCKzl2TG6Vtl87/vljfLhVD0gEHv8fRsqWEp3Rc6hVfKnCjLW5ayR2HYcow9w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/credential-provider-env": "3.840.0", - "@aws-sdk/credential-provider-http": "3.840.0", - "@aws-sdk/credential-provider-process": "3.840.0", - "@aws-sdk/credential-provider-sso": "3.840.0", - "@aws-sdk/credential-provider-web-identity": "3.840.0", - "@aws-sdk/nested-clients": "3.840.0", + "@aws-sdk/core": "3.844.0", + "@aws-sdk/credential-provider-env": "3.844.0", + "@aws-sdk/credential-provider-http": "3.844.0", + "@aws-sdk/credential-provider-process": "3.844.0", + "@aws-sdk/credential-provider-sso": "3.844.0", + "@aws-sdk/credential-provider-web-identity": "3.844.0", + "@aws-sdk/nested-clients": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/credential-provider-imds": "^4.0.6", "@smithy/property-provider": "^4.0.4", @@ -440,17 +440,17 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.840.0.tgz", - "integrity": "sha512-KufP8JnxA31wxklLm63evUPSFApGcH8X86z3mv9SRbpCm5ycgWIGVCTXpTOdgq6rPZrwT9pftzv2/b4mV/9clg==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.844.0.tgz", + "integrity": "sha512-pUqB0StTNyW0R03XjTA3wrQZcie/7FJKSXlYHue921ZXuhLOZpzyDkLNfdRsZTcEoYYWVPSmyS+Eu/g5yVsBNA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.840.0", - "@aws-sdk/credential-provider-http": "3.840.0", - "@aws-sdk/credential-provider-ini": "3.840.0", - "@aws-sdk/credential-provider-process": "3.840.0", - "@aws-sdk/credential-provider-sso": "3.840.0", - "@aws-sdk/credential-provider-web-identity": "3.840.0", + "@aws-sdk/credential-provider-env": "3.844.0", + "@aws-sdk/credential-provider-http": "3.844.0", + "@aws-sdk/credential-provider-ini": "3.844.0", + "@aws-sdk/credential-provider-process": "3.844.0", + "@aws-sdk/credential-provider-sso": "3.844.0", + "@aws-sdk/credential-provider-web-identity": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/credential-provider-imds": "^4.0.6", "@smithy/property-provider": "^4.0.4", @@ -463,12 +463,12 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.840.0.tgz", - "integrity": "sha512-HkDQWHy8tCI4A0Ps2NVtuVYMv9cB4y/IuD/TdOsqeRIAT12h8jDb98BwQPNLAImAOwOWzZJ8Cu0xtSpX7CQhMw==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.844.0.tgz", + "integrity": "sha512-VCI8XvIDt2WBfk5Gi/wXKPcWTS3OkAbovB66oKcNQalllH8ESDg4SfLNhchdnN8A5sDGj6tIBJ19nk+dQ6GaqQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/property-provider": "^4.0.4", "@smithy/shared-ini-file-loader": "^4.0.4", @@ -480,14 +480,14 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.840.0.tgz", - "integrity": "sha512-2qgdtdd6R0Z1y0KL8gzzwFUGmhBHSUx4zy85L2XV1CXhpRNwV71SVWJqLDVV5RVWVf9mg50Pm3AWrUC0xb0pcA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.844.0.tgz", + "integrity": "sha512-UNp/uWufGlb5nWa4dpc6uQnDOB/9ysJJFG95ACowNVL9XWfi1LJO7teKrqNkVhq0CzSJS1tCt3FvX4UfM+aN1g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.840.0", - "@aws-sdk/core": "3.840.0", - "@aws-sdk/token-providers": "3.840.0", + "@aws-sdk/client-sso": "3.844.0", + "@aws-sdk/core": "3.844.0", + "@aws-sdk/token-providers": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/property-provider": "^4.0.4", "@smithy/shared-ini-file-loader": "^4.0.4", @@ -499,13 +499,13 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.840.0.tgz", - "integrity": "sha512-dpEeVXG8uNZSmVXReE4WP0lwoioX2gstk4RnUgrdUE3YaPq8A+hJiVAyc3h+cjDeIqfbsQbZm9qFetKC2LF9dQ==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.844.0.tgz", + "integrity": "sha512-iDmX4pPmatjttIScdspZRagaFnCjpHZIEEwTyKdXxUaU0iAOSXF8ecrCEvutETvImPOC86xdrq+MPacJOnMzUA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/nested-clients": "3.840.0", + "@aws-sdk/core": "3.844.0", + "@aws-sdk/nested-clients": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/property-provider": "^4.0.4", "@smithy/types": "^4.3.1", @@ -549,22 +549,22 @@ } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.840.0.tgz", - "integrity": "sha512-Kg/o2G6o72sdoRH0J+avdcf668gM1bp6O4VeEXpXwUj/urQnV5qiB2q1EYT110INHUKWOLXPND3sQAqh6sTqHw==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.844.0.tgz", + "integrity": "sha512-LCImZd1hpM0cegfdpgZyK6x4on4Ky+c9XCFURfE4wil1J9HXf6OP4KsfHQwt1yIkMEbFqvd/ab2I5fmp7S7aFA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", "@aws-crypto/util": "5.2.0", - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/is-array-buffer": "^4.0.0", "@smithy/node-config-provider": "^4.1.3", "@smithy/protocol-http": "^5.1.2", "@smithy/types": "^4.3.1", "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -631,23 +631,23 @@ } }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.840.0.tgz", - "integrity": "sha512-rOUji7CayWN3O09zvvgLzDVQe0HiJdZkxoTS6vzOS3WbbdT7joGdVtAJHtn+x776QT3hHzbKU5gnfhel0o6gQA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.844.0.tgz", + "integrity": "sha512-vOD5reqZszXBWMbZFN3EUar203o2i8gcoTdrymY4GMsAPDsh0k8yd3VJRNPuxT/017tP6G+rQepOGzna4umung==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", "@aws-sdk/util-arn-parser": "3.804.0", - "@smithy/core": "^3.6.0", + "@smithy/core": "^3.7.0", "@smithy/node-config-provider": "^4.1.3", "@smithy/protocol-http": "^5.1.2", "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/util-config-provider": "^4.0.0", "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -670,15 +670,15 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.840.0.tgz", - "integrity": "sha512-hiiMf7BP5ZkAFAvWRcK67Mw/g55ar7OCrvrynC92hunx/xhMkrgSLM0EXIZ1oTn3uql9kH/qqGF0nqsK6K555A==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.844.0.tgz", + "integrity": "sha512-SIbDNUL6ZYXPj5Tk0qEz05sW9kNS1Gl3/wNWEmH+AuUACipkyIeKKWzD6z5433MllETh73vtka/JQF3g7AuZww==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", - "@smithy/core": "^3.6.0", + "@aws-sdk/util-endpoints": "3.844.0", + "@smithy/core": "^3.7.0", "@smithy/protocol-http": "^5.1.2", "@smithy/types": "^4.3.1", "tslib": "^2.6.2" @@ -688,44 +688,44 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.840.0.tgz", - "integrity": "sha512-LXYYo9+n4hRqnRSIMXLBb+BLz+cEmjMtTudwK1BF6Bn2RfdDv29KuyeDRrPCS3TwKl7ZKmXUmE9n5UuHAPfBpA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.844.0.tgz", + "integrity": "sha512-p2XILWc7AcevUSpBg2VtQrk79eWQC4q2JsCSY7HxKpFLZB4mMOfmiTyYkR1gEA6AttK/wpCOtfz+hi1/+z2V1A==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/middleware-host-header": "3.840.0", "@aws-sdk/middleware-logger": "3.840.0", "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.844.0", "@aws-sdk/region-config-resolver": "3.840.0", "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", + "@aws-sdk/util-endpoints": "3.844.0", "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.844.0", "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.6.0", - "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/core": "^3.7.0", + "@smithy/fetch-http-handler": "^5.1.0", "@smithy/hash-node": "^4.0.4", "@smithy/invalid-dependency": "^4.0.4", "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.13", - "@smithy/middleware-retry": "^4.1.14", + "@smithy/middleware-endpoint": "^4.1.14", + "@smithy/middleware-retry": "^4.1.15", "@smithy/middleware-serde": "^4.0.8", "@smithy/middleware-stack": "^4.0.4", "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", + "@smithy/node-http-handler": "^4.1.0", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.21", - "@smithy/util-defaults-mode-node": "^4.0.21", + "@smithy/util-defaults-mode-browser": "^4.0.22", + "@smithy/util-defaults-mode-node": "^4.0.22", "@smithy/util-endpoints": "^3.0.6", "@smithy/util-middleware": "^4.0.4", "@smithy/util-retry": "^4.0.6", @@ -754,12 +754,12 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.840.0.tgz", - "integrity": "sha512-8AoVgHrkSfhvGPtwx23hIUO4MmMnux2pjnso1lrLZGqxfElM6jm2w4jTNLlNXk8uKHGyX89HaAIuT0lL6dJj9g==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.844.0.tgz", + "integrity": "sha512-QC8nocQcZ3Bj7vTnuL47iNhcuUjMC46E2L85mU+sPQo3LN2qBVGSOTF+xSWGvmSFDpkN4ZXUMVeA0cJoJFEDFA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.840.0", + "@aws-sdk/middleware-sdk-s3": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/protocol-http": "^5.1.2", "@smithy/signature-v4": "^5.1.2", @@ -771,13 +771,13 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.840.0.tgz", - "integrity": "sha512-6BuTOLTXvmgwjK7ve7aTg9JaWFdM5UoMolLVPMyh3wTv9Ufalh8oklxYHUBIxsKkBGO2WiHXytveuxH6tAgTYg==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.844.0.tgz", + "integrity": "sha512-Kh728FEny0fil+LeH8U1offPJCTd/EDh8liBAvLtViLHt2WoX2xC8rk98D38Q5p79aIUhHb3Pf4n9IZfTu/Kog==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/nested-clients": "3.840.0", + "@aws-sdk/core": "3.844.0", + "@aws-sdk/nested-clients": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/property-provider": "^4.0.4", "@smithy/shared-ini-file-loader": "^4.0.4", @@ -814,13 +814,14 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.840.0.tgz", - "integrity": "sha512-eqE9ROdg/Kk0rj3poutyRCFauPDXIf/WSvCqFiRDDVi6QOnCv/M0g2XW8/jSvkJlOyaXkNCptapIp6BeeFFGYw==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.844.0.tgz", + "integrity": "sha512-1DHh0WTUmxlysz3EereHKtKoxVUG9UC5BsfAw6Bm4/6qDlJiqtY3oa2vebkYN23yltKdfsCK65cwnBRU59mWVg==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.840.0", "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", "@smithy/util-endpoints": "^3.0.6", "tslib": "^2.6.2" }, @@ -853,12 +854,12 @@ } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.840.0.tgz", - "integrity": "sha512-Fy5JUEDQU1tPm2Yw/YqRYYc27W5+QD/J4mYvQvdWjUGZLB5q3eLFMGD35Uc28ZFoGMufPr4OCxK/bRfWROBRHQ==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.844.0.tgz", + "integrity": "sha512-0eTpURp9Gxbyyeqr78ogARZMSWS5KUMZuN+XMHxNpQLmn2S+J3g+MAyoklCcwhKXlbdQq2aMULEiy0mqIWytuw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/node-config-provider": "^4.1.3", "@smithy/types": "^4.3.1", @@ -1087,9 +1088,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz", - "integrity": "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.2.tgz", + "integrity": "sha512-g0dF8P1e2QYPOj1gu7s/3LVP6kze9A7m6x0BZ9iTdXK8N5c2V7cpBKHV3/9A4Zd8xxavdhK0t4PnqjkqVmUc9Q==", "cpu": [ "arm" ], @@ -1101,9 +1102,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz", - "integrity": "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.2.tgz", + "integrity": "sha512-Yt5MKrOosSbSaAK5Y4J+vSiID57sOvpBNBR6K7xAaQvk3MkcNVV0f9fE20T+41WYN8hDn6SGFlFrKudtx4EoxA==", "cpu": [ "arm64" ], @@ -1115,9 +1116,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz", - "integrity": "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.2.tgz", + "integrity": "sha512-EsnFot9ZieM35YNA26nhbLTJBHD0jTwWpPwmRVDzjylQT6gkar+zenfb8mHxWpRrbn+WytRRjE0WKsfaxBkVUA==", "cpu": [ "arm64" ], @@ -1129,9 +1130,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz", - "integrity": "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.2.tgz", + "integrity": "sha512-dv/t1t1RkCvJdWWxQ2lWOO+b7cMsVw5YFaS04oHpZRWehI1h0fV1gF4wgGCTyQHHjJDfbNpwOi6PXEafRBBezw==", "cpu": [ "x64" ], @@ -1143,9 +1144,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz", - "integrity": "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.2.tgz", + "integrity": "sha512-W4tt4BLorKND4qeHElxDoim0+BsprFTwb+vriVQnFFtT/P6v/xO5I99xvYnVzKWrK6j7Hb0yp3x7V5LUbaeOMg==", "cpu": [ "arm64" ], @@ -1157,9 +1158,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz", - "integrity": "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.2.tgz", + "integrity": "sha512-tdT1PHopokkuBVyHjvYehnIe20fxibxFCEhQP/96MDSOcyjM/shlTkZZLOufV3qO6/FQOSiJTBebhVc12JyPTA==", "cpu": [ "x64" ], @@ -1171,9 +1172,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz", - "integrity": "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.2.tgz", + "integrity": "sha512-+xmiDGGaSfIIOXMzkhJ++Oa0Gwvl9oXUeIiwarsdRXSe27HUIvjbSIpPxvnNsRebsNdUo7uAiQVgBD1hVriwSQ==", "cpu": [ "arm" ], @@ -1185,9 +1186,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz", - "integrity": "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.2.tgz", + "integrity": "sha512-bDHvhzOfORk3wt8yxIra8N4k/N0MnKInCW5OGZaeDYa/hMrdPaJzo7CSkjKZqX4JFUWjUGm88lI6QJLCM7lDrA==", "cpu": [ "arm" ], @@ -1199,9 +1200,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz", - "integrity": "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.2.tgz", + "integrity": "sha512-NMsDEsDiYghTbeZWEGnNi4F0hSbGnsuOG+VnNvxkKg0IGDvFh7UVpM/14mnMwxRxUf9AdAVJgHPvKXf6FpMB7A==", "cpu": [ "arm64" ], @@ -1213,9 +1214,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz", - "integrity": "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.2.tgz", + "integrity": "sha512-lb5bxXnxXglVq+7imxykIp5xMq+idehfl+wOgiiix0191av84OqbjUED+PRC5OA8eFJYj5xAGcpAZ0pF2MnW+A==", "cpu": [ "arm64" ], @@ -1227,9 +1228,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz", - "integrity": "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.2.tgz", + "integrity": "sha512-Yl5Rdpf9pIc4GW1PmkUGHdMtbx0fBLE1//SxDmuf3X0dUC57+zMepow2LK0V21661cjXdTn8hO2tXDdAWAqE5g==", "cpu": [ "loong64" ], @@ -1241,9 +1242,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz", - "integrity": "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.2.tgz", + "integrity": "sha512-03vUDH+w55s680YYryyr78jsO1RWU9ocRMaeV2vMniJJW/6HhoTBwyyiiTPVHNWLnhsnwcQ0oH3S9JSBEKuyqw==", "cpu": [ "ppc64" ], @@ -1255,9 +1256,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz", - "integrity": "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.2.tgz", + "integrity": "sha512-iYtAqBg5eEMG4dEfVlkqo05xMOk6y/JXIToRca2bAWuqjrJYJlx/I7+Z+4hSrsWU8GdJDFPL4ktV3dy4yBSrzg==", "cpu": [ "riscv64" ], @@ -1269,9 +1270,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz", - "integrity": "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.2.tgz", + "integrity": "sha512-e6vEbgaaqz2yEHqtkPXa28fFuBGmUJ0N2dOJK8YUfijejInt9gfCSA7YDdJ4nYlv67JfP3+PSWFX4IVw/xRIPg==", "cpu": [ "riscv64" ], @@ -1283,9 +1284,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz", - "integrity": "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.2.tgz", + "integrity": "sha512-evFOtkmVdY3udE+0QKrV5wBx7bKI0iHz5yEVx5WqDJkxp9YQefy4Mpx3RajIVcM6o7jxTvVd/qpC1IXUhGc1Mw==", "cpu": [ "s390x" ], @@ -1297,9 +1298,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz", - "integrity": "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.2.tgz", + "integrity": "sha512-/bXb0bEsWMyEkIsUL2Yt5nFB5naLAwyOWMEviQfQY1x3l5WsLKgvZf66TM7UTfED6erckUVUJQ/jJ1FSpm3pRQ==", "cpu": [ "x64" ], @@ -1311,9 +1312,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz", - "integrity": "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.2.tgz", + "integrity": "sha512-3D3OB1vSSBXmkGEZR27uiMRNiwN08/RVAcBKwhUYPaiZ8bcvdeEwWPvbnXvvXHY+A/7xluzcN+kaiOFNiOZwWg==", "cpu": [ "x64" ], @@ -1325,9 +1326,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz", - "integrity": "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.2.tgz", + "integrity": "sha512-VfU0fsMK+rwdK8mwODqYeM2hDrF2WiHaSmCBrS7gColkQft95/8tphyzv2EupVxn3iE0FI78wzffoULH1G+dkw==", "cpu": [ "arm64" ], @@ -1339,9 +1340,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz", - "integrity": "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.2.tgz", + "integrity": "sha512-+qMUrkbUurpE6DVRjiJCNGZBGo9xM4Y0FXU5cjgudWqIBWbcLkjE3XprJUsOFgC6xjBClwVa9k6O3A7K3vxb5Q==", "cpu": [ "ia32" ], @@ -1353,9 +1354,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz", - "integrity": "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.2.tgz", + "integrity": "sha512-3+QZROYfJ25PDcxFF66UEk8jGWigHJeecZILvkPkyQN7oc5BvFo4YEXFkOs154j3FTMp9mn9Ky8RCOwastduEA==", "cpu": [ "x64" ], @@ -1421,9 +1422,9 @@ } }, "node_modules/@smithy/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.6.0.tgz", - "integrity": "sha512-Pgvfb+TQ4wUNLyHzvgCP4aYZMh16y7GcfF59oirRHcgGgkH1e/s9C0nv/v3WP+Quymyr5je71HeFQCwh+44XLg==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.7.0.tgz", + "integrity": "sha512-7ov8hu/4j0uPZv8b27oeOFtIBtlFmM3ibrPv/Omx1uUdoXvcpJ00U+H/OWWC/keAguLlcqwtyL2/jTlSnApgNQ==", "license": "Apache-2.0", "dependencies": { "@smithy/middleware-serde": "^4.0.8", @@ -1432,7 +1433,7 @@ "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -1527,9 +1528,9 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.4.tgz", - "integrity": "sha512-AMtBR5pHppYMVD7z7G+OlHHAcgAN7v0kVKEpHuTO4Gb199Gowh0taYi9oDStFeUhetkeP55JLSVlTW1n9rFtUw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.0.tgz", + "integrity": "sha512-mADw7MS0bYe2OGKkHYMaqarOXuDwRbO6ArD91XhHcl2ynjGCFF+hvqf0LyQcYxkA1zaWjefSkU7Ne9mqgApSgQ==", "license": "Apache-2.0", "dependencies": { "@smithy/protocol-http": "^5.1.2", @@ -1640,12 +1641,12 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.13.tgz", - "integrity": "sha512-xg3EHV/Q5ZdAO5b0UiIMj3RIOCobuS40pBBODguUDVdko6YK6QIzCVRrHTogVuEKglBWqWenRnZ71iZnLL3ZAQ==", + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.14.tgz", + "integrity": "sha512-+BGLpK5D93gCcSEceaaYhUD/+OCGXM1IDaq/jKUQ+ujB0PTWlWN85noodKw/IPFZhIKFCNEe19PGd/reUMeLSQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.6.0", + "@smithy/core": "^3.7.0", "@smithy/middleware-serde": "^4.0.8", "@smithy/node-config-provider": "^4.1.3", "@smithy/shared-ini-file-loader": "^4.0.4", @@ -1659,15 +1660,15 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.14.tgz", - "integrity": "sha512-eoXaLlDGpKvdmvt+YBfRXE7HmIEtFF+DJCbTPwuLunP0YUnrydl+C4tS+vEM0+nyxXrX3PSUFqC+lP1+EHB1Tw==", + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.15.tgz", + "integrity": "sha512-iKYUJpiyTQ33U2KlOZeUb0GwtzWR3C0soYcKuCnTmJrvt6XwTPQZhMfsjJZNw7PpQ3TU4Ati1qLSrkSJxnnSMQ==", "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.1.3", "@smithy/protocol-http": "^5.1.2", "@smithy/service-error-classification": "^4.0.6", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/util-middleware": "^4.0.4", "@smithy/util-retry": "^4.0.6", @@ -1721,9 +1722,9 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.6.tgz", - "integrity": "sha512-NqbmSz7AW2rvw4kXhKGrYTiJVDHnMsFnX4i+/FzcZAfbOBauPYs2ekuECkSbtqaxETLLTu9Rl/ex6+I2BKErPA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.1.0.tgz", + "integrity": "sha512-vqfSiHz2v8b3TTTrdXi03vNz1KLYYS3bhHCDv36FYDqxT7jvTll1mMnCrkD+gOvgwybuunh/2VmvOMqwBegxEg==", "license": "Apache-2.0", "dependencies": { "@smithy/abort-controller": "^4.0.4", @@ -1834,17 +1835,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.5.tgz", - "integrity": "sha512-+lynZjGuUFJaMdDYSTMnP/uPBBXXukVfrJlP+1U/Dp5SFTEI++w6NMga8DjOENxecOF71V9Z2DllaVDYRnGlkg==", + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.6.tgz", + "integrity": "sha512-3wfhywdzB/CFszP6moa5L3lf5/zSfQoH0kvVSdkyK2az5qZet0sn2PAHjcTDiq296Y4RP5yxF7B6S6+3oeBUCQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.6.0", - "@smithy/middleware-endpoint": "^4.1.13", + "@smithy/core": "^3.7.0", + "@smithy/middleware-endpoint": "^4.1.14", "@smithy/middleware-stack": "^4.0.4", "@smithy/protocol-http": "^5.1.2", "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "tslib": "^2.6.2" }, "engines": { @@ -1941,13 +1942,13 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.21.tgz", - "integrity": "sha512-wM0jhTytgXu3wzJoIqpbBAG5U6BwiubZ6QKzSbP7/VbmF1v96xlAbX2Am/mz0Zep0NLvLh84JT0tuZnk3wmYQA==", + "version": "4.0.22", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.22.tgz", + "integrity": "sha512-hjElSW18Wq3fUAWVk6nbk7pGrV7ZT14DL1IUobmqhV3lxcsIenr5FUsDe2jlTVaS8OYBI3x+Og9URv5YcKb5QA==", "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -1957,16 +1958,16 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.21.tgz", - "integrity": "sha512-/F34zkoU0GzpUgLJydHY8Rxu9lBn8xQC/s/0M0U9lLBkYbA1htaAFjWYJzpzsbXPuri5D1H8gjp2jBum05qBrA==", + "version": "4.0.22", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.22.tgz", + "integrity": "sha512-7B8mfQBtwwr2aNRRmU39k/bsRtv9B6/1mTMrGmmdJFKmLAH+KgIiOuhaqfKOBGh9sZ/VkZxbvm94rI4MMYpFjQ==", "license": "Apache-2.0", "dependencies": { "@smithy/config-resolver": "^4.1.4", "@smithy/credential-provider-imds": "^4.0.6", "@smithy/node-config-provider": "^4.1.3", "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, @@ -2028,13 +2029,13 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.2.tgz", - "integrity": "sha512-aI+GLi7MJoVxg24/3J1ipwLoYzgkB4kUfogZfnslcYlynj3xsQ0e7vk4TnTro9hhsS5PvX1mwmkRqqHQjwcU7w==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.3.tgz", + "integrity": "sha512-cQn412DWHHFNKrQfbHY8vSFI3nTROY1aIKji9N0tpp8gUABRilr7wdf8fqBbSlXresobM+tQFNk6I+0LXK/YZg==", "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/node-http-handler": "^4.0.6", + "@smithy/fetch-http-handler": "^5.1.0", + "@smithy/node-http-handler": "^4.1.0", "@smithy/types": "^4.3.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-buffer-from": "^4.0.0", @@ -2086,9 +2087,9 @@ } }, "node_modules/@soulcraft/brainy": { - "version": "0.9.37", - "resolved": "https://registry.npmjs.org/@soulcraft/brainy/-/brainy-0.9.37.tgz", - "integrity": "sha512-UgXozMeQdu5lzlxD5AxzTq34ixBEagPzuJy+hZxMogj8GwZ1tQnhRhEjC/JlbfvkUjgjn2dN9J+pFyxTLpYrSg==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@soulcraft/brainy/-/brainy-0.10.0.tgz", + "integrity": "sha512-KtJXuQBIH4oLtGw5D5/pNPzwLTgWPbsF2qbqN/2ljvRLvUvDmSpg7z2q2HZhZhfUbL5BGY5OhUzvDO1jLBmZeA==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -2103,16 +2104,7 @@ "uuid": "^9.0.1" }, "engines": { - "node": ">=24.3.0" - } - }, - "node_modules/@soulcraft/brainy/node_modules/@tensorflow/tfjs-converter": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-4.22.0.tgz", - "integrity": "sha512-PT43MGlnzIo+YfbsjM79Lxk9lOq6uUwZuCc8rrp0hfpLjF6Jv8jS84u2jFb+WpUeuF4K33ZDNx8CjiYrGQ2trQ==", - "license": "Apache-2.0", - "peerDependencies": { - "@tensorflow/tfjs-core": "4.22.0" + "node": ">=24.4.0" } }, "node_modules/@tensorflow-models/universal-sentence-encoder": { @@ -2181,6 +2173,15 @@ "@tensorflow/tfjs-core": "4.22.0" } }, + "node_modules/@tensorflow/tfjs-converter": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-4.22.0.tgz", + "integrity": "sha512-PT43MGlnzIo+YfbsjM79Lxk9lOq6uUwZuCc8rrp0hfpLjF6Jv8jS84u2jFb+WpUeuF4K33ZDNx8CjiYrGQ2trQ==", + "license": "Apache-2.0", + "peerDependencies": { + "@tensorflow/tfjs-core": "4.22.0" + } + }, "node_modules/@tensorflow/tfjs-core": { "version": "4.22.0", "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-4.22.0.tgz", @@ -2229,15 +2230,6 @@ "@tensorflow/tfjs-core": "4.22.0" } }, - "node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-converter": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-4.22.0.tgz", - "integrity": "sha512-PT43MGlnzIo+YfbsjM79Lxk9lOq6uUwZuCc8rrp0hfpLjF6Jv8jS84u2jFb+WpUeuF4K33ZDNx8CjiYrGQ2trQ==", - "license": "Apache-2.0", - "peerDependencies": { - "@tensorflow/tfjs-core": "4.22.0" - } - }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -2252,9 +2244,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.4.tgz", - "integrity": "sha512-OP+We5WV8Xnbuvw0zC2m4qfB/BJvjyCwtNjhHdJxV1639SGSKrLmJkc3fMnp2Qy8nJyHp8RO6umxELN/dS1/EA==", + "version": "20.19.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.7.tgz", + "integrity": "sha512-1GM9z6BJOv86qkPvzh2i6VW5+VVrXxCLknfmTkWEqz+6DqosiY28XUWCTmBcJ0ACzKqx/iwdIREfo1fwExIlkA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -2632,22 +2624,18 @@ "license": "MIT" }, "node_modules/fast-xml-parser": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", - "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } ], "license": "MIT", "dependencies": { - "strnum": "^1.0.5" + "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" @@ -3108,9 +3096,9 @@ } }, "node_modules/rollup": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz", - "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.2.tgz", + "integrity": "sha512-PVoapzTwSEcelaWGth3uR66u7ZRo6qhPHc0f2uRO9fX6XDVNrIiGYS0Pj9+R8yIIYSD/mCx2b16Ws9itljKSPg==", "dev": true, "license": "MIT", "dependencies": { @@ -3124,26 +3112,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.44.1", - "@rollup/rollup-android-arm64": "4.44.1", - "@rollup/rollup-darwin-arm64": "4.44.1", - "@rollup/rollup-darwin-x64": "4.44.1", - "@rollup/rollup-freebsd-arm64": "4.44.1", - "@rollup/rollup-freebsd-x64": "4.44.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.44.1", - "@rollup/rollup-linux-arm-musleabihf": "4.44.1", - "@rollup/rollup-linux-arm64-gnu": "4.44.1", - "@rollup/rollup-linux-arm64-musl": "4.44.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.44.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1", - "@rollup/rollup-linux-riscv64-gnu": "4.44.1", - "@rollup/rollup-linux-riscv64-musl": "4.44.1", - "@rollup/rollup-linux-s390x-gnu": "4.44.1", - "@rollup/rollup-linux-x64-gnu": "4.44.1", - "@rollup/rollup-linux-x64-musl": "4.44.1", - "@rollup/rollup-win32-arm64-msvc": "4.44.1", - "@rollup/rollup-win32-ia32-msvc": "4.44.1", - "@rollup/rollup-win32-x64-msvc": "4.44.1", + "@rollup/rollup-android-arm-eabi": "4.44.2", + "@rollup/rollup-android-arm64": "4.44.2", + "@rollup/rollup-darwin-arm64": "4.44.2", + "@rollup/rollup-darwin-x64": "4.44.2", + "@rollup/rollup-freebsd-arm64": "4.44.2", + "@rollup/rollup-freebsd-x64": "4.44.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.44.2", + "@rollup/rollup-linux-arm-musleabihf": "4.44.2", + "@rollup/rollup-linux-arm64-gnu": "4.44.2", + "@rollup/rollup-linux-arm64-musl": "4.44.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.44.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.44.2", + "@rollup/rollup-linux-riscv64-gnu": "4.44.2", + "@rollup/rollup-linux-riscv64-musl": "4.44.2", + "@rollup/rollup-linux-s390x-gnu": "4.44.2", + "@rollup/rollup-linux-x64-gnu": "4.44.2", + "@rollup/rollup-linux-x64-musl": "4.44.2", + "@rollup/rollup-win32-arm64-msvc": "4.44.2", + "@rollup/rollup-win32-ia32-msvc": "4.44.2", + "@rollup/rollup-win32-x64-msvc": "4.44.2", "fsevents": "~2.3.2" } }, @@ -3263,9 +3251,9 @@ } }, "node_modules/strnum": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", - "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", "funding": [ { "type": "github", diff --git a/cli-package/package.json b/cli-package/package.json index 702cf056..19d93d95 100644 --- a/cli-package/package.json +++ b/cli-package/package.json @@ -56,6 +56,6 @@ "typescript": "^5.4.5" }, "engines": { - "node": ">=24.3.0" + "node": ">=24.4.0" } } \ No newline at end of file diff --git a/cli-package/src/cli.ts b/cli-package/src/cli.ts index 4d14e021..d083856f 100644 --- a/cli-package/src/cli.ts +++ b/cli-package/src/cli.ts @@ -5,13 +5,8 @@ * A command-line interface for interacting with the Brainy vector database */ -// Import the unified text encoding utilities -// This needs to be done before importing @soulcraft/brainy -import { applyTensorFlowPatch } from './utils/textEncoding.js' - -// Apply the TensorFlow.js platform patch if needed +// Log environment information console.log('Brainy running in Node.js environment') -applyTensorFlowPatch() import { BrainyData, @@ -1360,6 +1355,21 @@ augmentCommand // Add the augment command to the program program.addCommand(augmentCommand) +// Add a top-level test-tensorflow-textencoder command +program + .command('test-tensorflow-textencoder') + .description('Test TensorFlow.js and TextEncoder functionality') + .action(async () => { + try { + // Import the test function from the test file + const { runTest } = await import('./test-tensorflow-textencoder.js') + await runTest() + } catch (error) { + console.error('Error:', (error as Error).message) + process.exit(1) + } + }) + // Add a top-level test-pipeline command that redirects to augment test-pipeline program .command('test-pipeline') diff --git a/cli-package/src/test-tensorflow-textencoder.ts b/cli-package/src/test-tensorflow-textencoder.ts new file mode 100644 index 00000000..a5575f75 --- /dev/null +++ b/cli-package/src/test-tensorflow-textencoder.ts @@ -0,0 +1,102 @@ +/** + * CLI Test for TensorFlow.js and TextEncoder + * + * This script tests TensorFlow.js and TextEncoder functionality in the CLI environment. + */ + +import { + getTextEncoder, + getTextDecoder +} from '@soulcraft/brainy/dist/utils/textEncoding.js' +import * as tf from '@tensorflow/tfjs' +import '@tensorflow/tfjs-backend-cpu' + +export async function testTensorFlowAndTextEncoder(): Promise { + console.log('Testing TensorFlow.js and TextEncoder in CLI environment...') + + try { + // TensorFlow patch is automatically applied by the main package + console.log('Using TensorFlow with automatic patching') + + // Test TextEncoder + console.log('\n--- Testing TextEncoder ---') + const encoder = getTextEncoder() + const decoder = getTextDecoder() + + const testString = 'Hello, world! 👋' + console.log(`Original string: "${testString}"`) + + const encoded = encoder.encode(testString) + console.log(`Encoded: [${encoded}]`) + + const decoded = decoder.decode(encoded) + console.log(`Decoded: "${decoded}"`) + + if (testString === decoded) { + console.log('✅ TextEncoder/TextDecoder test passed!') + } else { + console.error('❌ TextEncoder/TextDecoder test failed!') + return false + } + + // Test TensorFlow.js + console.log('\n--- Testing TensorFlow.js ---') + + // Create a simple tensor + const tensor = tf.tensor2d([ + [1, 2], + [3, 4] + ]) + console.log('Created tensor:') + tensor.print() + + // Perform a simple operation + const result = tensor.add(tf.scalar(1)) + console.log('Result of adding 1:') + result.print() + + // Check the values + const values = await result.array() + const expected = [ + [2, 3], + [4, 5] + ] + + console.log('Result values:', values) + console.log('Expected values:', expected) + + // Compare values + const match = JSON.stringify(values) === JSON.stringify(expected) + if (match) { + console.log('✅ TensorFlow.js test passed!') + } else { + console.error('❌ TensorFlow.js test failed!') + return false + } + + console.log('\nAll tests passed successfully!') + return true + } catch (error) { + console.error('Error during test:', error) + return false + } +} + +// This function can be called from the CLI +export async function runTest(): Promise { + const success = await testTensorFlowAndTextEncoder() + if (success) { + console.log( + 'TensorFlow.js and TextEncoder verification completed successfully!' + ) + process.exit(0) + } else { + console.error('TensorFlow.js and TextEncoder verification failed!') + process.exit(1) + } +} + +// If this file is run directly +if (typeof require !== 'undefined' && require.main === module) { + runTest() +} diff --git a/cli-package/src/utils/textEncoding.ts b/cli-package/src/utils/textEncoding.ts index 52615c5f..da0306e8 100644 --- a/cli-package/src/utils/textEncoding.ts +++ b/cli-package/src/utils/textEncoding.ts @@ -2,13 +2,13 @@ * Unified Text Encoding Utilities for CLI * * This module provides a consistent way to handle text encoding/decoding across all environments - * without relying on TextEncoder/TextDecoder polyfills or patches. + * using the native TextEncoder/TextDecoder APIs. */ /** * Apply the TensorFlow.js platform patch if needed * This function patches the global object to provide a PlatformNode class - * that uses our text encoding utilities instead of relying on TextEncoder/TextDecoder + * that uses native TextEncoder/TextDecoder */ export function applyTensorFlowPatch(): void { // Only apply in Node.js environment @@ -22,20 +22,32 @@ export function applyTensorFlowPatch(): void { // Define a custom PlatformNode class class PlatformNode { util: any - textEncoder: any - textDecoder: any + textEncoder: TextEncoder + textDecoder: TextDecoder constructor() { // Create a util object with necessary methods and constructors this.util = { + // Add isFloat32Array and isTypedArray directly to util + isFloat32Array: (arr: any) => { + return !!( + arr instanceof Float32Array || + (arr && + Object.prototype.toString.call(arr) === + '[object Float32Array]') + ) + }, + isTypedArray: (arr: any) => { + return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView)) + }, // Use native TextEncoder and TextDecoder TextEncoder: TextEncoder, TextDecoder: TextDecoder } - // Initialize using the constructors from util - this.textEncoder = new this.util.TextEncoder() - this.textDecoder = new this.util.TextDecoder() + // Initialize using native constructors + this.textEncoder = new TextEncoder() + this.textDecoder = new TextDecoder() } // Define isFloat32Array directly on the instance @@ -43,8 +55,7 @@ export function applyTensorFlowPatch(): void { return !!( arr instanceof Float32Array || (arr && - Object.prototype.toString.call(arr) === - '[object Float32Array]') + Object.prototype.toString.call(arr) === '[object Float32Array]') ) } @@ -59,6 +70,30 @@ export function applyTensorFlowPatch(): void { // Also create an instance and assign it to global.platformNode (lowercase p) ;(global as any).platformNode = new PlatformNode() + + // Ensure global.util exists and has the necessary methods + // This is needed because TensorFlow.js might look for these methods in global.util + if (!(global as any).util) { + ;(global as any).util = {} + } + + // Add isFloat32Array method if it doesn't exist + if (!(global as any).util.isFloat32Array) { + ;(global as any).util.isFloat32Array = (arr: any) => { + return !!( + arr instanceof Float32Array || + (arr && + Object.prototype.toString.call(arr) === '[object Float32Array]') + ) + } + } + + // Add isTypedArray method if it doesn't exist + if (!(global as any).util.isTypedArray) { + ;(global as any).util.isTypedArray = (arr: any) => { + return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView)) + } + } } catch (error) { console.warn('Failed to apply TensorFlow.js platform patch:', error) } diff --git a/cloud-wrapper/package.json b/cloud-wrapper/package.json index b2821ac6..fd5b1b7b 100644 --- a/cloud-wrapper/package.json +++ b/cloud-wrapper/package.json @@ -44,7 +44,7 @@ "typescript": "^5.4.5" }, "engines": { - "node": ">=24.3.0" + "node": ">=24.4.0" }, "prettier": { "arrowParens": "always", diff --git a/demo/test-fallback.html b/demo/test-fallback.html index e2b1bd4a..4ee85f20 100644 --- a/demo/test-fallback.html +++ b/demo/test-fallback.html @@ -99,36 +99,32 @@ }) async function runWorkerTest(resultDiv) { - // Define a compute-intensive function using a function expression - // This is more compatible with how the worker evaluates the function string - const computeIntensiveFunction = ` - function computeTask(data) { - console.log('Worker/Fallback: Starting computation...'); + // Define a compute-intensive function using a simple anonymous function expression + // This format works with both worker and fallback mechanisms + const computeIntensiveFunction = `function(data) { + console.log('Worker/Fallback: Starting computation...'); - // Simulate a compute-intensive task - const start = Date.now(); - let result = 0; - for (let i = 0; i < data.iterations; i++) { - result += Math.sqrt(i) * Math.sin(i); + // Simulate a compute-intensive task + const start = Date.now(); + let result = 0; + for (let i = 0; i < data.iterations; i++) { + result += Math.sqrt(i) * Math.sin(i); + } + + const duration = Date.now() - start; + console.log('Worker/Fallback: Computation completed in ' + duration + 'ms'); + + const globalObj = typeof self !== 'undefined' ? self : + typeof window !== 'undefined' ? window : + {}; + + return { + result, + duration, + iterations: data.iterations, + webWorkersAvailable: typeof globalObj.Worker !== 'undefined' + }; } - - const duration = Date.now() - start; - console.log('Worker/Fallback: Computation completed in ' + duration + 'ms'); - - const globalObj = typeof self !== 'undefined' ? self : - typeof window !== 'undefined' ? window : - {}; - - return { - result, - duration, - iterations: data.iterations, - webWorkersAvailable: typeof globalObj.Worker !== 'undefined' - }; - } - - // Return the function itself - computeTask; ` // Execute the function diff --git a/demo/test-tensorflow-textencoder.html b/demo/test-tensorflow-textencoder.html new file mode 100644 index 00000000..44bffaa8 --- /dev/null +++ b/demo/test-tensorflow-textencoder.html @@ -0,0 +1,159 @@ + + + + + + Brainy TensorFlow and TextEncoder Test + + + +

Brainy TensorFlow and TextEncoder Test

+

This page tests TensorFlow.js and TextEncoder functionality in a browser environment.

+ + +
+

Results will appear here...

+
+ + + + diff --git a/docs/publishing-cli.md b/docs/publishing-cli.md index 722dfc9d..afc69d64 100644 --- a/docs/publishing-cli.md +++ b/docs/publishing-cli.md @@ -6,7 +6,7 @@ This document explains how to publish both the @soulcraft/brainy and @soulcraft/ Before publishing, ensure you have: -1. Node.js >= 24.3.0 installed +1. Node.js >= 24.4.0 installed 2. An npm account with access to the @soulcraft organization 3. Logged in to npm using `npm login` diff --git a/package-lock.json b/package-lock.json index baef2b49..ab6b17c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,7 @@ "typescript": "^5.4.5" }, "engines": { - "node": ">=24.3.0" + "node": ">=24.4.0" } }, "node_modules/@aws-crypto/crc32": { @@ -244,64 +244,64 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.842.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.842.0.tgz", - "integrity": "sha512-T5Rh72Rcq1xIaM8KkTr1Wpr7/WPCYO++KrM+/Em0rq2jxpjMMhj77ITpgH7eEmNxWmwIndTwqpgfmbpNfk7Gbw==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.844.0.tgz", + "integrity": "sha512-Yhp8+U4KFVQqL6phZ5yrHF5PdCvKWbYtLSS+egAfAW+N5w78amhbZcctervj59uqOZHMGDWXuDBklN+7eVfasg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.840.0", - "@aws-sdk/credential-provider-node": "3.840.0", + "@aws-sdk/core": "3.844.0", + "@aws-sdk/credential-provider-node": "3.844.0", "@aws-sdk/middleware-bucket-endpoint": "3.840.0", "@aws-sdk/middleware-expect-continue": "3.840.0", - "@aws-sdk/middleware-flexible-checksums": "3.840.0", + "@aws-sdk/middleware-flexible-checksums": "3.844.0", "@aws-sdk/middleware-host-header": "3.840.0", "@aws-sdk/middleware-location-constraint": "3.840.0", "@aws-sdk/middleware-logger": "3.840.0", "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-sdk-s3": "3.840.0", + "@aws-sdk/middleware-sdk-s3": "3.844.0", "@aws-sdk/middleware-ssec": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.844.0", "@aws-sdk/region-config-resolver": "3.840.0", - "@aws-sdk/signature-v4-multi-region": "3.840.0", + "@aws-sdk/signature-v4-multi-region": "3.844.0", "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", + "@aws-sdk/util-endpoints": "3.844.0", "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.844.0", "@aws-sdk/xml-builder": "3.821.0", "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.6.0", + "@smithy/core": "^3.7.0", "@smithy/eventstream-serde-browser": "^4.0.4", "@smithy/eventstream-serde-config-resolver": "^4.1.2", "@smithy/eventstream-serde-node": "^4.0.4", - "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/fetch-http-handler": "^5.1.0", "@smithy/hash-blob-browser": "^4.0.4", "@smithy/hash-node": "^4.0.4", "@smithy/hash-stream-node": "^4.0.4", "@smithy/invalid-dependency": "^4.0.4", "@smithy/md5-js": "^4.0.4", "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.13", - "@smithy/middleware-retry": "^4.1.14", + "@smithy/middleware-endpoint": "^4.1.14", + "@smithy/middleware-retry": "^4.1.15", "@smithy/middleware-serde": "^4.0.8", "@smithy/middleware-stack": "^4.0.4", "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", + "@smithy/node-http-handler": "^4.1.0", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.21", - "@smithy/util-defaults-mode-node": "^4.0.21", + "@smithy/util-defaults-mode-browser": "^4.0.22", + "@smithy/util-defaults-mode-node": "^4.0.22", "@smithy/util-endpoints": "^3.0.6", "@smithy/util-middleware": "^4.0.4", "@smithy/util-retry": "^4.0.6", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "@smithy/util-utf8": "^4.0.0", "@smithy/util-waiter": "^4.0.6", "@types/uuid": "^9.0.1", @@ -319,44 +319,44 @@ "license": "MIT" }, "node_modules/@aws-sdk/client-sso": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.840.0.tgz", - "integrity": "sha512-3Zp+FWN2hhmKdpS0Ragi5V2ZPsZNScE3jlbgoJjzjI/roHZqO+e3/+XFN4TlM0DsPKYJNp+1TAjmhxN6rOnfYA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.844.0.tgz", + "integrity": "sha512-FktodSx+pfUfIqMjoNwZ6t1xqq/G3cfT7I4JJ0HKHoIIZdoCHQB52x0OzKDtHDJAnEQPInasdPS8PorZBZtHmg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/middleware-host-header": "3.840.0", "@aws-sdk/middleware-logger": "3.840.0", "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.844.0", "@aws-sdk/region-config-resolver": "3.840.0", "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", + "@aws-sdk/util-endpoints": "3.844.0", "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.844.0", "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.6.0", - "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/core": "^3.7.0", + "@smithy/fetch-http-handler": "^5.1.0", "@smithy/hash-node": "^4.0.4", "@smithy/invalid-dependency": "^4.0.4", "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.13", - "@smithy/middleware-retry": "^4.1.14", + "@smithy/middleware-endpoint": "^4.1.14", + "@smithy/middleware-retry": "^4.1.15", "@smithy/middleware-serde": "^4.0.8", "@smithy/middleware-stack": "^4.0.4", "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", + "@smithy/node-http-handler": "^4.1.0", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.21", - "@smithy/util-defaults-mode-node": "^4.0.21", + "@smithy/util-defaults-mode-browser": "^4.0.22", + "@smithy/util-defaults-mode-node": "^4.0.22", "@smithy/util-endpoints": "^3.0.6", "@smithy/util-middleware": "^4.0.4", "@smithy/util-retry": "^4.0.6", @@ -368,25 +368,25 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.840.0.tgz", - "integrity": "sha512-x3Zgb39tF1h2XpU+yA4OAAQlW6LVEfXNlSedSYJ7HGKXqA/E9h3rWQVpYfhXXVVsLdYXdNw5KBUkoAoruoZSZA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.844.0.tgz", + "integrity": "sha512-pfpI54bG5Xf2NkqrDBC2REStXlDXNCw/whORhkEs+Tp5exU872D5QKguzjPA6hH+8Pvbq1qgt5zXMbduISTHJw==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.840.0", "@aws-sdk/xml-builder": "3.821.0", - "@smithy/core": "^3.6.0", + "@smithy/core": "^3.7.0", "@smithy/node-config-provider": "^4.1.3", "@smithy/property-provider": "^4.0.4", "@smithy/protocol-http": "^5.1.2", "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-middleware": "^4.0.4", "@smithy/util-utf8": "^4.0.0", - "fast-xml-parser": "4.4.1", + "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" }, "engines": { @@ -394,12 +394,12 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.840.0.tgz", - "integrity": "sha512-EzF6VcJK7XvQ/G15AVEfJzN2mNXU8fcVpXo4bRyr1S6t2q5zx6UPH/XjDbn18xyUmOq01t+r8gG+TmHEVo18fA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.844.0.tgz", + "integrity": "sha512-WB94Ox86MqcZ4CnRjKgopzaSuZH4hMP0GqdOxG4s1it1lRWOIPOHOC1dPiM0Zbj1uqITIhbXUQVXyP/uaJeNkw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/property-provider": "^4.0.4", "@smithy/types": "^4.3.1", @@ -410,20 +410,20 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.840.0.tgz", - "integrity": "sha512-wbnUiPGLVea6mXbUh04fu+VJmGkQvmToPeTYdHE8eRZq3NRDi3t3WltT+jArLBKD/4NppRpMjf2ju4coMCz91g==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.844.0.tgz", + "integrity": "sha512-e+efVqfkhpM8zxYeiLNgTUlX+tmtXzVm3bw1A02U9Z9cWBHyQNb8pi90M7QniLoqRURY1B0C2JqkOE61gd4KNg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/node-http-handler": "^4.0.6", + "@smithy/fetch-http-handler": "^5.1.0", + "@smithy/node-http-handler": "^4.1.0", "@smithy/property-provider": "^4.0.4", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "tslib": "^2.6.2" }, "engines": { @@ -431,18 +431,18 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.840.0.tgz", - "integrity": "sha512-7F290BsWydShHb+7InXd+IjJc3mlEIm9I0R57F/Pjl1xZB69MdkhVGCnuETWoBt4g53ktJd6NEjzm/iAhFXFmw==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.844.0.tgz", + "integrity": "sha512-jc5ArGz2HfAx5QPXD+Ep36+QWyCKzl2TG6Vtl87/vljfLhVD0gEHv8fRsqWEp3Rc6hVfKnCjLW5ayR2HYcow9w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/credential-provider-env": "3.840.0", - "@aws-sdk/credential-provider-http": "3.840.0", - "@aws-sdk/credential-provider-process": "3.840.0", - "@aws-sdk/credential-provider-sso": "3.840.0", - "@aws-sdk/credential-provider-web-identity": "3.840.0", - "@aws-sdk/nested-clients": "3.840.0", + "@aws-sdk/core": "3.844.0", + "@aws-sdk/credential-provider-env": "3.844.0", + "@aws-sdk/credential-provider-http": "3.844.0", + "@aws-sdk/credential-provider-process": "3.844.0", + "@aws-sdk/credential-provider-sso": "3.844.0", + "@aws-sdk/credential-provider-web-identity": "3.844.0", + "@aws-sdk/nested-clients": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/credential-provider-imds": "^4.0.6", "@smithy/property-provider": "^4.0.4", @@ -455,17 +455,17 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.840.0.tgz", - "integrity": "sha512-KufP8JnxA31wxklLm63evUPSFApGcH8X86z3mv9SRbpCm5ycgWIGVCTXpTOdgq6rPZrwT9pftzv2/b4mV/9clg==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.844.0.tgz", + "integrity": "sha512-pUqB0StTNyW0R03XjTA3wrQZcie/7FJKSXlYHue921ZXuhLOZpzyDkLNfdRsZTcEoYYWVPSmyS+Eu/g5yVsBNA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.840.0", - "@aws-sdk/credential-provider-http": "3.840.0", - "@aws-sdk/credential-provider-ini": "3.840.0", - "@aws-sdk/credential-provider-process": "3.840.0", - "@aws-sdk/credential-provider-sso": "3.840.0", - "@aws-sdk/credential-provider-web-identity": "3.840.0", + "@aws-sdk/credential-provider-env": "3.844.0", + "@aws-sdk/credential-provider-http": "3.844.0", + "@aws-sdk/credential-provider-ini": "3.844.0", + "@aws-sdk/credential-provider-process": "3.844.0", + "@aws-sdk/credential-provider-sso": "3.844.0", + "@aws-sdk/credential-provider-web-identity": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/credential-provider-imds": "^4.0.6", "@smithy/property-provider": "^4.0.4", @@ -478,12 +478,12 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.840.0.tgz", - "integrity": "sha512-HkDQWHy8tCI4A0Ps2NVtuVYMv9cB4y/IuD/TdOsqeRIAT12h8jDb98BwQPNLAImAOwOWzZJ8Cu0xtSpX7CQhMw==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.844.0.tgz", + "integrity": "sha512-VCI8XvIDt2WBfk5Gi/wXKPcWTS3OkAbovB66oKcNQalllH8ESDg4SfLNhchdnN8A5sDGj6tIBJ19nk+dQ6GaqQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/property-provider": "^4.0.4", "@smithy/shared-ini-file-loader": "^4.0.4", @@ -495,14 +495,14 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.840.0.tgz", - "integrity": "sha512-2qgdtdd6R0Z1y0KL8gzzwFUGmhBHSUx4zy85L2XV1CXhpRNwV71SVWJqLDVV5RVWVf9mg50Pm3AWrUC0xb0pcA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.844.0.tgz", + "integrity": "sha512-UNp/uWufGlb5nWa4dpc6uQnDOB/9ysJJFG95ACowNVL9XWfi1LJO7teKrqNkVhq0CzSJS1tCt3FvX4UfM+aN1g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.840.0", - "@aws-sdk/core": "3.840.0", - "@aws-sdk/token-providers": "3.840.0", + "@aws-sdk/client-sso": "3.844.0", + "@aws-sdk/core": "3.844.0", + "@aws-sdk/token-providers": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/property-provider": "^4.0.4", "@smithy/shared-ini-file-loader": "^4.0.4", @@ -514,13 +514,13 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.840.0.tgz", - "integrity": "sha512-dpEeVXG8uNZSmVXReE4WP0lwoioX2gstk4RnUgrdUE3YaPq8A+hJiVAyc3h+cjDeIqfbsQbZm9qFetKC2LF9dQ==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.844.0.tgz", + "integrity": "sha512-iDmX4pPmatjttIScdspZRagaFnCjpHZIEEwTyKdXxUaU0iAOSXF8ecrCEvutETvImPOC86xdrq+MPacJOnMzUA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/nested-clients": "3.840.0", + "@aws-sdk/core": "3.844.0", + "@aws-sdk/nested-clients": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/property-provider": "^4.0.4", "@smithy/types": "^4.3.1", @@ -564,22 +564,22 @@ } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.840.0.tgz", - "integrity": "sha512-Kg/o2G6o72sdoRH0J+avdcf668gM1bp6O4VeEXpXwUj/urQnV5qiB2q1EYT110INHUKWOLXPND3sQAqh6sTqHw==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.844.0.tgz", + "integrity": "sha512-LCImZd1hpM0cegfdpgZyK6x4on4Ky+c9XCFURfE4wil1J9HXf6OP4KsfHQwt1yIkMEbFqvd/ab2I5fmp7S7aFA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", "@aws-crypto/util": "5.2.0", - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/is-array-buffer": "^4.0.0", "@smithy/node-config-provider": "^4.1.3", "@smithy/protocol-http": "^5.1.2", "@smithy/types": "^4.3.1", "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -646,23 +646,23 @@ } }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.840.0.tgz", - "integrity": "sha512-rOUji7CayWN3O09zvvgLzDVQe0HiJdZkxoTS6vzOS3WbbdT7joGdVtAJHtn+x776QT3hHzbKU5gnfhel0o6gQA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.844.0.tgz", + "integrity": "sha512-vOD5reqZszXBWMbZFN3EUar203o2i8gcoTdrymY4GMsAPDsh0k8yd3VJRNPuxT/017tP6G+rQepOGzna4umung==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", "@aws-sdk/util-arn-parser": "3.804.0", - "@smithy/core": "^3.6.0", + "@smithy/core": "^3.7.0", "@smithy/node-config-provider": "^4.1.3", "@smithy/protocol-http": "^5.1.2", "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/util-config-provider": "^4.0.0", "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -685,15 +685,15 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.840.0.tgz", - "integrity": "sha512-hiiMf7BP5ZkAFAvWRcK67Mw/g55ar7OCrvrynC92hunx/xhMkrgSLM0EXIZ1oTn3uql9kH/qqGF0nqsK6K555A==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.844.0.tgz", + "integrity": "sha512-SIbDNUL6ZYXPj5Tk0qEz05sW9kNS1Gl3/wNWEmH+AuUACipkyIeKKWzD6z5433MllETh73vtka/JQF3g7AuZww==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", - "@smithy/core": "^3.6.0", + "@aws-sdk/util-endpoints": "3.844.0", + "@smithy/core": "^3.7.0", "@smithy/protocol-http": "^5.1.2", "@smithy/types": "^4.3.1", "tslib": "^2.6.2" @@ -703,44 +703,44 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.840.0.tgz", - "integrity": "sha512-LXYYo9+n4hRqnRSIMXLBb+BLz+cEmjMtTudwK1BF6Bn2RfdDv29KuyeDRrPCS3TwKl7ZKmXUmE9n5UuHAPfBpA==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.844.0.tgz", + "integrity": "sha512-p2XILWc7AcevUSpBg2VtQrk79eWQC4q2JsCSY7HxKpFLZB4mMOfmiTyYkR1gEA6AttK/wpCOtfz+hi1/+z2V1A==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.840.0", + "@aws-sdk/core": "3.844.0", "@aws-sdk/middleware-host-header": "3.840.0", "@aws-sdk/middleware-logger": "3.840.0", "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.844.0", "@aws-sdk/region-config-resolver": "3.840.0", "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", + "@aws-sdk/util-endpoints": "3.844.0", "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.844.0", "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.6.0", - "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/core": "^3.7.0", + "@smithy/fetch-http-handler": "^5.1.0", "@smithy/hash-node": "^4.0.4", "@smithy/invalid-dependency": "^4.0.4", "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.13", - "@smithy/middleware-retry": "^4.1.14", + "@smithy/middleware-endpoint": "^4.1.14", + "@smithy/middleware-retry": "^4.1.15", "@smithy/middleware-serde": "^4.0.8", "@smithy/middleware-stack": "^4.0.4", "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", + "@smithy/node-http-handler": "^4.1.0", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.21", - "@smithy/util-defaults-mode-node": "^4.0.21", + "@smithy/util-defaults-mode-browser": "^4.0.22", + "@smithy/util-defaults-mode-node": "^4.0.22", "@smithy/util-endpoints": "^3.0.6", "@smithy/util-middleware": "^4.0.4", "@smithy/util-retry": "^4.0.6", @@ -769,12 +769,12 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.840.0.tgz", - "integrity": "sha512-8AoVgHrkSfhvGPtwx23hIUO4MmMnux2pjnso1lrLZGqxfElM6jm2w4jTNLlNXk8uKHGyX89HaAIuT0lL6dJj9g==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.844.0.tgz", + "integrity": "sha512-QC8nocQcZ3Bj7vTnuL47iNhcuUjMC46E2L85mU+sPQo3LN2qBVGSOTF+xSWGvmSFDpkN4ZXUMVeA0cJoJFEDFA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.840.0", + "@aws-sdk/middleware-sdk-s3": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/protocol-http": "^5.1.2", "@smithy/signature-v4": "^5.1.2", @@ -786,13 +786,13 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.840.0.tgz", - "integrity": "sha512-6BuTOLTXvmgwjK7ve7aTg9JaWFdM5UoMolLVPMyh3wTv9Ufalh8oklxYHUBIxsKkBGO2WiHXytveuxH6tAgTYg==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.844.0.tgz", + "integrity": "sha512-Kh728FEny0fil+LeH8U1offPJCTd/EDh8liBAvLtViLHt2WoX2xC8rk98D38Q5p79aIUhHb3Pf4n9IZfTu/Kog==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/nested-clients": "3.840.0", + "@aws-sdk/core": "3.844.0", + "@aws-sdk/nested-clients": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/property-provider": "^4.0.4", "@smithy/shared-ini-file-loader": "^4.0.4", @@ -829,13 +829,14 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.840.0.tgz", - "integrity": "sha512-eqE9ROdg/Kk0rj3poutyRCFauPDXIf/WSvCqFiRDDVi6QOnCv/M0g2XW8/jSvkJlOyaXkNCptapIp6BeeFFGYw==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.844.0.tgz", + "integrity": "sha512-1DHh0WTUmxlysz3EereHKtKoxVUG9UC5BsfAw6Bm4/6qDlJiqtY3oa2vebkYN23yltKdfsCK65cwnBRU59mWVg==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.840.0", "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", "@smithy/util-endpoints": "^3.0.6", "tslib": "^2.6.2" }, @@ -868,12 +869,12 @@ } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.840.0.tgz", - "integrity": "sha512-Fy5JUEDQU1tPm2Yw/YqRYYc27W5+QD/J4mYvQvdWjUGZLB5q3eLFMGD35Uc28ZFoGMufPr4OCxK/bRfWROBRHQ==", + "version": "3.844.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.844.0.tgz", + "integrity": "sha512-0eTpURp9Gxbyyeqr78ogARZMSWS5KUMZuN+XMHxNpQLmn2S+J3g+MAyoklCcwhKXlbdQq2aMULEiy0mqIWytuw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.844.0", "@aws-sdk/types": "3.840.0", "@smithy/node-config-provider": "^4.1.3", "@smithy/types": "^4.3.1", @@ -1712,9 +1713,9 @@ } }, "node_modules/@smithy/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.6.0.tgz", - "integrity": "sha512-Pgvfb+TQ4wUNLyHzvgCP4aYZMh16y7GcfF59oirRHcgGgkH1e/s9C0nv/v3WP+Quymyr5je71HeFQCwh+44XLg==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.7.0.tgz", + "integrity": "sha512-7ov8hu/4j0uPZv8b27oeOFtIBtlFmM3ibrPv/Omx1uUdoXvcpJ00U+H/OWWC/keAguLlcqwtyL2/jTlSnApgNQ==", "license": "Apache-2.0", "dependencies": { "@smithy/middleware-serde": "^4.0.8", @@ -1723,7 +1724,7 @@ "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -1818,9 +1819,9 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.4.tgz", - "integrity": "sha512-AMtBR5pHppYMVD7z7G+OlHHAcgAN7v0kVKEpHuTO4Gb199Gowh0taYi9oDStFeUhetkeP55JLSVlTW1n9rFtUw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.0.tgz", + "integrity": "sha512-mADw7MS0bYe2OGKkHYMaqarOXuDwRbO6ArD91XhHcl2ynjGCFF+hvqf0LyQcYxkA1zaWjefSkU7Ne9mqgApSgQ==", "license": "Apache-2.0", "dependencies": { "@smithy/protocol-http": "^5.1.2", @@ -1931,12 +1932,12 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.13.tgz", - "integrity": "sha512-xg3EHV/Q5ZdAO5b0UiIMj3RIOCobuS40pBBODguUDVdko6YK6QIzCVRrHTogVuEKglBWqWenRnZ71iZnLL3ZAQ==", + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.14.tgz", + "integrity": "sha512-+BGLpK5D93gCcSEceaaYhUD/+OCGXM1IDaq/jKUQ+ujB0PTWlWN85noodKw/IPFZhIKFCNEe19PGd/reUMeLSQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.6.0", + "@smithy/core": "^3.7.0", "@smithy/middleware-serde": "^4.0.8", "@smithy/node-config-provider": "^4.1.3", "@smithy/shared-ini-file-loader": "^4.0.4", @@ -1950,15 +1951,15 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.14.tgz", - "integrity": "sha512-eoXaLlDGpKvdmvt+YBfRXE7HmIEtFF+DJCbTPwuLunP0YUnrydl+C4tS+vEM0+nyxXrX3PSUFqC+lP1+EHB1Tw==", + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.15.tgz", + "integrity": "sha512-iKYUJpiyTQ33U2KlOZeUb0GwtzWR3C0soYcKuCnTmJrvt6XwTPQZhMfsjJZNw7PpQ3TU4Ati1qLSrkSJxnnSMQ==", "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.1.3", "@smithy/protocol-http": "^5.1.2", "@smithy/service-error-classification": "^4.0.6", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "@smithy/util-middleware": "^4.0.4", "@smithy/util-retry": "^4.0.6", @@ -2012,9 +2013,9 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.6.tgz", - "integrity": "sha512-NqbmSz7AW2rvw4kXhKGrYTiJVDHnMsFnX4i+/FzcZAfbOBauPYs2ekuECkSbtqaxETLLTu9Rl/ex6+I2BKErPA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.1.0.tgz", + "integrity": "sha512-vqfSiHz2v8b3TTTrdXi03vNz1KLYYS3bhHCDv36FYDqxT7jvTll1mMnCrkD+gOvgwybuunh/2VmvOMqwBegxEg==", "license": "Apache-2.0", "dependencies": { "@smithy/abort-controller": "^4.0.4", @@ -2125,17 +2126,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.5.tgz", - "integrity": "sha512-+lynZjGuUFJaMdDYSTMnP/uPBBXXukVfrJlP+1U/Dp5SFTEI++w6NMga8DjOENxecOF71V9Z2DllaVDYRnGlkg==", + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.6.tgz", + "integrity": "sha512-3wfhywdzB/CFszP6moa5L3lf5/zSfQoH0kvVSdkyK2az5qZet0sn2PAHjcTDiq296Y4RP5yxF7B6S6+3oeBUCQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.6.0", - "@smithy/middleware-endpoint": "^4.1.13", + "@smithy/core": "^3.7.0", + "@smithy/middleware-endpoint": "^4.1.14", "@smithy/middleware-stack": "^4.0.4", "@smithy/protocol-http": "^5.1.2", "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "tslib": "^2.6.2" }, "engines": { @@ -2232,13 +2233,13 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.21.tgz", - "integrity": "sha512-wM0jhTytgXu3wzJoIqpbBAG5U6BwiubZ6QKzSbP7/VbmF1v96xlAbX2Am/mz0Zep0NLvLh84JT0tuZnk3wmYQA==", + "version": "4.0.22", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.22.tgz", + "integrity": "sha512-hjElSW18Wq3fUAWVk6nbk7pGrV7ZT14DL1IUobmqhV3lxcsIenr5FUsDe2jlTVaS8OYBI3x+Og9URv5YcKb5QA==", "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -2248,16 +2249,16 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.21.tgz", - "integrity": "sha512-/F34zkoU0GzpUgLJydHY8Rxu9lBn8xQC/s/0M0U9lLBkYbA1htaAFjWYJzpzsbXPuri5D1H8gjp2jBum05qBrA==", + "version": "4.0.22", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.22.tgz", + "integrity": "sha512-7B8mfQBtwwr2aNRRmU39k/bsRtv9B6/1mTMrGmmdJFKmLAH+KgIiOuhaqfKOBGh9sZ/VkZxbvm94rI4MMYpFjQ==", "license": "Apache-2.0", "dependencies": { "@smithy/config-resolver": "^4.1.4", "@smithy/credential-provider-imds": "^4.0.6", "@smithy/node-config-provider": "^4.1.3", "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.5", + "@smithy/smithy-client": "^4.4.6", "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, @@ -2319,13 +2320,13 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.2.tgz", - "integrity": "sha512-aI+GLi7MJoVxg24/3J1ipwLoYzgkB4kUfogZfnslcYlynj3xsQ0e7vk4TnTro9hhsS5PvX1mwmkRqqHQjwcU7w==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.3.tgz", + "integrity": "sha512-cQn412DWHHFNKrQfbHY8vSFI3nTROY1aIKji9N0tpp8gUABRilr7wdf8fqBbSlXresobM+tQFNk6I+0LXK/YZg==", "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/node-http-handler": "^4.0.6", + "@smithy/fetch-http-handler": "^5.1.0", + "@smithy/node-http-handler": "^4.1.0", "@smithy/types": "^4.3.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-buffer-from": "^4.0.0", @@ -2520,9 +2521,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.4.tgz", - "integrity": "sha512-OP+We5WV8Xnbuvw0zC2m4qfB/BJvjyCwtNjhHdJxV1639SGSKrLmJkc3fMnp2Qy8nJyHp8RO6umxELN/dS1/EA==", + "version": "20.19.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.7.tgz", + "integrity": "sha512-1GM9z6BJOv86qkPvzh2i6VW5+VVrXxCLknfmTkWEqz+6DqosiY28XUWCTmBcJ0ACzKqx/iwdIREfo1fwExIlkA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -2805,9 +2806,9 @@ } }, "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", "engines": { @@ -2908,9 +2909,9 @@ "license": "MIT" }, "node_modules/bare-events": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", - "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.6.0.tgz", + "integrity": "sha512-EKZ5BTXYExaNqi3I3f9RtEsaI/xBSGjE0XZCZilPzFAV/goswFHuPd9jEZlPIZ/iNZJwDSao9qRiScySz7MbQg==", "dev": true, "license": "Apache-2.0", "optional": true @@ -3770,22 +3771,18 @@ "license": "MIT" }, "node_modules/fast-xml-parser": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", - "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } ], "license": "MIT", "dependencies": { - "strnum": "^1.0.5" + "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" @@ -3986,9 +3983,9 @@ } }, "node_modules/get-uri": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", - "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", "dev": true, "license": "MIT", "dependencies": { @@ -5304,9 +5301,9 @@ } }, "node_modules/socks": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz", - "integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.6.tgz", + "integrity": "sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==", "dev": true, "license": "MIT", "dependencies": { @@ -5423,9 +5420,9 @@ } }, "node_modules/strnum": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", - "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", "funding": [ { "type": "github", diff --git a/package.json b/package.json index d516a5ce..dfdbce81 100644 --- a/package.json +++ b/package.json @@ -22,14 +22,22 @@ "./types/augmentations": { "import": "./dist/types/augmentations.js", "types": "./dist/types/augmentations.d.ts" + }, + "./utils/textEncoding": { + "import": "./dist/utils/textEncoding.js", + "types": "./dist/utils/textEncoding.d.ts" + }, + "./dist/utils/textEncoding.js": { + "import": "./dist/utils/textEncoding.js", + "types": "./dist/utils/textEncoding.d.ts" } }, "engines": { - "node": ">=24.3.0" + "node": ">=24.4.0" }, "scripts": { "prebuild": "node scripts/generate-version.js", - "build": "BUILD_TYPE=unified rollup -c rollup.config.js && node scripts/patch-textencoder.js", + "build": "BUILD_TYPE=unified rollup -c rollup.config.js", "build:browser": "BUILD_TYPE=browser rollup -c rollup.config.js", "build:cli": "cd cli-package && npm run build", "start": "node dist/unified.js", @@ -53,7 +61,9 @@ "postinstall": "echo 'Note: If you encounter dependency conflicts with TensorFlow.js packages, please use: npm install --legacy-peer-deps'", "dry-run": "npm pack --dry-run", "test:cli": "node scripts/test-cli-locally.js", - "test:all": "node scripts/test-all-environments.js" + "test:tensorflow": "node test-tensorflow-textencoder.js", + "test:all": "node scripts/test-all-environments.js", + "test": "npm run test:all" }, "keywords": [ "vector-database", diff --git a/scripts/test-all-environments.js b/scripts/test-all-environments.js index 043f6835..83e868c2 100644 --- a/scripts/test-all-environments.js +++ b/scripts/test-all-environments.js @@ -66,6 +66,11 @@ async function runAllTests() { runCommand('npm run build') log('Main package built successfully!', colors.green) + // Apply TextEncoder patch + log('Applying TextEncoder patch...', colors.yellow) + runCommand('node scripts/patch-textencoder.js') + log('TextEncoder patch applied successfully!', colors.green) + // Build the browser package log('Building browser package...', colors.yellow) runCommand('npm run build:browser') @@ -89,6 +94,11 @@ async function runAllTests() { log(textEncodingResult) log('Unified text encoding test completed!', colors.green) + log('Running TensorFlow and TextEncoder test...', colors.yellow) + const tensorflowTextEncoderResult = runCommand('node test-tensorflow-textencoder.js') + log(tensorflowTextEncoderResult) + log('TensorFlow and TextEncoder test completed!', colors.green) + logSection('RUNNING BROWSER TESTS') // Start a simple HTTP server to serve the test files @@ -214,6 +224,25 @@ async function runAllTests() { log('Fallback test result:', colors.green) log(fallbackResult.replace(/<[^>]*>/g, '').trim()) + // Test TensorFlow and TextEncoder in browser + log('Running TensorFlow and TextEncoder browser test...', colors.yellow) + await page.goto(`http://localhost:${PORT}/demo/test-tensorflow-textencoder.html`) + await page.waitForSelector('#runTest') + await page.click('#runTest') + await page.waitForFunction( + () => { + const resultText = document.getElementById('result').textContent + return resultText.includes('Test completed') + }, + { timeout: 30000 } + ) + + const browserTensorflowTextEncoderResult = await page.evaluate(() => { + return document.getElementById('result').innerHTML + }) + log('TensorFlow and TextEncoder browser test result:', colors.green) + log(browserTensorflowTextEncoderResult.replace(/<[^>]*>/g, '').trim()) + // Close the browser and server await browser.close() server.close() @@ -239,6 +268,11 @@ async function runAllTests() { log('Testing pipeline command...', colors.yellow) const pipelineResult = runCommand('brainy test-pipeline "This is a test"') log('Pipeline test completed!', colors.green) + + // Test TensorFlow and TextEncoder in CLI + log('Testing TensorFlow and TextEncoder in CLI...', colors.yellow) + const cliTensorflowResult = runCommand('brainy test-tensorflow-textencoder') + log('TensorFlow and TextEncoder CLI test completed!', colors.green) } catch (error) { log( "CLI tests failed. This might be expected if you don't have the CLI installed globally.", diff --git a/src/index.ts b/src/index.ts index 58acad54..814e445c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,12 @@ /** - * OPFS BrainyData - * A vector database using HNSW indexing with Origin Private File System storage + * Brainy + * A vector and graph database using HNSW */ -// Import unified text encoding utilities first to ensure they're available -import { applyTensorFlowPatch } from './utils/textEncoding.js' -// Apply the TensorFlow.js platform patch if needed -applyTensorFlowPatch() +// Import the setup file for its side-effects. +// This MUST be the very first import to ensure patches are applied +// before any other module (like TensorFlow.js) is loaded. +import './setup.js' // Export main BrainyData class and related types import { BrainyData, BrainyDataConfig } from './brainyData.js' @@ -39,10 +39,7 @@ import { } from './utils/embedding.js' // Export worker utilities -import { - executeInThread, - cleanupWorkerPools -} from './utils/workerUtils.js' +import { executeInThread, cleanupWorkerPools } from './utils/workerUtils.js' // Export environment utilities import { diff --git a/src/setup.ts b/src/setup.ts new file mode 100644 index 00000000..edd4be4d --- /dev/null +++ b/src/setup.ts @@ -0,0 +1,12 @@ +/** + * This file is imported for its side effects to patch the environment + * for TensorFlow.js before any other library code runs. + * + * It ensures that by the time TensorFlow.js is imported by any other + * module, the necessary compatibility fixes for the current Node.js + * environment are already in place. + */ +import { applyTensorFlowPatch } from './utils/textEncoding.js' + +// Apply the TensorFlow.js platform patch if needed +applyTensorFlowPatch() diff --git a/src/storage/fileSystemStorage.ts b/src/storage/fileSystemStorage.ts index 19d77476..8a448f98 100644 --- a/src/storage/fileSystemStorage.ts +++ b/src/storage/fileSystemStorage.ts @@ -1,12 +1,47 @@ import { GraphVerb, HNSWNoun, StorageAdapter } from '../coreTypes.js' -// Import Node.js built-in modules -// Using dynamic imports for compatibility with ES modules +// Dynamically and asynchronously load Node.js modules at the top level. +// This ensures they are available as soon as this module is imported, +// preventing race conditions with dependencies like TensorFlow.js. let fs: any let path: any -// We'll initialize these modules in the init() method -// No synchronous loading here to avoid issues with ES modules +const nodeModulesPromise = (async () => { + // A reliable check for a Node.js environment. + const isNode = + typeof process !== 'undefined' && + process.versions != null && + process.versions.node != null + + if (!isNode) { + return { fs: null, path: null } + } + + try { + // Use the 'node:' prefix for unambiguous importing of built-in modules. + const fsModule = await import('node:fs') + const pathModule = await import('node:path') + // Return the modules, preferring the default export if it exists. + return { + fs: fsModule.default || fsModule, + path: pathModule.default || pathModule + } + } catch (error) { + console.error( + 'FileSystemStorage: Failed to load Node.js modules. This adapter is not supported in this environment.', + error + ) + return { fs: null, path: null } + } +})() + +// Immediately assign the modules once the promise resolves. +nodeModulesPromise.then((modules) => { + fs = modules.fs + path = modules.path +}) + +// --- End of Refactored Code --- // Constants for directory and file names const ROOT_DIR = 'brainy-data' @@ -63,80 +98,17 @@ export class FileSystemStorage implements StorageAdapter { return } + // Wait for the top-level module loading to complete. + await nodeModulesPromise + + // Check if the modules were loaded successfully. + if (!fs || !path) { + throw new Error( + 'FileSystemStorage requires a Node.js environment, but `fs` and `path` modules could not be loaded.' + ) + } + try { - // Check if fs and path modules are available and have required methods - if (!fs || !path || typeof path.resolve !== 'function') { - console.log( - 'Node.js modules not properly loaded, attempting to load them now' - ) - - // Try multiple approaches to load the modules - const loadAttempts = [ - // Attempt 1: Use dynamic import - async () => { - console.log( - 'Attempting to load Node.js modules with dynamic import' - ) - const fsModule = await import('fs') - const pathModule = await import('path') - - const fsResolved = fsModule.default || fsModule - const pathResolved = pathModule.default || pathModule - - if (!pathResolved || typeof pathResolved.resolve !== 'function') { - throw new Error( - 'path.resolve is not a function after dynamic import' - ) - } - - return { fs: fsResolved, path: pathResolved } - }, - - // Attempt 2: Use dynamic import with node: prefix - async () => { - console.log( - 'Attempting to load Node.js modules with dynamic import("node:...")' - ) - const fsModule = await import('node:fs') - const pathModule = await import('node:path') - - const fsResolved = fsModule.default || fsModule - const pathResolved = pathModule.default || pathModule - - if (!pathResolved || typeof pathResolved.resolve !== 'function') { - throw new Error( - 'path.resolve is not a function after dynamic import("node:path")' - ) - } - - return { fs: fsResolved, path: pathResolved } - } - ] - - // Try each loading method until one succeeds - let lastError = null - for (const loadAttempt of loadAttempts) { - try { - const modules = await loadAttempt() - fs = modules.fs - path = modules.path - console.log('Successfully loaded Node.js modules') - break - } catch (error) { - lastError = error - console.warn(`Module loading attempt failed:`, error) - // Continue to the next attempt - } - } - - // If all attempts failed, throw an error - if (!fs || !path || typeof path.resolve !== 'function') { - throw new Error( - `Failed to import Node.js modules after multiple attempts: ${lastError}. This adapter requires a Node.js environment.` - ) - } - } - // Now set up the directory paths const rootDir = this.rootDir || process.cwd() this.rootDir = path.resolve(rootDir, ROOT_DIR) @@ -158,8 +130,6 @@ export class FileSystemStorage implements StorageAdapter { await this.ensureDirectoryExists(this.nounsDir) await this.ensureDirectoryExists(this.verbsDir) await this.ensureDirectoryExists(this.metadataDir) - - // Create noun type directories await this.ensureDirectoryExists(this.personDir) await this.ensureDirectoryExists(this.placeDir) await this.ensureDirectoryExists(this.thingDir) @@ -169,841 +139,352 @@ export class FileSystemStorage implements StorageAdapter { await this.ensureDirectoryExists(this.defaultDir) this.isInitialized = true - } catch (error) { - console.error('Failed to initialize file system storage:', error) - throw new Error(`Failed to initialize file system storage: ${error}`) + } catch (error: any) { + console.error('Error initializing FileSystemStorage:', error) + throw error } } - /** - * Save a node to storage - */ - public async saveNoun(noun: HNSWNoun): Promise { - await this.ensureInitialized() - - try { - // Convert connections Map to a serializable format - const serializableNode = { - ...noun, - connections: this.mapToObject(noun.connections, (set) => - Array.from(set as Set) - ) - } - - // Get the appropriate directory based on the node's metadata - const nodeDir = await this.getNodeDirectory(noun.id) - - const filePath = path.join(nodeDir, `${noun.id}.json`) - await fs.promises.writeFile( - filePath, - JSON.stringify(serializableNode, null, 2), - 'utf8' - ) - } catch (error) { - console.error(`Failed to save node ${noun.id}:`, error) - throw new Error(`Failed to save node ${noun.id}: ${error}`) - } - } - - /** - * Get a node from storage - */ - public async getNoun(id: string): Promise { - await this.ensureInitialized() - - try { - // Get the appropriate directory based on the node's metadata - const nodeDir = await this.getNodeDirectory(id) - - const filePath = path.join(nodeDir, `${id}.json`) - - // Check if a file exists - try { - await fs.promises.access(filePath) - } catch { - // If the file doesn't exist in the expected directory, try the default directory - if (nodeDir !== this.defaultDir) { - const defaultFilePath = path.join(this.defaultDir, `${id}.json`) - try { - await fs.promises.access(defaultFilePath) - // If found in default directory, use that path - const data = await fs.promises.readFile(defaultFilePath, 'utf8') - const parsedNode = JSON.parse(data) - - // Convert serialized connections back to Map> - const connections = new Map>() - for (const [level, nodeIds] of Object.entries( - parsedNode.connections - )) { - connections.set(Number(level), new Set(nodeIds as string[])) - } - - return { - id: parsedNode.id, - vector: parsedNode.vector, - connections - } - } catch { - // If not found in default directory either, try all noun type directories - const directories = [ - this.personDir, - this.placeDir, - this.thingDir, - this.eventDir, - this.conceptDir, - this.contentDir - ] - - for (const dir of directories) { - if (dir === nodeDir) continue // Skip the already checked directory - - const dirFilePath = path.join(dir, `${id}.json`) - try { - await fs.promises.access(dirFilePath) - // If found in this directory, use that path - const data = await fs.promises.readFile(dirFilePath, 'utf8') - const parsedNode = JSON.parse(data) - - // Convert serialized connections back to Map> - const connections = new Map>() - for (const [level, nodeIds] of Object.entries( - parsedNode.connections - )) { - connections.set(Number(level), new Set(nodeIds as string[])) - } - - return { - id: parsedNode.id, - vector: parsedNode.vector, - connections - } - } catch { - // Continue to the next directory - } - } - - return null // File doesn't exist in any directory - } - } - return null // File doesn't exist - } - - const data = await fs.promises.readFile(filePath, 'utf8') - const parsedNode = JSON.parse(data) - - // Convert serialized connections back to Map> - const connections = new Map>() - for (const [level, nodeIds] of Object.entries(parsedNode.connections)) { - connections.set(Number(level), new Set(nodeIds as string[])) - } - - return { - id: parsedNode.id, - vector: parsedNode.vector, - connections - } - } catch (error) { - console.error(`Failed to get node ${id}:`, error) - return null - } - } - - /** - * Get nodes by noun type - * @param nounType The noun type to filter by - * @returns Promise that resolves to an array of nodes of the specified noun type - */ - public async getNounsByNounType(nounType: string): Promise { - await this.ensureInitialized() - - try { - // Determine the directory based on the noun type - let dir: string - switch (nounType) { - case 'person': - dir = this.personDir - break - case 'place': - dir = this.placeDir - break - case 'thing': - dir = this.thingDir - break - case 'event': - dir = this.eventDir - break - case 'concept': - dir = this.conceptDir - break - case 'content': - dir = this.contentDir - break - default: - dir = this.defaultDir - } - - const nodes: HNSWNoun[] = [] - - try { - const files = await fs.promises.readdir(dir) - const nodePromises = files - .filter((file: string) => file.endsWith('.json')) - .map((file: string) => { - // Use the file path directly instead of getNode to avoid redundant searches - return this.readNodeFromFile(path.join(dir, file)) - }) - - const dirNodes = await Promise.all(nodePromises) - nodes.push( - ...dirNodes.filter((node): node is HNSWNoun => node !== null) - ) - } catch (dirError) { - // If directory doesn't exist or can't be read, log a warning - console.warn( - `Could not read directory for noun type ${nounType}:`, - dirError - ) - } - - return nodes - } catch (error) { - console.error(`Failed to get nodes for noun type ${nounType}:`, error) - throw new Error(`Failed to get nodes for noun type ${nounType}: ${error}`) - } - } - - /** - * Get all nodes from storage - */ - public async getAllNouns(): Promise { - await this.ensureInitialized() - - try { - // Get all noun types - const nounTypes = [ - 'person', - 'place', - 'thing', - 'event', - 'concept', - 'content', - 'default' - ] - - // Run searches in parallel for all noun types - const nodePromises = nounTypes.map((nounType) => - this.getNounsByNounType(nounType) - ) - const nodeArrays = await Promise.all(nodePromises) - - // Combine all results - const allNodes: HNSWNoun[] = [] - for (const nodes of nodeArrays) { - allNodes.push(...nodes) - } - - return allNodes - } catch (error) { - console.error('Failed to get all nodes:', error) - throw new Error(`Failed to get all nodes: ${error}`) - } - } - - /** - * Read a node from a file - */ - private async readNodeFromFile(filePath: string): Promise { - try { - const data = await fs.promises.readFile(filePath, 'utf8') - const parsedNode = JSON.parse(data) - - // Convert serialized connections back to Map> - const connections = new Map>() - for (const [level, nodeIds] of Object.entries(parsedNode.connections)) { - connections.set(Number(level), new Set(nodeIds as string[])) - } - - return { - id: parsedNode.id, - vector: parsedNode.vector, - connections - } - } catch (error) { - console.error(`Failed to read node from file ${filePath}:`, error) - return null - } - } - - /** - * Delete a node from storage - */ - public async deleteNoun(id: string): Promise { - await this.ensureInitialized() - - try { - // Get the appropriate directory based on the node's metadata - const nodeDir = await this.getNodeDirectory(id) - - const filePath = path.join(nodeDir, `${id}.json`) - - // Check if a file exists before attempting to delete - try { - await fs.promises.access(filePath) - await fs.promises.unlink(filePath) - return // File found and deleted - } catch { - // If the file doesn't exist in the expected directory, try the default directory - if (nodeDir !== this.defaultDir) { - const defaultFilePath = path.join(this.defaultDir, `${id}.json`) - try { - await fs.promises.access(defaultFilePath) - await fs.promises.unlink(defaultFilePath) - return // File found and deleted - } catch { - // If not found in default directory either, try all noun type directories - const directories = [ - this.personDir, - this.placeDir, - this.thingDir, - this.eventDir, - this.conceptDir, - this.contentDir - ] - - for (const dir of directories) { - if (dir === nodeDir) continue // Skip the already checked directory - - const dirFilePath = path.join(dir, `${id}.json`) - try { - await fs.promises.access(dirFilePath) - await fs.promises.unlink(dirFilePath) - return // File found and deleted - } catch { - // Continue to the next directory - } - } - - return // File doesn't exist in any directory, nothing to delete - } - } - return // File doesn't exist, nothing to delete - } - } catch (error) { - console.error(`Failed to delete node ${id}:`, error) - throw new Error(`Failed to delete node ${id}: ${error}`) - } - } - - /** - * Save an edge to storage - */ - public async saveVerb(verb: GraphVerb): Promise { - await this.ensureInitialized() - - try { - // Convert connections Map to a serializable format - const serializableEdge = { - ...verb, - connections: this.mapToObject(verb.connections, (set) => - Array.from(set as Set) - ) - } - - const filePath = path.join(this.verbsDir, `${verb.id}.json`) - await fs.promises.writeFile( - filePath, - JSON.stringify(serializableEdge, null, 2), - 'utf8' - ) - } catch (error) { - console.error(`Failed to save edge ${verb.id}:`, error) - throw new Error(`Failed to save edge ${verb.id}: ${error}`) - } - } - - /** - * Get an edge from storage - */ - public async getVerb(id: string): Promise { - await this.ensureInitialized() - - try { - const filePath = path.join(this.verbsDir, `${id}.json`) - - // Check if a file exists - try { - await fs.promises.access(filePath) - } catch { - return null // File doesn't exist - } - - const data = await fs.promises.readFile(filePath, 'utf8') - const parsedEdge = JSON.parse(data) - - // Convert serialized connections back to Map> - const connections = new Map>() - for (const [level, nodeIds] of Object.entries(parsedEdge.connections)) { - connections.set(Number(level), new Set(nodeIds as string[])) - } - - return { - id: parsedEdge.id, - vector: parsedEdge.vector, - connections, - sourceId: parsedEdge.sourceId, - targetId: parsedEdge.targetId, - type: parsedEdge.type, - weight: parsedEdge.weight, - metadata: parsedEdge.metadata - } - } catch (error) { - console.error(`Failed to get edge ${id}:`, error) - return null - } - } - - /** - * Get all edges from storage - */ - public async getAllVerbs(): Promise { - await this.ensureInitialized() - - try { - const files = await fs.promises.readdir(this.verbsDir) - const edgePromises = files - .filter((file: string) => file.endsWith('.json')) - .map((file: string) => { - const id = path.basename(file, '.json') - return this.getVerb(id) - }) - - const edges = await Promise.all(edgePromises) - return edges.filter((edge): edge is GraphVerb => edge !== null) - } catch (error) { - console.error('Failed to get all edges:', error) - throw new Error(`Failed to get all edges: ${error}`) - } - } - - /** - * Get edges by source node ID - */ - public async getVerbsBySource(sourceId: string): Promise { - await this.ensureInitialized() - - try { - const allEdges = await this.getAllVerbs() - return allEdges.filter((edge) => edge.sourceId === sourceId) - } catch (error) { - console.error(`Failed to get edges by source ${sourceId}:`, error) - throw new Error(`Failed to get edges by source ${sourceId}: ${error}`) - } - } - - /** - * Get edges by target node ID - */ - public async getVerbsByTarget(targetId: string): Promise { - await this.ensureInitialized() - - try { - const allEdges = await this.getAllVerbs() - return allEdges.filter((edge) => edge.targetId === targetId) - } catch (error) { - console.error(`Failed to get edges by target ${targetId}:`, error) - throw new Error(`Failed to get edges by target ${targetId}: ${error}`) - } - } - - /** - * Get edges by type - */ - public async getVerbsByType(type: string): Promise { - await this.ensureInitialized() - - try { - const allEdges = await this.getAllVerbs() - return allEdges.filter((edge) => edge.type === type) - } catch (error) { - console.error(`Failed to get edges by type ${type}:`, error) - throw new Error(`Failed to get edges by type ${type}: ${error}`) - } - } - - /** - * Delete an edge from storage - */ - public async deleteVerb(id: string): Promise { - await this.ensureInitialized() - - try { - const filePath = path.join(this.verbsDir, `${id}.json`) - - // Check if a file exists before attempting to delete - try { - await fs.promises.access(filePath) - } catch { - return // File doesn't exist, nothing to delete - } - - await fs.promises.unlink(filePath) - } catch (error) { - console.error(`Failed to delete edge ${id}:`, error) - throw new Error(`Failed to delete edge ${id}: ${error}`) - } - } - - /** - * Save metadata to storage - */ - public async saveMetadata(id: string, metadata: any): Promise { - await this.ensureInitialized() - - try { - const filePath = path.join(this.metadataDir, `${id}.json`) - await fs.promises.writeFile( - filePath, - JSON.stringify(metadata, null, 2), - 'utf8' - ) - } catch (error) { - console.error(`Failed to save metadata for ${id}:`, error) - throw new Error(`Failed to save metadata for ${id}: ${error}`) - } - } - - /** - * Get metadata from storage - */ - public async getMetadata(id: string): Promise { - await this.ensureInitialized() - - try { - const filePath = path.join(this.metadataDir, `${id}.json`) - - // Check if a file exists - try { - await fs.promises.access(filePath) - } catch { - return null // File doesn't exist - } - - const data = await fs.promises.readFile(filePath, 'utf8') - return JSON.parse(data) - } catch (error) { - console.error(`Failed to get metadata for ${id}:`, error) - return null - } - } - - /** - * Clear all data from storage - */ - public async clear(): Promise { - await this.ensureInitialized() - - try { - // Delete and recreate the nodes, edges, and metadata directories - await this.deleteDirectory(this.nounsDir) - await this.deleteDirectory(this.verbsDir) - await this.deleteDirectory(this.metadataDir) - - await this.ensureDirectoryExists(this.nounsDir) - await this.ensureDirectoryExists(this.verbsDir) - await this.ensureDirectoryExists(this.metadataDir) - - // Create noun type directories - await this.ensureDirectoryExists(this.personDir) - await this.ensureDirectoryExists(this.placeDir) - await this.ensureDirectoryExists(this.thingDir) - await this.ensureDirectoryExists(this.eventDir) - await this.ensureDirectoryExists(this.conceptDir) - await this.ensureDirectoryExists(this.contentDir) - await this.ensureDirectoryExists(this.defaultDir) - } catch (error) { - console.error('Failed to clear storage:', error) - throw new Error(`Failed to clear storage: ${error}`) - } - } - - /** - * Ensure the storage adapter is initialized - */ - private async ensureInitialized(): Promise { - if (!this.isInitialized) { - await this.init() - } - } - - /** - * Ensure a directory exists, creating it if necessary - */ private async ensureDirectoryExists(dirPath: string): Promise { try { - await fs.promises.access(dirPath) - } catch { - // Directory doesn't exist, create it await fs.promises.mkdir(dirPath, { recursive: true }) + } catch (error: any) { + // Ignore EEXIST error, which means the directory already exists + if (error.code !== 'EEXIST') { + throw error + } } } - /** - * Delete a directory and all its contents recursively - */ - private async deleteDirectory(dirPath: string): Promise { - try { - const files = await fs.promises.readdir(dirPath) + private getNounPath(id: string, nounType?: string): string { + let typeDir = this.defaultDir + if (nounType) { + switch (nounType.toLowerCase()) { + case 'person': + typeDir = this.personDir + break + case 'place': + typeDir = this.placeDir + break + case 'thing': + typeDir = this.thingDir + break + case 'event': + typeDir = this.eventDir + break + case 'concept': + typeDir = this.conceptDir + break + case 'content': + typeDir = this.contentDir + break + default: + typeDir = this.defaultDir + } + } + return path.join(typeDir, `${id}.json`) + } - for (const file of files) { - const filePath = path.join(dirPath, file) - const stats = await fs.promises.stat(filePath) + public async saveNoun( + noun: HNSWNoun & { metadata?: { noun?: string } } + ): Promise { + if (!this.isInitialized) await this.init() + const nounType = (noun as any).metadata?.noun + const filePath = this.getNounPath(noun.id, nounType) + await this.ensureDirectoryExists(path.dirname(filePath)) + await fs.promises.writeFile(filePath, JSON.stringify(noun, null, 2)) + } - if (stats.isDirectory()) { - // Recursively delete subdirectories - await this.deleteDirectory(filePath) - } else { - // Delete files - await fs.promises.unlink(filePath) + public async getNoun(id: string): Promise { + if (!this.isInitialized) await this.init() + const nounDirs = [ + this.personDir, + this.placeDir, + this.thingDir, + this.eventDir, + this.conceptDir, + this.contentDir, + this.defaultDir + ] + for (const dir of nounDirs) { + const filePath = path.join(dir, `${id}.json`) + try { + const data = await fs.promises.readFile(filePath, 'utf-8') + return JSON.parse(data) + } catch (error: any) { + if (error.code !== 'ENOENT') { + console.error(`Error reading noun ${id}:`, error) } } + } + return null + } - // After all contents are deleted, remove the directory itself - await fs.promises.rmdir(dirPath) - } catch (error) { - // If the directory doesn't exist, that's fine - if ((error as NodeJS.ErrnoException).code !== 'ENOENT') { + public async deleteNoun(id: string): Promise { + if (!this.isInitialized) await this.init() + const noun = await this.getNoun(id) + if (noun) { + const nounType = (noun as any).metadata?.noun + const filePath = this.getNounPath(id, nounType) + try { + await fs.promises.unlink(filePath) + } catch (error: any) { + if (error.code !== 'ENOENT') { + console.error(`Error deleting noun file ${filePath}:`, error) + throw error + } + } + } + } + + public async getAllNouns(): Promise { + if (!this.isInitialized) await this.init() + const allNouns: HNSWNoun[] = [] + const nounDirs = [ + this.personDir, + this.placeDir, + this.thingDir, + this.eventDir, + this.conceptDir, + this.contentDir, + this.defaultDir + ] + for (const dir of nounDirs) { + try { + const files = await fs.promises.readdir(dir) + for (const file of files) { + if (file.endsWith('.json')) { + const filePath = path.join(dir, file) + const data = await fs.promises.readFile(filePath, 'utf-8') + allNouns.push(JSON.parse(data)) + } + } + } catch (error: any) { + if (error.code !== 'ENOENT') { + console.error(`Error reading directory ${dir}:`, error) + } + } + } + return allNouns + } + + /** + * Get nouns by noun type + * @param nounType The noun type to filter by + * @returns Promise that resolves to an array of nouns of the specified noun type + */ + public async getNounsByNounType(nounType: string): Promise { + if (!this.isInitialized) await this.init() + + let typeDir: string + switch (nounType.toLowerCase()) { + case 'person': + typeDir = this.personDir + break + case 'place': + typeDir = this.placeDir + break + case 'thing': + typeDir = this.thingDir + break + case 'event': + typeDir = this.eventDir + break + case 'concept': + typeDir = this.conceptDir + break + case 'content': + typeDir = this.contentDir + break + default: + typeDir = this.defaultDir + } + + const nouns: HNSWNoun[] = [] + try { + const files = await fs.promises.readdir(typeDir) + for (const file of files) { + if (file.endsWith('.json')) { + const filePath = path.join(typeDir, file) + const data = await fs.promises.readFile(filePath, 'utf-8') + nouns.push(JSON.parse(data)) + } + } + } catch (error: any) { + if (error.code !== 'ENOENT') { + console.error(`Error reading directory ${typeDir}:`, error) + } + } + + return nouns + } + + public async saveVerb(verb: GraphVerb): Promise { + if (!this.isInitialized) await this.init() + const filePath = path.join(this.verbsDir, `${verb.id}.json`) + await fs.promises.writeFile(filePath, JSON.stringify(verb, null, 2)) + } + + /** + * Get a verb by its ID + * @param id The ID of the verb to retrieve + * @returns Promise that resolves to the verb or null if not found + */ + public async getVerb(id: string): Promise { + if (!this.isInitialized) await this.init() + const filePath = path.join(this.verbsDir, `${id}.json`) + try { + const data = await fs.promises.readFile(filePath, 'utf-8') + return JSON.parse(data) + } catch (error: any) { + if (error.code !== 'ENOENT') { + console.error(`Error reading verb ${id}:`, error) + } + return null + } + } + + public async getVerbsBySource(sourceId: string): Promise { + if (!this.isInitialized) await this.init() + const allVerbs = await this.getAllVerbs() + return allVerbs.filter((verb) => verb.sourceId === sourceId) + } + + /** + * Get verbs by target ID + * @param targetId The target ID to filter by + * @returns Promise that resolves to an array of verbs with the specified target ID + */ + public async getVerbsByTarget(targetId: string): Promise { + if (!this.isInitialized) await this.init() + const allVerbs = await this.getAllVerbs() + return allVerbs.filter((verb) => verb.targetId === targetId) + } + + /** + * Get verbs by type + * @param type The verb type to filter by + * @returns Promise that resolves to an array of verbs of the specified type + */ + public async getVerbsByType(type: string): Promise { + if (!this.isInitialized) await this.init() + const allVerbs = await this.getAllVerbs() + return allVerbs.filter((verb) => verb.type === type) + } + + public async getAllVerbs(): Promise { + if (!this.isInitialized) await this.init() + const allVerbs: GraphVerb[] = [] + try { + const files = await fs.promises.readdir(this.verbsDir) + for (const file of files) { + if (file.endsWith('.json')) { + const filePath = path.join(this.verbsDir, file) + const data = await fs.promises.readFile(filePath, 'utf-8') + allVerbs.push(JSON.parse(data)) + } + } + } catch (error: any) { + if (error.code !== 'ENOENT') { + console.error(`Error reading verbs directory ${this.verbsDir}:`, error) + } + } + return allVerbs + } + + public async deleteVerb(id: string): Promise { + if (!this.isInitialized) await this.init() + const filePath = path.join(this.verbsDir, `${id}.json`) + try { + await fs.promises.unlink(filePath) + } catch (error: any) { + if (error.code !== 'ENOENT') { + console.error(`Error deleting verb file ${filePath}:`, error) throw error } } } /** - * Count the number of JSON files in a directory + * Save metadata for an entity + * @param id The ID of the entity + * @param metadata The metadata to save */ - private async countFilesInDirectory(dirPath: string): Promise { + public async saveMetadata(id: string, metadata: any): Promise { + if (!this.isInitialized) await this.init() + const filePath = path.join(this.metadataDir, `${id}.json`) + await fs.promises.writeFile(filePath, JSON.stringify(metadata, null, 2)) + } + + /** + * Get metadata for an entity + * @param id The ID of the entity + * @returns Promise that resolves to the metadata or null if not found + */ + public async getMetadata(id: string): Promise { + if (!this.isInitialized) await this.init() + const filePath = path.join(this.metadataDir, `${id}.json`) try { - const files = await fs.promises.readdir(dirPath) - return files.filter((file: string) => file.endsWith('.json')).length - } catch (error) { - // If the directory doesn't exist, return 0 - if ((error as NodeJS.ErrnoException).code === 'ENOENT') { - return 0 + const data = await fs.promises.readFile(filePath, 'utf-8') + return JSON.parse(data) + } catch (error: any) { + if (error.code !== 'ENOENT') { + console.error(`Error reading metadata for ${id}:`, error) } - throw error + return null } } - /** - * Convert a Map to a plain object for serialization - */ - private mapToObject( - map: Map, - valueTransformer: (value: V) => any = (v) => v - ): Record { - const obj: Record = {} - for (const [key, value] of map.entries()) { - obj[key.toString()] = valueTransformer(value) - } - return obj + public async clear(): Promise { + if (!this.isInitialized) await this.init() + await fs.promises.rm(this.rootDir, { recursive: true, force: true }) + this.isInitialized = false // Reset state + await this.init() // Re-create directories } - /** - * Get the appropriate directory for a node based on its metadata - */ - private async getNodeDirectory(id: string): Promise { - try { - // Try to get the metadata for the node - const metadata = await this.getMetadata(id) - - // If metadata exists and has a noun field, use the corresponding directory - if (metadata && metadata.noun) { - switch (metadata.noun) { - case 'person': - return this.personDir - case 'place': - return this.placeDir - case 'thing': - return this.thingDir - case 'event': - return this.eventDir - case 'concept': - return this.conceptDir - case 'content': - return this.contentDir - default: - return this.defaultDir - } - } - - // If no metadata or no noun field, use the default directory - return this.defaultDir - } catch (error) { - // If there's an error getting the metadata, use the default directory - return this.defaultDir - } - } - - /** - * Get information about storage usage and capacity - */ public async getStorageStatus(): Promise<{ type: string used: number quota: number | null details?: Record }> { - await this.ensureInitialized() - - try { - // Calculate the total size of all files in the storage directories - let totalSize = 0 - - // Helper function to calculate directory size - const calculateDirSize = async (dirPath: string): Promise => { - let size = 0 - try { - const files = await fs.promises.readdir(dirPath) - - for (const file of files) { - const filePath = path.join(dirPath, file) - const stats = await fs.promises.stat(filePath) - - if (stats.isDirectory()) { - size += await calculateDirSize(filePath) - } else { - size += stats.size - } - } - } catch (error) { - console.warn(`Error calculating size for ${dirPath}:`, error) - } - return size - } - - // Calculate size for each directory - const nodesDirSize = await calculateDirSize(this.nounsDir) - const edgesDirSize = await calculateDirSize(this.verbsDir) - const metadataDirSize = await calculateDirSize(this.metadataDir) - - // Calculate sizes of noun type directories - const personDirSize = await calculateDirSize(this.personDir) - const placeDirSize = await calculateDirSize(this.placeDir) - const thingDirSize = await calculateDirSize(this.thingDir) - const eventDirSize = await calculateDirSize(this.eventDir) - const conceptDirSize = await calculateDirSize(this.conceptDir) - const contentDirSize = await calculateDirSize(this.contentDir) - const defaultDirSize = await calculateDirSize(this.defaultDir) - - // Note: The noun type directories are subdirectories of the nodes directory, - // so their sizes are already included in nodesDirSize. - // We don't need to add them again to avoid double counting. - totalSize = nodesDirSize + edgesDirSize + metadataDirSize - - // Get filesystem information - let quota = null - let details: { - nounTypes?: { - person: { size: number; count: number } - place: { size: number; count: number } - thing: { size: number; count: number } - event: { size: number; count: number } - concept: { size: number; count: number } - content: { size: number; count: number } - default: { size: number; count: number } - } - availableSpace?: number - totalSpace?: number - freePercentage?: number - } = { - nounTypes: { - person: { - size: personDirSize, - count: await this.countFilesInDirectory(this.personDir) - }, - place: { - size: placeDirSize, - count: await this.countFilesInDirectory(this.placeDir) - }, - thing: { - size: thingDirSize, - count: await this.countFilesInDirectory(this.thingDir) - }, - event: { - size: eventDirSize, - count: await this.countFilesInDirectory(this.eventDir) - }, - concept: { - size: conceptDirSize, - count: await this.countFilesInDirectory(this.conceptDir) - }, - content: { - size: contentDirSize, - count: await this.countFilesInDirectory(this.contentDir) - }, - default: { - size: defaultDirSize, - count: await this.countFilesInDirectory(this.defaultDir) - } - } - } + if (!this.isInitialized) await this.init() + const calculateSize = async (dirPath: string): Promise => { + let size = 0 try { - // Try to get disk space information - const stats = await fs.promises.statfs(this.rootDir) - if (stats) { - const availableSpace = stats.bavail * stats.bsize - const totalSpace = stats.blocks * stats.bsize - - quota = totalSpace - details = { - availableSpace, - totalSpace, - freePercentage: (availableSpace / totalSpace) * 100 + const files = await fs.promises.readdir(dirPath, { + withFileTypes: true + }) + for (const file of files) { + const fullPath = path.join(dirPath, file.name) + if (file.isDirectory()) { + size += await calculateSize(fullPath) + } else { + const stats = await fs.promises.stat(fullPath) + size += stats.size } } - } catch (error) { - console.warn('Unable to get filesystem stats:', error) - // If statfs is not available, try to use df command on Unix-like systems - try { - const { exec } = await import('child_process') - const util = await import('util') - const execPromise = util.promisify(exec) - - const { stdout } = await execPromise(`df -k "${this.rootDir}"`) - const lines = stdout.trim().split('\n') - if (lines.length > 1) { - const parts = lines[1].split(/\s+/) - if (parts.length >= 4) { - const totalKB = parseInt(parts[1], 10) - const usedKB = parseInt(parts[2], 10) - const availableKB = parseInt(parts[3], 10) - - quota = totalKB * 1024 - details = { - availableSpace: availableKB * 1024, - totalSpace: totalKB * 1024, - freePercentage: (availableKB / totalKB) * 100 - } - } - } - } catch (dfError) { - console.warn('Unable to get disk space using df command:', dfError) + } catch (error: any) { + if (error.code !== 'ENOENT') { + console.error(`Could not calculate size for ${dirPath}:`, error) } } + return size + } - return { - type: 'filesystem', - used: totalSize, - quota, - details - } - } catch (error) { - console.error('Failed to get storage status:', error) - return { - type: 'filesystem', - used: 0, - quota: null, - details: { error: String(error) } + const totalSize = await calculateSize(this.rootDir) + const nouns = await this.getAllNouns() + const verbs = await this.getAllVerbs() + + return { + type: 'FileSystem', + used: totalSize, + quota: null, // File system quota is not easily available from Node.js + details: { + rootDir: this.rootDir, + nounCount: nouns.length, + verbCount: verbs.length } } } diff --git a/src/types/tensorflowTypes.ts b/src/types/tensorflowTypes.ts index b7381dfb..f616395c 100644 --- a/src/types/tensorflowTypes.ts +++ b/src/types/tensorflowTypes.ts @@ -5,8 +5,9 @@ // Define the shape of the util object used for TensorFlow.js compatibility export interface TensorFlowUtilObject { - isFloat32Array: (arr: unknown) => boolean - isTypedArray: (arr: unknown) => boolean + isFloat32Array?: (arr: unknown) => boolean + isTypedArray?: (arr: unknown) => boolean + [key: string]: unknown } @@ -14,12 +15,14 @@ export interface TensorFlowUtilObject { export interface PlatformNodeObject { isFloat32Array?: (arr: unknown) => boolean isTypedArray?: (arr: unknown) => boolean + [key: string]: unknown } // Define the shape of the tf object that might exist in global export interface TensorFlowObject { util?: TensorFlowUtilObject + [key: string]: unknown } @@ -32,4 +35,15 @@ declare global { interface WorkerGlobalScope { importTensorFlow?: () => Promise } + + // Declare types for the global object and globalThis + var global: { + util?: TensorFlowUtilObject + [key: string]: any + } + + var globalThis: { + util?: TensorFlowUtilObject + [key: string]: any + } } diff --git a/src/unified.ts b/src/unified.ts index dc99202f..e00d8527 100644 --- a/src/unified.ts +++ b/src/unified.ts @@ -4,13 +4,6 @@ * Environment detection is handled here and made available to all components */ -// Import unified text encoding utilities -// This needs to be imported first to ensure it's loaded before TensorFlow.js -import { applyTensorFlowPatch } from './utils/textEncoding.js' - -// Apply the TensorFlow.js platform patch if needed -applyTensorFlowPatch() - // Export environment information export const environment = { isBrowser: typeof window !== 'undefined', diff --git a/src/utils/embedding.ts b/src/utils/embedding.ts index fcceccb7..b0ca71de 100644 --- a/src/utils/embedding.ts +++ b/src/utils/embedding.ts @@ -34,7 +34,88 @@ export class UniversalSentenceEncoder implements EmbeddingModel { return } - // No compatibility patches needed - TensorFlow.js now works correctly with Node.js 24+ + // Add polyfill for isFloat32Array in Node.js 24.4.0 + // This fixes the "Cannot read properties of undefined (reading 'isFloat32Array')" error + if (typeof global !== 'undefined') { + try { + // Define a custom PlatformNode class + class PlatformNode { + util: any + textEncoder: TextEncoder + textDecoder: TextDecoder + + constructor() { + // Create a util object with necessary methods + this.util = { + // Add isFloat32Array and isTypedArray directly to util + isFloat32Array: (arr: any) => { + return !!( + arr instanceof Float32Array || + (arr && + Object.prototype.toString.call(arr) === + '[object Float32Array]') + ) + }, + isTypedArray: (arr: any) => { + return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView)) + }, + // Use native TextEncoder and TextDecoder + TextEncoder: TextEncoder, + TextDecoder: TextDecoder + } + + // Initialize encoders using native constructors + this.textEncoder = new TextEncoder() + this.textDecoder = new TextDecoder() + } + + // Define isFloat32Array directly on the instance + isFloat32Array(arr: any) { + return !!( + arr instanceof Float32Array || + (arr && + Object.prototype.toString.call(arr) === '[object Float32Array]') + ) + } + + // Define isTypedArray directly on the instance + isTypedArray(arr: any) { + return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView)) + } + } + + // Assign the PlatformNode class to the global object + ;(global as any).PlatformNode = PlatformNode + + // Also create an instance and assign it to global.platformNode + ;(global as any).platformNode = new PlatformNode() + } catch (error) { + console.warn('Failed to define global PlatformNode class:', error) + } + + // Ensure the util object exists + if (!global.util) { + global.util = {} + } + + // Add isFloat32Array method if it doesn't exist + if (!global.util.isFloat32Array) { + global.util.isFloat32Array = (obj: any) => { + return !!( + obj instanceof Float32Array || + (obj && + Object.prototype.toString.call(obj) === '[object Float32Array]') + ) + } + } + + // Add isTypedArray method if it doesn't exist + if (!global.util.isTypedArray) { + global.util.isTypedArray = (obj: any) => { + return !!(ArrayBuffer.isView(obj) && !(obj instanceof DataView)) + } + } + } } /** diff --git a/src/utils/environment.ts b/src/utils/environment.ts index af716ae6..4be9d23d 100644 --- a/src/utils/environment.ts +++ b/src/utils/environment.ts @@ -60,7 +60,7 @@ export async function areWorkerThreadsAvailable(): Promise { export function areWorkerThreadsAvailableSync(): boolean { if (!isNode()) return false - // In Node.js 24.3.0+, worker_threads is always available + // In Node.js 24.4.0+, worker_threads is always available return parseInt(process.versions.node.split('.')[0]) >= 24 } diff --git a/src/utils/tensorflowUtils.ts b/src/utils/tensorflowUtils.ts index 04c374eb..d0139476 100644 --- a/src/utils/tensorflowUtils.ts +++ b/src/utils/tensorflowUtils.ts @@ -10,12 +10,8 @@ import type { PlatformNodeObject } from '../types/tensorflowTypes.js' -// Import the unified text encoding utilities -import { applyTensorFlowPatch } from './textEncoding.js' - -// Apply the TensorFlow.js platform patch if needed -// This will define a global PlatformNode class that uses our text encoding utilities -applyTensorFlowPatch() +// Note: TensorFlow.js platform patch is applied in setup.ts +// This ensures the global PlatformNode class uses our text encoding utilities /** * Check if an array is a Float32Array diff --git a/src/utils/textEncoding.ts b/src/utils/textEncoding.ts index 8bcd0c8d..8d64a637 100644 --- a/src/utils/textEncoding.ts +++ b/src/utils/textEncoding.ts @@ -2,140 +2,49 @@ * Unified Text Encoding Utilities * * This module provides a consistent way to handle text encoding/decoding across all environments - * without relying on TextEncoder/TextDecoder polyfills or patches. + * using the native TextEncoder/TextDecoder APIs. */ -/** - * A simple text encoder that works in all environments - * This avoids the need for TextEncoder polyfills and patches - */ -export class SimpleTextEncoder { - /** - * Encode a string to a Uint8Array - * @param input - The string to encode - * @returns A Uint8Array containing the encoded string - */ - encode(input: string): Uint8Array { - // Simple UTF-8 encoding implementation that works everywhere - return new Uint8Array([...input].map((c) => c.charCodeAt(0))) - } -} - -/** - * A simple text decoder that works in all environments - * This avoids the need for TextDecoder polyfills and patches - */ -export class SimpleTextDecoder { - /** - * Decode a Uint8Array to a string - * @param input - The Uint8Array to decode - * @returns The decoded string - */ - decode(input: Uint8Array): string { - // Simple UTF-8 decoding implementation that works everywhere - return String.fromCharCode.apply(null, [...input]) - } -} - -// Create constructor functions that can be used as drop-in replacements -// for the native TextEncoder and TextDecoder - -/** - * Interface for UniversalTextEncoder instance - */ -interface IUniversalTextEncoder { - encode: (input: string) => Uint8Array; -} - -/** - * A constructor function for TextEncoder that works in all environments - */ -export function UniversalTextEncoder(this: IUniversalTextEncoder) { - if (!(this instanceof UniversalTextEncoder)) { - return new (UniversalTextEncoder as any)() - } - - try { - // Try to use the native TextEncoder if available - const nativeEncoder: TextEncoder = new TextEncoder() - this.encode = nativeEncoder.encode.bind(nativeEncoder) - } catch (e) { - // Fall back to our simple implementation - const simpleEncoder: SimpleTextEncoder = new SimpleTextEncoder() - this.encode = simpleEncoder.encode.bind(simpleEncoder) - } -} - -/** - * Interface for UniversalTextDecoder instance - */ -interface IUniversalTextDecoder { - decode: (input: Uint8Array) => string; -} - -/** - * A constructor function for TextDecoder that works in all environments - */ -export function UniversalTextDecoder(this: IUniversalTextDecoder) { - if (!(this instanceof UniversalTextDecoder)) { - return new (UniversalTextDecoder as any)() - } - - try { - // Try to use the native TextDecoder if available - const nativeDecoder: TextDecoder = new TextDecoder() - this.decode = nativeDecoder.decode.bind(nativeDecoder) - } catch (e) { - // Fall back to our simple implementation - const simpleDecoder: SimpleTextDecoder = new SimpleTextDecoder() - this.decode = simpleDecoder.decode.bind(simpleDecoder) - } -} - /** * Get a text encoder that works in the current environment - * @returns A text encoder object with an encode method + * @returns A TextEncoder instance */ -export function getTextEncoder(): IUniversalTextEncoder { - return new (UniversalTextEncoder as any)() +export function getTextEncoder(): TextEncoder { + return new TextEncoder() } /** * Get a text decoder that works in the current environment - * @returns A text decoder object with a decode method + * @returns A TextDecoder instance */ -export function getTextDecoder(): IUniversalTextDecoder { - return new (UniversalTextDecoder as any)() +export function getTextDecoder(): TextDecoder { + return new TextDecoder() } /** * Apply the TensorFlow.js platform patch if needed * This function patches the global object to provide a PlatformNode class - * that uses our text encoding utilities instead of relying on TextEncoder/TextDecoder + * that uses native TextEncoder/TextDecoder */ export function applyTensorFlowPatch(): void { try { - // Get encoders/decoders - const encoder = getTextEncoder() - const decoder = getTextDecoder() - // Define a custom Platform class that works in both Node.js and browser environments class Platform { util: any - textEncoder: any - textDecoder: any + textEncoder: TextEncoder + textDecoder: TextDecoder constructor() { // Create a util object with necessary methods and constructors this.util = { - // Add TextEncoder and TextDecoder as constructors - TextEncoder: UniversalTextEncoder, - TextDecoder: UniversalTextDecoder + // Use native TextEncoder and TextDecoder + TextEncoder: TextEncoder, + TextDecoder: TextDecoder } - // Initialize using the constructors from util - this.textEncoder = new this.util.TextEncoder() - this.textDecoder = new this.util.TextDecoder() + // Initialize using native constructors + this.textEncoder = new TextEncoder() + this.textDecoder = new TextDecoder() } // Define isFloat32Array directly on the instance @@ -143,8 +52,7 @@ export function applyTensorFlowPatch(): void { return !!( arr instanceof Float32Array || (arr && - Object.prototype.toString.call(arr) === - '[object Float32Array]') + Object.prototype.toString.call(arr) === '[object Float32Array]') ) } @@ -155,10 +63,14 @@ export function applyTensorFlowPatch(): void { } // Get the global object in a way that works in both Node.js and browser - const globalObj = typeof global !== 'undefined' ? global : - typeof window !== 'undefined' ? window : - typeof self !== 'undefined' ? self : - {}; + const globalObj = + typeof global !== 'undefined' + ? global + : typeof window !== 'undefined' + ? window + : typeof self !== 'undefined' + ? self + : {} // Only apply in Node.js environment if ( @@ -167,14 +79,14 @@ export function applyTensorFlowPatch(): void { process.versions.node ) { // Assign the Platform class to the global object as PlatformNode for Node.js - (globalObj as any).PlatformNode = Platform; + ;(globalObj as any).PlatformNode = Platform // Also create an instance and assign it to global.platformNode (lowercase p) - (globalObj as any).platformNode = new Platform(); + ;(globalObj as any).platformNode = new Platform() } else if (typeof window !== 'undefined' || typeof self !== 'undefined') { // In browser environments, we might need to provide similar functionality // but we'll use a different name to avoid conflicts - (globalObj as any).PlatformBrowser = Platform; - (globalObj as any).platformBrowser = new Platform(); + ;(globalObj as any).PlatformBrowser = Platform + ;(globalObj as any).platformBrowser = new Platform() } } catch (error) { console.warn('Failed to apply TensorFlow.js platform patch:', error) diff --git a/src/utils/workerUtils.ts b/src/utils/workerUtils.ts index 63714082..00fca82d 100644 --- a/src/utils/workerUtils.ts +++ b/src/utils/workerUtils.ts @@ -48,14 +48,26 @@ export function executeInThread(fnString: string, args: any): Promise { // Try direct approach for named functions fn = new Function(fnString)() } catch (directError) { - console.error( - 'Fallback: All approaches to create function failed', + console.warn( + 'Fallback: Direct approach failed, trying with function wrapper', directError ) - throw new Error( - 'Failed to create function from string: ' + - (functionError as Error).message - ) + + try { + // Try wrapping in a function that returns the function expression + fn = new Function( + 'return function(args) { return (' + fnString + ')(args); }' + )() + } catch (wrapperError) { + console.error( + 'Fallback: All approaches to create function failed', + wrapperError + ) + throw new Error( + 'Failed to create function from string: ' + + (functionError as Error).message + ) + } } } } @@ -94,6 +106,82 @@ function executeInNodeWorker(fnString: string, args: any): Promise { worker = new Worker( ` import { parentPort, workerData } from 'node:worker_threads'; + + // Add TensorFlow.js platform patch for Node.js + if (typeof global !== 'undefined') { + try { + // Define a custom PlatformNode class + class PlatformNode { + constructor() { + // Create a util object with necessary methods + this.util = { + // Add isFloat32Array and isTypedArray directly to util + isFloat32Array: (arr) => { + return !!( + arr instanceof Float32Array || + (arr && + Object.prototype.toString.call(arr) === '[object Float32Array]') + ); + }, + isTypedArray: (arr) => { + return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView)); + }, + // Use native TextEncoder and TextDecoder + TextEncoder: TextEncoder, + TextDecoder: TextDecoder + }; + + // Initialize encoders using native constructors + this.textEncoder = new TextEncoder(); + this.textDecoder = new TextDecoder(); + } + + // Define isFloat32Array directly on the instance + isFloat32Array(arr) { + return !!( + arr instanceof Float32Array || + (arr && Object.prototype.toString.call(arr) === '[object Float32Array]') + ); + } + + // Define isTypedArray directly on the instance + isTypedArray(arr) { + return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView)); + } + } + + // Assign the PlatformNode class to the global object + global.PlatformNode = PlatformNode; + + // Also create an instance and assign it to global.platformNode + global.platformNode = new PlatformNode(); + + // Ensure global.util exists and has the necessary methods + if (!global.util) { + global.util = {}; + } + + // Add isFloat32Array method if it doesn't exist + if (!global.util.isFloat32Array) { + global.util.isFloat32Array = (arr) => { + return !!( + arr instanceof Float32Array || + (arr && Object.prototype.toString.call(arr) === '[object Float32Array]') + ); + }; + } + + // Add isTypedArray method if it doesn't exist + if (!global.util.isTypedArray) { + global.util.isTypedArray = (arr) => { + return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView)); + }; + } + } catch (error) { + console.warn('Failed to apply TensorFlow.js platform patch:', error); + } + } + const fn = new Function('return ' + workerData.fnString)(); const result = fn(workerData.args); parentPort.postMessage({ result }); @@ -118,6 +206,71 @@ function executeInNodeWorker(fnString: string, args: any): Promise { worker = new Worker( ` import { parentPort, workerData } from 'node:worker_threads'; + + // Add TensorFlow.js platform patch for Node.js + if (typeof global !== 'undefined') { + try { + // Define a custom PlatformNode class + class PlatformNode { + constructor() { + // Create a util object with necessary methods + this.util = { + // Use native TextEncoder and TextDecoder + TextEncoder: TextEncoder, + TextDecoder: TextDecoder + }; + + // Initialize encoders using native constructors + this.textEncoder = new TextEncoder(); + this.textDecoder = new TextDecoder(); + } + + // Define isFloat32Array directly on the instance + isFloat32Array(arr) { + return !!( + arr instanceof Float32Array || + (arr && Object.prototype.toString.call(arr) === '[object Float32Array]') + ); + } + + // Define isTypedArray directly on the instance + isTypedArray(arr) { + return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView)); + } + } + + // Assign the PlatformNode class to the global object + global.PlatformNode = PlatformNode; + + // Also create an instance and assign it to global.platformNode + global.platformNode = new PlatformNode(); + + // Ensure global.util exists and has the necessary methods + if (!global.util) { + global.util = {}; + } + + // Add isFloat32Array method if it doesn't exist + if (!global.util.isFloat32Array) { + global.util.isFloat32Array = (arr) => { + return !!( + arr instanceof Float32Array || + (arr && Object.prototype.toString.call(arr) === '[object Float32Array]') + ); + }; + } + + // Add isTypedArray method if it doesn't exist + if (!global.util.isTypedArray) { + global.util.isTypedArray = (arr) => { + return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView)); + }; + } + } catch (error) { + console.warn('Failed to apply TensorFlow.js platform patch:', error); + } + } + const fn = new Function('return ' + workerData.fnString)(); const result = fn(workerData.args); parentPort.postMessage({ result }); diff --git a/src/worker.ts b/src/worker.ts index 5e7ec25a..7f6c5d9a 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,11 +1,8 @@ // Brainy Worker Script // This script is used by the workerUtils.js file to execute functions in a separate thread -// Import text encoding utilities -import { applyTensorFlowPatch } from './utils/textEncoding.js' - -// Apply the TensorFlow.js platform patch if needed -applyTensorFlowPatch() +// Note: TensorFlow.js platform patch is applied in setup.ts +// Worker scripts should import setup.ts if they need TensorFlow.js functionality // Log that the worker has started console.log('Brainy Worker: Started') diff --git a/test-fallback-function.js b/test-fallback-function.js new file mode 100644 index 00000000..2eda4d84 --- /dev/null +++ b/test-fallback-function.js @@ -0,0 +1,59 @@ +// Test script to verify that the function string format works with the fallback mechanism +import { executeInThread } from './dist/unified.js' + +// Define a compute-intensive function using a named function declaration +// followed by a statement that returns the function +const computeIntensiveFunction = ` + // Define a named function + function computeTask(data) { + console.log('Worker/Fallback: Starting computation...'); + + // Simulate a compute-intensive task + const start = Date.now(); + let result = 0; + for (let i = 0; i < data.iterations; i++) { + result += Math.sqrt(i) * Math.sin(i); + } + + const duration = Date.now() - start; + console.log('Worker/Fallback: Computation completed in ' + duration + 'ms'); + + return { + result, + duration, + iterations: data.iterations + }; + } + + // Return the function + computeTask; + ` + +// Test with different environments +async function runTests() { + try { + console.log('Testing executeInThread with fallback...') + + // Disable Web Workers to force fallback + const originalWorker = globalThis.Worker + globalThis.Worker = function() { + throw new Error('Worker constructor disabled for testing') + } + + try { + // Execute the function in fallback mode + const result = await executeInThread(computeIntensiveFunction, { + iterations: 1000000 + }) + console.log('Fallback result:', result) + console.log('Test passed!') + } finally { + // Restore Web Workers + globalThis.Worker = originalWorker + } + } catch (error) { + console.error('Test failed:', error) + } +} + +runTests() diff --git a/test-fallback-simple.js b/test-fallback-simple.js new file mode 100644 index 00000000..f54c2a30 --- /dev/null +++ b/test-fallback-simple.js @@ -0,0 +1,52 @@ +// Test script to verify that the function string format works with the fallback mechanism +import { executeInThread } from './dist/unified.js' + +// Define a compute-intensive function using a simple anonymous function expression +const computeIntensiveFunction = `function(data) { + console.log('Worker/Fallback: Starting computation...'); + + // Simulate a compute-intensive task + const start = Date.now(); + let result = 0; + for (let i = 0; i < data.iterations; i++) { + result += Math.sqrt(i) * Math.sin(i); + } + + const duration = Date.now() - start; + console.log('Worker/Fallback: Computation completed in ' + duration + 'ms'); + + return { + result, + duration, + iterations: data.iterations + }; +}` + +// Test with different environments +async function runTests() { + try { + console.log('Testing executeInThread with fallback...') + + // Disable Web Workers to force fallback + const originalWorker = globalThis.Worker + globalThis.Worker = function() { + throw new Error('Worker constructor disabled for testing') + } + + try { + // Execute the function in fallback mode + const result = await executeInThread(computeIntensiveFunction, { + iterations: 1000000 + }) + console.log('Fallback result:', result) + console.log('Test passed!') + } finally { + // Restore Web Workers + globalThis.Worker = originalWorker + } + } catch (error) { + console.error('Test failed:', error) + } +} + +runTests() diff --git a/test-tensorflow-textencoder.js b/test-tensorflow-textencoder.js new file mode 100644 index 00000000..498f2086 --- /dev/null +++ b/test-tensorflow-textencoder.js @@ -0,0 +1,103 @@ +// Test script to verify TensorFlow.js and TextEncoder functionality in Node.js environment +import * as tf from '@tensorflow/tfjs' +import '@tensorflow/tfjs-backend-cpu' +import { TextEncoder, TextDecoder } from 'util' + +// Implement the necessary functions directly +function applyTensorFlowPatch() { + // This is a simplified version of the patch + console.log('Applying TensorFlow patch directly in test file') + return true +} + +function getTextEncoder() { + return new TextEncoder() +} + +function getTextDecoder() { + return new TextDecoder() +} + +async function testTensorFlowAndTextEncoder() { + console.log('Testing TensorFlow.js and TextEncoder in Node.js environment...') + + try { + // Apply TensorFlow patch for TextEncoder compatibility + applyTensorFlowPatch() + console.log('TensorFlow patch applied successfully') + + // Test TextEncoder + console.log('\n--- Testing TextEncoder ---') + const encoder = getTextEncoder() + const decoder = getTextDecoder() + + const testString = 'Hello, world! 👋' + console.log(`Original string: "${testString}"`) + + const encoded = encoder.encode(testString) + console.log(`Encoded: [${encoded}]`) + + const decoded = decoder.decode(encoded) + console.log(`Decoded: "${decoded}"`) + + if (testString === decoded) { + console.log('✅ TextEncoder/TextDecoder test passed!') + } else { + console.error('❌ TextEncoder/TextDecoder test failed!') + return false + } + + // Test TensorFlow.js + console.log('\n--- Testing TensorFlow.js ---') + + // Create a simple tensor + const tensor = tf.tensor2d([ + [1, 2], + [3, 4] + ]) + console.log('Created tensor:') + tensor.print() + + // Perform a simple operation + const result = tensor.add(tf.scalar(1)) + console.log('Result of adding 1:') + result.print() + + // Check the values + const values = await result.array() + const expected = [ + [2, 3], + [4, 5] + ] + + console.log('Result values:', values) + console.log('Expected values:', expected) + + // Compare values + const match = JSON.stringify(values) === JSON.stringify(expected) + if (match) { + console.log('✅ TensorFlow.js test passed!') + } else { + console.error('❌ TensorFlow.js test failed!') + return false + } + + console.log('\nAll tests passed successfully!') + return true + } catch (error) { + console.error('Error during test:', error) + return false + } +} + +// Run the test +testTensorFlowAndTextEncoder().then((success) => { + if (success) { + console.log( + 'TensorFlow.js and TextEncoder verification completed successfully!' + ) + } else { + console.error('TensorFlow.js and TextEncoder verification failed!') + process.exit(1) + } +})