From 6d4beddfb5e98bfcb2e99ca751c04323b774fa0f Mon Sep 17 00:00:00 2001 From: Kieran Farr Date: Mon, 30 Dec 2024 21:47:26 -0800 Subject: [PATCH 1/7] vertex ai barely working output is json but is not parsed, only returns text --- package-lock.json | 1373 ++++++++++++++---- package.json | 2 +- src/editor/components/Main.js | 101 +- src/editor/components/widgets/AIChatPanel.js | 110 ++ src/editor/contexts/AIChatContext.js | 72 + src/editor/services/aiChatService.js | 82 ++ src/editor/services/firebase.js | 4 +- src/editor/style/chat-panel.scss | 87 ++ src/editor/style/index.scss | 2 + src/editor/style/scenegraph.scss | 20 + 10 files changed, 1532 insertions(+), 321 deletions(-) create mode 100644 src/editor/components/widgets/AIChatPanel.js create mode 100644 src/editor/contexts/AIChatContext.js create mode 100644 src/editor/services/aiChatService.js create mode 100644 src/editor/style/chat-panel.scss diff --git a/package-lock.json b/package-lock.json index 7cbdadb71..b33eeffff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "classnames": "^2.3.2", "clipboard": "^2.0.11", "date-fns": "^2.30.0", - "firebase": "^10.9.0", + "firebase": "^11.1.0", "firebase-admin": "^12.1.1", "firebase-functions": "^5.0.1", "lodash-es": "^4.17.21", @@ -2466,14 +2466,14 @@ } }, "node_modules/@firebase/analytics": { - "version": "0.10.8", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.8.tgz", - "integrity": "sha512-CVnHcS4iRJPqtIDc411+UmFldk0ShSK3OB+D0bKD8Ck5Vro6dbK5+APZpkuWpbfdL359DIQUnAaMLE+zs/PVyA==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "version": "0.10.10", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.10.tgz", + "integrity": "sha512-Psdo7c9g2SLAYh6u1XRA+RZ7ab2JfBVuAt/kLzXkhKZL/gS2cQUCMsOW5p0RIlDPRKqpdNSmvujd2TeRWLKOkQ==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/installations": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, "peerDependencies": { @@ -2481,29 +2481,86 @@ } }, "node_modules/@firebase/analytics-compat": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.14.tgz", - "integrity": "sha512-unRVY6SvRqfNFIAA/kwl4vK+lvQAL2HVcgu9zTrUtTyYDmtIt/lOuHJynBMYEgLnKm39YKBDhtqdapP2e++ASw==", - "dependencies": { - "@firebase/analytics": "0.10.8", - "@firebase/analytics-types": "0.8.2", - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.16.tgz", + "integrity": "sha512-Q/s+u/TEMSb2EDJFQMGsOzpSosybBl8HuoSEMyGZ99+0Pu7SIR9MPDGUjc8PKiCFQWDJ3QXxgqh1d/rujyAMbA==", + "dependencies": { + "@firebase/analytics": "0.10.10", + "@firebase/analytics-types": "0.8.3", + "@firebase/component": "0.6.11", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/analytics-compat/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/analytics-compat/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/analytics-compat/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/analytics-types": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.2.tgz", - "integrity": "sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==" + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz", + "integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==" + }, + "node_modules/@firebase/analytics/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/analytics/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/analytics/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } }, "node_modules/@firebase/analytics/node_modules/tslib": { "version": "2.8.1", @@ -2511,47 +2568,90 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/app": { - "version": "0.10.13", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.13.tgz", - "integrity": "sha512-OZiDAEK/lDB6xy/XzYAyJJkaDqmQ+BCtOEPLqFvxWKUz5JbBmej7IiiRHdtiIOD/twW7O5AxVsfaaGA/V1bNsA==", + "version": "0.10.17", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.17.tgz", + "integrity": "sha512-53sIYyAnYEPIZdaxuyq5OST7j4KBc2pqmktz+tEb1BIUSbXh8Gp4k/o6qzLelLpm4ngrBz7SRN0PZJqNRAyPog==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", "idb": "7.1.1", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@firebase/app-check": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.8.tgz", - "integrity": "sha512-O49RGF1xj7k6BuhxGpHmqOW5hqBIAEbt2q6POW0lIywx7emYtzPDeQI+ryQpC4zbKX646SoVZ711TN1DBLNSOQ==", + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.10.tgz", + "integrity": "sha512-DWFfxxif/t+Ow4MmRUevDX+A3hVxm1rUf6y5ZP4sIomfnVCO1NNahqtsv9rb1/tKGkTeoVT40weiTS/WjQG1mA==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, + "engines": { + "node": ">=18.0.0" + }, "peerDependencies": { "@firebase/app": "0.x" } }, "node_modules/@firebase/app-check-compat": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.15.tgz", - "integrity": "sha512-zFIvIFFNqDXpOT2huorz9cwf56VT3oJYRFjSFYdSbGYEJYEaXjLJbfC79lx/zjx4Fh+yuN8pry3TtvwaevrGbg==", - "dependencies": { - "@firebase/app-check": "0.8.8", - "@firebase/app-check-types": "0.5.2", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.17.tgz", + "integrity": "sha512-a/eadrGsY0MVCBPhrNbKUhoYpms4UKTYLKO7nswwSFVsm3Rw6NslQQCNLfvljcDqP4E7alQDRGJXjkxd/5gJ+Q==", + "dependencies": { + "@firebase/app-check": "0.8.10", + "@firebase/app-check-types": "0.5.3", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, + "engines": { + "node": ">=18.0.0" + }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/app-check-compat/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/app-check-compat/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/app-check-compat/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/app-check-compat/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -2563,9 +2663,43 @@ "integrity": "sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==" }, "node_modules/@firebase/app-check-types": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.2.tgz", - "integrity": "sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==" + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz", + "integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==" + }, + "node_modules/@firebase/app-check/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/app-check/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/app-check/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } }, "node_modules/@firebase/app-check/node_modules/tslib": { "version": "2.8.1", @@ -2573,15 +2707,52 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/app-compat": { - "version": "0.2.43", - "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.43.tgz", - "integrity": "sha512-HM96ZyIblXjAC7TzE8wIk2QhHlSvksYkQ4Ukh1GmEenzkucSNUmUX4QvoKrqeWsLEQ8hdcojABeCV8ybVyZmeg==", + "version": "0.2.47", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.47.tgz", + "integrity": "sha512-TdEWGDp6kSwuO1mxiM2Fe39eLWygfyzqTZcoU3aPV0viqqphPCbBBnVjPbFJErZ4+yaS7uCWXEbFEP9m5/COKA==", + "dependencies": { + "@firebase/app": "0.10.17", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/app-compat/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", "dependencies": { - "@firebase/app": "0.10.13", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/app-compat/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/app-compat/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@firebase/app-compat/node_modules/tslib": { @@ -2594,21 +2765,57 @@ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz", "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==" }, + "node_modules/@firebase/app/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/app/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/app/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/app/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/auth": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.7.9.tgz", - "integrity": "sha512-yLD5095kVgDw965jepMyUrIgDklD6qH/BZNHeKOgvu7pchOKNjVM+zQoOVYJIKWMWOWBq8IRNVU6NXzBbozaJg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.8.1.tgz", + "integrity": "sha512-LX9N/Cf5Z35r5yqm2+5M3+2bRRe/+RFaa/+u4HDni7TA27C/Xm4XHLKcWcLg1BzjrS4zngSaBEOSODvp6RFOqQ==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" }, "peerDependencies": { "@firebase/app": "0.x", @@ -2621,21 +2828,46 @@ } }, "node_modules/@firebase/auth-compat": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.14.tgz", - "integrity": "sha512-2eczCSqBl1KUPJacZlFpQayvpilg3dxXLy9cSMTKtQMTQSmondUtPI47P3ikH3bQAXhzKLOE+qVxJ3/IRtu9pw==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.16.tgz", + "integrity": "sha512-YlYwJMBqAyv0ESy3jDUyshMhZlbUiwAm6B6+uUmigNDHU+uq7j4SFiDJEZlFFIz397yBzKn06SUdqutdQzGnCA==", "dependencies": { - "@firebase/auth": "1.7.9", - "@firebase/auth-types": "0.12.2", - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" + "@firebase/auth": "1.8.1", + "@firebase/auth-types": "0.12.3", + "@firebase/component": "0.6.11", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/auth-compat/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/auth-compat/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/auth-compat/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -2647,14 +2879,48 @@ "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==" }, "node_modules/@firebase/auth-types": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.2.tgz", - "integrity": "sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w==", + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.3.tgz", + "integrity": "sha512-Zq9zI0o5hqXDtKg6yDkSnvMCMuLU6qAVS51PANQx+ZZX5xnzyNLEBO3GZgBUPsV5qIMFhjhqmLDxUqCbnAYy2A==", "peerDependencies": { "@firebase/app-types": "0.x", "@firebase/util": "1.x" } }, + "node_modules/@firebase/auth/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/auth/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/auth/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/auth/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -2675,20 +2941,59 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/data-connect": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.0.tgz", - "integrity": "sha512-vSe5s8dY13ilhLnfY0eYRmQsdTbH7PUFZtBbqU6JVX/j8Qp9A6G5gG6//ulbX9/1JFOF1IWNOne9c8S/DOCJaQ==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.3.tgz", + "integrity": "sha512-FbAQpWNHownJx1VTCQI4ydbWGOZmSWXoFlirQn3ItHqsLJYSywqxSgDafzvyooifFh3J/2WqaM8y9hInnPcsTw==", "dependencies": { - "@firebase/auth-interop-types": "0.2.3", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, + "node_modules/@firebase/data-connect/node_modules/@firebase/auth-interop-types": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", + "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==" + }, + "node_modules/@firebase/data-connect/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/data-connect/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/data-connect/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/data-connect/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -2741,101 +3046,221 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/firestore": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.3.tgz", - "integrity": "sha512-NwVU+JPZ/3bhvNSJMCSzfcBZZg8SUGyzZ2T0EW3/bkUeefCyzMISSt/TTIfEHc8cdyXGlMqfGe3/62u9s74UEg==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.5.tgz", + "integrity": "sha512-OO3rHvjC07jL2ITN255xH/UzCVSvh6xG8oTzQdFScQvFbcm1fjCL1hgAdpDZcx3vVcKMV+6ktr8wbllkB8r+FQ==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", - "@firebase/webchannel-wrapper": "1.0.1", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "@firebase/webchannel-wrapper": "1.0.3", "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", - "tslib": "^2.1.0", - "undici": "6.19.7" + "tslib": "^2.1.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.0.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "node_modules/@firebase/firestore-compat": { - "version": "0.3.38", - "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.38.tgz", - "integrity": "sha512-GoS0bIMMkjpLni6StSwRJarpu2+S5m346Na7gr9YZ/BZ/W3/8iHGNr9PxC+f0rNZXqS4fGRn88pICjrZEgbkqQ==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/firestore": "4.7.3", - "@firebase/firestore-types": "3.0.2", - "@firebase/util": "1.10.0", + "version": "0.3.40", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.40.tgz", + "integrity": "sha512-18HopMN811KYBc9Ptpr1Rewwio0XF09FF3jc5wtV6rGyAs815SlFFw5vW7ZeLd43zv9tlEc2FzM0H+5Vr9ZRxw==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/firestore": "4.7.5", + "@firebase/firestore-types": "3.0.3", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, + "engines": { + "node": ">=18.0.0" + }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/firestore-compat/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/firestore-compat/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/firestore-compat/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/firestore-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.2.tgz", - "integrity": "sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz", + "integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==", "peerDependencies": { "@firebase/app-types": "0.x", "@firebase/util": "1.x" } }, + "node_modules/@firebase/firestore/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/firestore/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/firestore/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/firestore/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/functions": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.8.tgz", - "integrity": "sha512-Lo2rTPDn96naFIlSZKVd1yvRRqqqwiJk7cf9TZhUerwnPKgBzXy+aHE22ry+6EjCaQusUoNai6mU6p+G8QZT1g==", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.2", - "@firebase/auth-interop-types": "0.2.3", - "@firebase/component": "0.6.9", - "@firebase/messaging-interop-types": "0.2.2", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.0.tgz", + "integrity": "sha512-plTtzY/nT0jOgHzT0vB9qch4FpHFOhCnR8HhYBqqdArG6GOQMIruKZbiTyLybO8bcaaNgQ6kSm9yohGUwxHcIw==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.11", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "node_modules/@firebase/functions-compat": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.14.tgz", - "integrity": "sha512-dZ0PKOKQFnOlMfcim39XzaXonSuPPAVuzpqA4ONTIdyaJK/OnBaIEVs/+BH4faa1a2tLeR+Jy15PKqDRQoNIJw==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/functions": "0.11.8", - "@firebase/functions-types": "0.6.2", - "@firebase/util": "1.10.0", + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.17.tgz", + "integrity": "sha512-oj2XV8YsJYutyPCRYUfbN6swmfrL6zar0/qtqZsKT7P7btOiYRl+lD6fxtQaT+pKE5YgOBGZW//kLPZfY0jWhw==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/functions": "0.12.0", + "@firebase/functions-types": "0.6.3", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, + "engines": { + "node": ">=18.0.0" + }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/functions-compat/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/functions-compat/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/functions-compat/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/functions-types": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.2.tgz", - "integrity": "sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz", + "integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==" + }, + "node_modules/@firebase/functions/node_modules/@firebase/app-check-interop-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", + "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==" + }, + "node_modules/@firebase/functions/node_modules/@firebase/auth-interop-types": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", + "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==" + }, + "node_modules/@firebase/functions/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/functions/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } }, "node_modules/@firebase/functions/node_modules/tslib": { "version": "2.8.1", @@ -2843,12 +3268,12 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/installations": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.9.tgz", - "integrity": "sha512-hlT7AwCiKghOX3XizLxXOsTFiFCQnp/oj86zp1UxwDGmyzsyoxtX+UIZyVyH/oBF5+XtblFG9KZzZQ/h+dpy+Q==", + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.11.tgz", + "integrity": "sha512-w8fY8mw6fxJzsZM2ufmTtomopXl1+bn/syYon+Gpn+0p0nO1cIUEVEFrFazTLaaL9q1CaVhc3HmseRTsI3igAA==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", + "@firebase/component": "0.6.11", + "@firebase/util": "1.10.2", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -2857,33 +3282,79 @@ } }, "node_modules/@firebase/installations-compat": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.9.tgz", - "integrity": "sha512-2lfdc6kPXR7WaL4FCQSQUhXcPbI7ol3wF+vkgtU25r77OxPf8F/VmswQ7sgIkBBWtymn5ZF20TIKtnOj9rjb6w==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/installations-types": "0.5.2", - "@firebase/util": "1.10.0", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.11.tgz", + "integrity": "sha512-SHRgw5LTa6v8LubmJZxcOCwEd1MfWQPUtKdiuCx2VMWnapX54skZd1PkQg0K4l3k+4ujbI2cn7FE6Li9hbChBw==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/installations": "0.6.11", + "@firebase/installations-types": "0.5.3", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/installations-compat/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/installations-compat/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/installations-compat/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/installations-types": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.2.tgz", - "integrity": "sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz", + "integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==", "peerDependencies": { "@firebase/app-types": "0.x" } }, + "node_modules/@firebase/installations/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/installations/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/installations/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -2903,14 +3374,14 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/messaging": { - "version": "0.12.12", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.12.tgz", - "integrity": "sha512-6q0pbzYBJhZEtUoQx7hnPhZvAbuMNuBXKQXOx2YlWhSrlv9N1m0ZzlNpBbu/ItTzrwNKTibdYzUyaaxdWLg+4w==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/messaging-interop-types": "0.2.2", - "@firebase/util": "1.10.0", + "version": "0.12.15", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.15.tgz", + "integrity": "sha512-Bz+qvWNEwEWAbYtG4An8hgcNco6NWNoNLuLbGVwPL2fAoCF1zz+dcaBp+iTR2+K199JyRyDT9yDPAXhNHNDaKQ==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/installations": "0.6.11", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.10.2", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -2919,43 +3390,89 @@ } }, "node_modules/@firebase/messaging-compat": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.12.tgz", - "integrity": "sha512-pKsiUVZrbmRgdImYqhBNZlkKJbqjlPkVdQRZGRbkTyX4OSGKR0F/oJeCt1a8jEg5UnBp4fdVwSWSp4DuCovvEQ==", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.15.tgz", + "integrity": "sha512-mEKKASRvRWq1aBNHgioGsOYR2c5nBZpO7k90K794zjKe0WkGNf0k7PLs5SlCf8FKnzumEkhTAp/SjYxovuxa8A==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/messaging": "0.12.15", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/messaging-compat/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/messaging-compat/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/messaging-compat/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/@firebase/messaging-interop-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz", + "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==" + }, + "node_modules/@firebase/messaging/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/messaging/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/messaging": "0.12.12", - "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@firebase/messaging-compat/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/@firebase/messaging-interop-types": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz", - "integrity": "sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA==" - }, "node_modules/@firebase/messaging/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/performance": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.9.tgz", - "integrity": "sha512-PnVaak5sqfz5ivhua+HserxTJHtCar/7zM0flCX6NkzBNzJzyzlH4Hs94h2Il0LQB99roBqoE5QT1JqWqcLJHQ==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.11.tgz", + "integrity": "sha512-FlkJFeqLlIeh5T4Am3uE38HVzggliDIEFy/fErEc1faINOUFCb6vQBEoNZGaXvRnTR8lh3X/hP7tv37C7BsK9g==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/installations": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, "peerDependencies": { @@ -2963,30 +3480,98 @@ } }, "node_modules/@firebase/performance-compat": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.9.tgz", - "integrity": "sha512-dNl95IUnpsu3fAfYBZDCVhXNkASE0uo4HYaEPd2/PKscfTvsgqFAOxfAXzBEDOnynDWiaGUnb5M1O00JQ+3FXA==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/performance": "0.6.9", - "@firebase/performance-types": "0.2.2", - "@firebase/util": "1.10.0", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.11.tgz", + "integrity": "sha512-DqeNBy51W2xzlklyC7Ht9JQ94HhTA08PCcM4MDeyG/ol3fqum/+YgtHWQ2IQuduqH9afETthZqLwCZiSgY7hiA==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/performance": "0.6.11", + "@firebase/performance-types": "0.2.3", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/performance-compat/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/performance-compat/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/performance-compat/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/performance-compat/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/performance-types": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.2.tgz", - "integrity": "sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA==" + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz", + "integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==" + }, + "node_modules/@firebase/performance/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/performance/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/performance/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } }, "node_modules/@firebase/performance/node_modules/tslib": { "version": "2.8.1", @@ -2994,14 +3579,14 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/remote-config": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.9.tgz", - "integrity": "sha512-EO1NLCWSPMHdDSRGwZ73kxEEcTopAxX1naqLJFNApp4hO8WfKfmEpmjxmP5TrrnypjIf2tUkYaKsfbEA7+AMmA==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.11.tgz", + "integrity": "sha512-9z0rgKuws2nj+7cdiqF+NY1QR4na6KnuOvP+jQvgilDOhGtKOcCMq5XHiu66i73A9kFhyU6QQ2pHXxcmaq1pBw==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.6.11", + "@firebase/installations": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, "peerDependencies": { @@ -3009,30 +3594,98 @@ } }, "node_modules/@firebase/remote-config-compat": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.9.tgz", - "integrity": "sha512-AxzGpWfWFYejH2twxfdOJt5Cfh/ATHONegTd/a0p5flEzsD5JsxXgfkFToop+mypEL3gNwawxrxlZddmDoNxyA==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/remote-config": "0.4.9", - "@firebase/remote-config-types": "0.3.2", - "@firebase/util": "1.10.0", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.11.tgz", + "integrity": "sha512-zfIjpwPrGuIOZDmduukN086qjhZ1LnbJi/iYzgua+2qeTlO0XdlE1v66gJPwygGB3TOhT0yb9EiUZ3nBNttMqg==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/remote-config": "0.4.11", + "@firebase/remote-config-types": "0.3.3", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/remote-config-compat/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/remote-config-compat/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/remote-config-compat/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/remote-config-compat/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/remote-config-types": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz", - "integrity": "sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==" + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.3.tgz", + "integrity": "sha512-YlRI9CHxrk3lpQuFup9N1eohpwdWayKZUNZ/YeQ0PZoncJ66P32UsKUKqVXOaieTjJIOh7yH8JEzRdht5s+d6g==" + }, + "node_modules/@firebase/remote-config/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/remote-config/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/remote-config/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } }, "node_modules/@firebase/remote-config/node_modules/tslib": { "version": "2.8.1", @@ -3040,48 +3693,99 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/storage": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.2.tgz", - "integrity": "sha512-fxuJnHshbhVwuJ4FuISLu+/76Aby2sh+44ztjF2ppoe0TELIDxPW6/r1KGlWYt//AD0IodDYYA8ZTN89q8YqUw==", + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.4.tgz", + "integrity": "sha512-b1KaTTRiMupFurIhpGIbReaWev0k5O3ouTHkAPcEssT+FvU3q/1JwzvkX4+ZdB60Fc43Mbp8qQ1gWfT0Z2FP9Q==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" + "@firebase/component": "0.6.11", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "node_modules/@firebase/storage-compat": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.12.tgz", - "integrity": "sha512-hA4VWKyGU5bWOll+uwzzhEMMYGu9PlKQc1w4DWxB3aIErWYzonrZjF0icqNQZbwKNIdh8SHjZlFeB2w6OSsjfg==", + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.14.tgz", + "integrity": "sha512-Ok5FmXJiapaNAOQ8W8qppnfwgP8540jw2B8M0c4TFZqF4BD+CoKBxW0dRtOuLNGadLhzqqkDZZZtkexxrveQqA==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/storage": "0.13.2", - "@firebase/storage-types": "0.8.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.6.11", + "@firebase/storage": "0.13.4", + "@firebase/storage-types": "0.8.3", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, + "engines": { + "node": ">=18.0.0" + }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, + "node_modules/@firebase/storage-compat/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/storage-compat/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/storage-compat/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/storage-types": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.2.tgz", - "integrity": "sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz", + "integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==", "peerDependencies": { "@firebase/app-types": "0.x", "@firebase/util": "1.x" } }, + "node_modules/@firebase/storage/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/storage/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@firebase/storage/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -3100,15 +3804,15 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, - "node_modules/@firebase/vertexai-preview": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@firebase/vertexai-preview/-/vertexai-preview-0.0.4.tgz", - "integrity": "sha512-EBSqyu9eg8frQlVU9/HjKtHN7odqbh9MtAcVz3WwHj4gLCLOoN9F/o+oxlq3CxvFrd3CNTZwu6d2mZtVlEInng==", + "node_modules/@firebase/vertexai": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.2.tgz", + "integrity": "sha512-4dC9m2nD0tkfKJT5v+i27tELrmUePjFXW3CDAxhVHUEv647B2R7kqpGQnyPkNEeaXkCr76THe7GGg35EWn4lDw==", "dependencies": { - "@firebase/app-check-interop-types": "0.3.2", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", "tslib": "^2.1.0" }, "engines": { @@ -3119,15 +3823,54 @@ "@firebase/app-types": "0.x" } }, - "node_modules/@firebase/vertexai-preview/node_modules/tslib": { + "node_modules/@firebase/vertexai/node_modules/@firebase/app-check-interop-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", + "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==" + }, + "node_modules/@firebase/vertexai/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/vertexai/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/vertexai/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/vertexai/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@firebase/webchannel-wrapper": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.1.tgz", - "integrity": "sha512-jmEnr/pk0yVkA7mIlHNnxCi+wWzOFUg0WyIotgkKAb2u1J7fAeDBcVNSTjTihbAYNusCLQdW5s9IJ5qwnEufcQ==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz", + "integrity": "sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==" }, "node_modules/@floating-ui/core": { "version": "1.6.2", @@ -15502,38 +16245,38 @@ } }, "node_modules/firebase": { - "version": "10.14.1", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.14.1.tgz", - "integrity": "sha512-0KZxU+Ela9rUCULqFsUUOYYkjh7OM1EWdIfG6///MtXd0t2/uUIf0iNV5i0KariMhRQ5jve/OY985nrAXFaZeQ==", - "dependencies": { - "@firebase/analytics": "0.10.8", - "@firebase/analytics-compat": "0.2.14", - "@firebase/app": "0.10.13", - "@firebase/app-check": "0.8.8", - "@firebase/app-check-compat": "0.3.15", - "@firebase/app-compat": "0.2.43", - "@firebase/app-types": "0.9.2", - "@firebase/auth": "1.7.9", - "@firebase/auth-compat": "0.5.14", - "@firebase/data-connect": "0.1.0", - "@firebase/database": "1.0.8", - "@firebase/database-compat": "1.0.8", - "@firebase/firestore": "4.7.3", - "@firebase/firestore-compat": "0.3.38", - "@firebase/functions": "0.11.8", - "@firebase/functions-compat": "0.3.14", - "@firebase/installations": "0.6.9", - "@firebase/installations-compat": "0.2.9", - "@firebase/messaging": "0.12.12", - "@firebase/messaging-compat": "0.2.12", - "@firebase/performance": "0.6.9", - "@firebase/performance-compat": "0.2.9", - "@firebase/remote-config": "0.4.9", - "@firebase/remote-config-compat": "0.2.9", - "@firebase/storage": "0.13.2", - "@firebase/storage-compat": "0.3.12", - "@firebase/util": "1.10.0", - "@firebase/vertexai-preview": "0.0.4" + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.1.0.tgz", + "integrity": "sha512-3OoNW3vBXmBLYJvcwbPCwfluptbDVp2zZYjrfHPVFAXfPgmyy/LWjidt+Sw2WNvRelsG0v++WN2Wor6J3OwDRg==", + "dependencies": { + "@firebase/analytics": "0.10.10", + "@firebase/analytics-compat": "0.2.16", + "@firebase/app": "0.10.17", + "@firebase/app-check": "0.8.10", + "@firebase/app-check-compat": "0.3.17", + "@firebase/app-compat": "0.2.47", + "@firebase/app-types": "0.9.3", + "@firebase/auth": "1.8.1", + "@firebase/auth-compat": "0.5.16", + "@firebase/data-connect": "0.1.3", + "@firebase/database": "1.0.10", + "@firebase/database-compat": "2.0.1", + "@firebase/firestore": "4.7.5", + "@firebase/firestore-compat": "0.3.40", + "@firebase/functions": "0.12.0", + "@firebase/functions-compat": "0.3.17", + "@firebase/installations": "0.6.11", + "@firebase/installations-compat": "0.2.11", + "@firebase/messaging": "0.12.15", + "@firebase/messaging-compat": "0.2.15", + "@firebase/performance": "0.6.11", + "@firebase/performance-compat": "0.2.11", + "@firebase/remote-config": "0.4.11", + "@firebase/remote-config-compat": "0.2.11", + "@firebase/storage": "0.13.4", + "@firebase/storage-compat": "0.3.14", + "@firebase/util": "1.10.2", + "@firebase/vertexai": "1.0.2" } }, "node_modules/firebase-admin": { @@ -15611,6 +16354,102 @@ "@types/serve-static": "*" } }, + "node_modules/firebase/node_modules/@firebase/app-check-interop-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", + "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==" + }, + "node_modules/firebase/node_modules/@firebase/app-types": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", + "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==" + }, + "node_modules/firebase/node_modules/@firebase/auth-interop-types": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", + "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==" + }, + "node_modules/firebase/node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/firebase/node_modules/@firebase/database": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.10.tgz", + "integrity": "sha512-sWp2g92u7xT4BojGbTXZ80iaSIaL6GAL0pwvM0CO/hb0nHSnABAqsH7AhnWGsGvXuEvbPr7blZylPaR9J+GSuQ==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/firebase/node_modules/@firebase/database-compat": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.1.tgz", + "integrity": "sha512-IsFivOjdE1GrjTeKoBU/ZMenESKDXidFDzZzHBPQ/4P20ptGdrl3oLlWrV/QJqJ9lND4IidE3z4Xr5JyfUW1vg==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/database": "1.0.10", + "@firebase/database-types": "1.0.7", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/firebase/node_modules/@firebase/database-types": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.7.tgz", + "integrity": "sha512-I7zcLfJXrM0WM+ksFmFdAMdlq/DFmpeMNa+/GNsLyFo5u/lX5zzkPzGe3srVWqaBQBY5KprylDGxOsP6ETfL0A==", + "dependencies": { + "@firebase/app-types": "0.9.3", + "@firebase/util": "1.10.2" + } + }, + "node_modules/firebase/node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/firebase/node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/firebase/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -28733,14 +29572,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/undici": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.7.tgz", - "integrity": "sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A==", - "engines": { - "node": ">=18.17" - } - }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", diff --git a/package.json b/package.json index 970a7865e..3e07971dd 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "classnames": "^2.3.2", "clipboard": "^2.0.11", "date-fns": "^2.30.0", - "firebase": "^10.9.0", + "firebase": "^11.1.0", "firebase-admin": "^12.1.1", "firebase-functions": "^5.0.1", "lodash-es": "^4.17.21", diff --git a/src/editor/components/Main.js b/src/editor/components/Main.js index 3a80e89ad..81a5bbc56 100644 --- a/src/editor/components/Main.js +++ b/src/editor/components/Main.js @@ -20,6 +20,8 @@ import { IntroModal } from './modals/IntroModal'; import { NewModal } from './modals/NewModal'; import { ToolbarWrapper } from './scenegraph/ToolbarWrapper.js'; import useStore from '@/store'; +import { AIChatProvider } from '../contexts/AIChatContext'; +import AIChatPanel from './widgets/AIChatPanel'; THREE.ImageUtils.crossOrigin = ''; @@ -109,58 +111,61 @@ export default function Main() { return (
- - {isInspectorEnabled && ( -
- -
- + + {isInspectorEnabled && ( +
+ + +
+ +
-
- )} - - - - - - - - - - - + )} + + + + + + + + + + + - {isInspectorEnabled && ( - <> -
- -
-
- -
-
- - -
- + {isInspectorEnabled && ( + <> +
+
-
- - )} +
+ +
+
+ + +
+ +
+
+ + )} +
); } diff --git a/src/editor/components/widgets/AIChatPanel.js b/src/editor/components/widgets/AIChatPanel.js new file mode 100644 index 000000000..f5267b16d --- /dev/null +++ b/src/editor/components/widgets/AIChatPanel.js @@ -0,0 +1,110 @@ +import { useState, useEffect, useRef } from 'react'; +import { vertexAI } from '../../services/firebase.js'; +import { getGenerativeModel } from 'firebase/vertexai'; +import Collapsible from '../Collapsible'; + +const AIChatPanel = ({ scene }) => { + const [messages, setMessages] = useState([]); + const [input, setInput] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const chatContainerRef = useRef(null); + const modelRef = useRef(null); + + useEffect(() => { + console.log('AIChatPanel mounted'); + console.log('Scene available:', !!scene); + const initializeAI = async () => { + try { + console.log('Initializing Vertex AI'); + modelRef.current = getGenerativeModel(vertexAI, { + model: 'gemini-1.5-flash' + }); + console.log('Vertex AI initialized successfully'); + } catch (error) { + console.error('Error initializing Vertex AI:', error); + } + }; + + initializeAI(); + }, []); + + const handleSendMessage = async () => { + if (!input.trim() || !modelRef.current) return; + + setIsLoading(true); + const userMessage = { role: 'user', content: input }; + setMessages((prev) => [...prev, userMessage]); + setInput(''); + + try { + // Get the current scene state + const sceneState = scene.current + ? scene.current.getAttribute('managed-street') + : null; + + const prompt = ` + Context: You are a 3D street scene assistant. The current scene has the following state: + ${JSON.stringify(sceneState, null, 2)} + + User request: ${input} + + Please provide suggestions for modifying the scene. Format your response as JSON when suggesting specific changes. + `; + + const result = await modelRef.current.generateContent(prompt); + const response = await result.response; + const aiMessage = { role: 'assistant', content: response.text() }; + + setMessages((prev) => [...prev, aiMessage]); + } catch (error) { + console.error('Error generating response:', error); + setMessages((prev) => [ + ...prev, + { + role: 'assistant', + content: 'Sorry, I encountered an error. Please try again.' + } + ]); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + if (chatContainerRef.current) { + chatContainerRef.current.scrollTop = + chatContainerRef.current.scrollHeight; + } + }, [messages]); + return ( +
+ +
AI Scene Assistant
+
+
+ {messages.map((message, index) => ( +
+ {message.content} +
+ ))} + {isLoading &&
Thinking...
} +
+
+ setInput(e.target.value)} + onKeyPress={(e) => e.key === 'Enter' && handleSendMessage()} + placeholder="Ask about the scene..." + /> + +
+
+
+
+ ); +}; + +export default AIChatPanel; diff --git a/src/editor/contexts/AIChatContext.js b/src/editor/contexts/AIChatContext.js new file mode 100644 index 000000000..063d664ee --- /dev/null +++ b/src/editor/contexts/AIChatContext.js @@ -0,0 +1,72 @@ +import { createContext, useContext, useState, useCallback } from 'react'; +import AIChatService from '../services/aiChatService'; + +const AIChatContext = createContext(null); + +export const AIChatProvider = ({ children, firebaseApp }) => { + const [chatService] = useState(() => new AIChatService(firebaseApp)); + const [messages, setMessages] = useState([]); + const [isProcessing, setIsProcessing] = useState(false); + + const sendMessage = useCallback( + async (message, sceneState) => { + setIsProcessing(true); + try { + const response = await chatService.generateResponse( + message, + sceneState + ); + const parsedResponse = chatService.parseResponse(response); + + setMessages((prev) => [ + ...prev, + { role: 'user', content: message }, + { role: 'assistant', content: response, parsed: parsedResponse } + ]); + + return parsedResponse; + } catch (error) { + console.error('Error in chat:', error); + setMessages((prev) => [ + ...prev, + { role: 'user', content: message }, + { + role: 'assistant', + content: 'Sorry, I encountered an error. Please try again.' + } + ]); + throw error; + } finally { + setIsProcessing(false); + } + }, + [chatService] + ); + + const clearMessages = useCallback(() => { + setMessages([]); + }, []); + + return ( + + {children} + + ); +}; + +export const useAIChat = () => { + const context = useContext(AIChatContext); + if (!context) { + throw new Error('useAIChat must be used within an AIChatProvider'); + } + return context; +}; + +export default AIChatContext; diff --git a/src/editor/services/aiChatService.js b/src/editor/services/aiChatService.js new file mode 100644 index 000000000..f3e371ace --- /dev/null +++ b/src/editor/services/aiChatService.js @@ -0,0 +1,82 @@ +import { getGenerativeModel } from 'firebase/vertexai'; +import { vertexAI } from '../services/firebase.js'; + +class AIChatService { + constructor(firebaseApp) { + this.model = null; + this.initPromise = this.initialize(firebaseApp); + } + + async initialize(firebaseApp) { + try { + this.model = getGenerativeModel(vertexAI, { + model: 'gemini-1.5-flash' + }); + } catch (error) { + console.error('Error initializing AI Chat Service:', error); + throw error; + } + } + + async generateResponse(prompt, sceneState) { + if (!this.model) { + throw new Error('AI model not initialized'); + } + + const formattedPrompt = this.formatPrompt(prompt, sceneState); + const result = await this.model.generateContent(formattedPrompt); + return result.response.text(); + } + + formatPrompt(userInput, sceneState) { + return ` + Context: You are a 3D street scene assistant for the 3DStreet application. + The current scene has the following state: + ${JSON.stringify(sceneState, null, 2)} + + User request: ${userInput} + + Please analyze the request and provide one of the following: + 1. If the user is asking to modify the scene, provide specific JSON-formatted changes + 2. If the user is asking about the scene, provide a natural language explanation + 3. If the user needs help, provide relevant guidance about the 3DStreet editor + + For scene modifications, use this JSON format: + { + "action": "modify_scene", + "changes": [ + { + "type": "add"|"remove"|"update", + "element": "", + "properties": {} + } + ] + } + `; + } + + parseResponse(response) { + try { + // Check if the response is JSON + const parsed = JSON.parse(response); + if (parsed.action === 'modify_scene') { + return { + type: 'scene_modification', + data: parsed.changes + }; + } + return { + type: 'text', + data: response + }; + } catch (e) { + // If not JSON, treat as regular text response + return { + type: 'text', + data: response + }; + } + } +} + +export default AIChatService; diff --git a/src/editor/services/firebase.js b/src/editor/services/firebase.js index a039ffebb..4c146d8ea 100644 --- a/src/editor/services/firebase.js +++ b/src/editor/services/firebase.js @@ -3,6 +3,7 @@ import { getAuth } from 'firebase/auth'; import { getStorage } from 'firebase/storage'; import { getFirestore } from 'firebase/firestore'; import { getFunctions } from 'firebase/functions'; +import { getVertexAI } from 'firebase/vertexai'; const firebaseConfig = { apiKey: process.env.FIREBASE_API_KEY, @@ -19,5 +20,6 @@ const auth = getAuth(app); const storage = getStorage(app); const db = getFirestore(app); const functions = getFunctions(app); +const vertexAI = getVertexAI(app); -export { firebaseConfig, auth, storage, db, functions }; +export { firebaseConfig, auth, storage, db, functions, vertexAI }; diff --git a/src/editor/style/chat-panel.scss b/src/editor/style/chat-panel.scss new file mode 100644 index 000000000..c21227f8c --- /dev/null +++ b/src/editor/style/chat-panel.scss @@ -0,0 +1,87 @@ +@use 'variables.scss'; + +.chat-panel-container { + position: absolute; + top: 60px; + right: 320px; + width: 300px; + z-index: 999; + background-color: variables.$darkgray-800; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} + +.chat-messages { + height: 300px; + overflow-y: auto; + padding: 10px; + display: flex; + flex-direction: column; + gap: 10px; +} + +.chat-message { + max-width: 80%; + padding: 8px 12px; + border-radius: 12px; + color: variables.$white; + + &.user { + align-self: flex-end; + background-color: variables.$purple-800; + } + + &.assistant { + align-self: flex-start; + background-color: variables.$darkgray-500; + } +} + +.chat-input { + padding: 10px; + display: flex; + gap: 8px; + background-color: variables.$darkgray-800; + border-radius: 0 0 8px 8px; + + input { + flex: 1; + padding: 8px; + border-radius: 4px; + border: 1px solid variables.$darkgray-500; + background: variables.$darkgray-900; + color: variables.$white; + + &::placeholder { + color: variables.$gray-500; + } + } + + button { + padding: 8px 16px; + border-radius: 4px; + background-color: variables.$purple-800; + color: variables.$white; + border: none; + cursor: pointer; + + &:hover { + background-color: variables.$purple-100; + } + + &:active { + background-color: variables.$purple-200; + } + + &:disabled { + opacity: 0.7; + cursor: default; + } + } +} + +.loading-indicator { + text-align: center; + color: variables.$gray-500; + padding: 8px; +} diff --git a/src/editor/style/index.scss b/src/editor/style/index.scss index 2ae4e4049..a9a324bb2 100644 --- a/src/editor/style/index.scss +++ b/src/editor/style/index.scss @@ -1,5 +1,6 @@ @use './variables.scss'; @import '../normalize.css'; +@import './chat-panel.scss'; body.aframe-inspector-opened, .toggle-edit { @@ -456,6 +457,7 @@ body.aframe-inspector-opened { z-index: 9; } + .chat-panel-container, #toolbar, .outliner, .modal, diff --git a/src/editor/style/scenegraph.scss b/src/editor/style/scenegraph.scss index 7ace8d4c6..0522c0cf8 100644 --- a/src/editor/style/scenegraph.scss +++ b/src/editor/style/scenegraph.scss @@ -1,4 +1,24 @@ @use './variables.scss'; +/* chatpanel */ +.ai-chat-panel { + position: fixed; + bottom: 20px; + right: 20px; + width: 350px; + z-index: 1000; + background: white; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} +/* Add responsive styles */ +@media (max-width: 768px) { + .ai-chat-panel { + width: 100%; + bottom: 0; + right: 0; + border-radius: 8px 8px 0 0; + } +} #toolbar { // top: 36px; // left: 32px; From 558b7bd0fd3daef94f03d20b5b7978040af56162 Mon Sep 17 00:00:00 2001 From: Kieran Farr Date: Mon, 30 Dec 2024 22:28:04 -0800 Subject: [PATCH 2/7] better reference to firebase app --- src/editor/components/Main.js | 4 ++-- src/editor/services/firebase.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/editor/components/Main.js b/src/editor/components/Main.js index 81a5bbc56..5c596d756 100644 --- a/src/editor/components/Main.js +++ b/src/editor/components/Main.js @@ -8,7 +8,7 @@ import { ScreenshotModal } from './modals/ScreenshotModal'; // import ViewportHUD from "./viewport/ViewportHUD"; import { SignInModal } from './modals/SignInModal'; import { ProfileModal } from './modals/ProfileModal'; -import { firebaseConfig } from '../services/firebase.js'; +import { firebaseConfig, app } from '../services/firebase.js'; import { LoadScript } from '@react-google-maps/api'; import { GeoModal } from './modals/GeoModal'; import { ActionBar } from './components/ActionBar'; @@ -111,7 +111,7 @@ export default function Main() { return (
- + {isInspectorEnabled && (
diff --git a/src/editor/services/firebase.js b/src/editor/services/firebase.js index 4c146d8ea..e3f2bd880 100644 --- a/src/editor/services/firebase.js +++ b/src/editor/services/firebase.js @@ -22,4 +22,4 @@ const db = getFirestore(app); const functions = getFunctions(app); const vertexAI = getVertexAI(app); -export { firebaseConfig, auth, storage, db, functions, vertexAI }; +export { firebaseConfig, app, auth, storage, db, functions, vertexAI }; From a2cc5fcedd44883cb776a47217284e7f01182ee4 Mon Sep 17 00:00:00 2001 From: Kieran Farr Date: Mon, 30 Dec 2024 22:52:58 -0800 Subject: [PATCH 3/7] premature parsing of json in a blob --- package-lock.json | 13 ++++ package.json | 3 +- src/editor/components/widgets/AIChatPanel.js | 68 +++++++++++++++++++- src/editor/style/chat-panel.scss | 40 ++++++++++++ 4 files changed, 122 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index b33eeffff..83b46c874 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-json-pretty": "^2.2.0", "react-select": "^5.4.0", "stripe": "^15.8.0", "three": "0.145.0", @@ -26233,6 +26234,18 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-json-pretty": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/react-json-pretty/-/react-json-pretty-2.2.0.tgz", + "integrity": "sha512-3UMzlAXkJ4R8S4vmkRKtvJHTewG4/rn1Q18n0zqdu/ipZbUPLVZD+QwC7uVcD/IAY3s8iNVHlgR2dMzIUS0n1A==", + "dependencies": { + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=15.0", + "react-dom": ">=15.0" + } + }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", diff --git a/package.json b/package.json index 3e07971dd..b35f2c9b9 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-json-pretty": "^2.2.0", "react-select": "^5.4.0", "stripe": "^15.8.0", "three": "0.145.0", @@ -123,4 +124,4 @@ "prettier --write" ] } -} +} \ No newline at end of file diff --git a/src/editor/components/widgets/AIChatPanel.js b/src/editor/components/widgets/AIChatPanel.js index f5267b16d..31d93135b 100644 --- a/src/editor/components/widgets/AIChatPanel.js +++ b/src/editor/components/widgets/AIChatPanel.js @@ -2,6 +2,71 @@ import { useState, useEffect, useRef } from 'react'; import { vertexAI } from '../../services/firebase.js'; import { getGenerativeModel } from 'firebase/vertexai'; import Collapsible from '../Collapsible'; +import JSONPretty from 'react-json-pretty'; +import 'react-json-pretty/themes/monikai.css'; + +// Helper component to render message content with JSON formatting +const MessageContent = ({ content }) => { + const formatContent = (text) => { + const parts = []; + let currentIndex = 0; + const jsonBlockRegex = /```(?:json)?\s*(\{[\s\S]*?\})\s*```/g; + + let match; + while ((match = jsonBlockRegex.exec(text)) !== null) { + // Add text before the JSON block + if (match.index > currentIndex) { + parts.push({ + type: 'text', + content: text.slice(currentIndex, match.index) + }); + } + + try { + // Try to parse the JSON + const jsonContent = JSON.parse(match[1]); + parts.push({ + type: 'json', + content: jsonContent + }); + } catch (e) { + // If parsing fails, treat as regular text + parts.push({ + type: 'text', + content: match[0] + }); + } + + currentIndex = match.index + match[0].length; + } + + // Add any remaining text + if (currentIndex < text.length) { + parts.push({ + type: 'text', + content: text.slice(currentIndex) + }); + } + + return parts; + }; + + const parts = formatContent(content); + + return ( + <> + {parts.map((part, index) => ( +
+ {part.type === 'json' ? ( + + ) : ( + {part.content} + )} +
+ ))} + + ); +}; const AIChatPanel = ({ scene }) => { const [messages, setMessages] = useState([]); @@ -76,6 +141,7 @@ const AIChatPanel = ({ scene }) => { chatContainerRef.current.scrollHeight; } }, [messages]); + return (
@@ -84,7 +150,7 @@ const AIChatPanel = ({ scene }) => {
{messages.map((message, index) => (
- {message.content} +
))} {isLoading &&
Thinking...
} diff --git a/src/editor/style/chat-panel.scss b/src/editor/style/chat-panel.scss index c21227f8c..afa7aba04 100644 --- a/src/editor/style/chat-panel.scss +++ b/src/editor/style/chat-panel.scss @@ -34,6 +34,46 @@ &.assistant { align-self: flex-start; background-color: variables.$darkgray-500; + + // Ensure JSON blocks expand properly within assistant messages + .json-block { + width: 100%; + margin: 0.5em 0; + } + + // Override react-json-pretty default styles + .json-pretty { + width: 100% !important; + max-width: none !important; + font-family: 'Fira Code', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', + monospace !important; + font-size: 13px !important; + line-height: 1.4 !important; + background-color: variables.$darkgray-900 !important; + padding: 8px !important; + border-radius: 6px !important; + overflow-x: auto !important; + + // Style JSON keys + .__json-key__ { + color: variables.$purple-100 !important; + } + + // Style JSON strings + .__json-string__ { + color: variables.$green-100 !important; + } + + // Style JSON values (numbers, booleans) + .__json-value__ { + color: variables.$blue-100 !important; + } + + // Style JSON punctuation + .__json-punctuation__ { + color: variables.$gray-300 !important; + } + } } } From 558dcb7191e8844b2465e48dd0ca40727f35817b Mon Sep 17 00:00:00 2001 From: Kieran Farr Date: Mon, 30 Dec 2024 23:12:22 -0800 Subject: [PATCH 4/7] copy button styling is a hot mess --- src/editor/components/widgets/AIChatPanel.js | 28 +++++++++++- src/editor/style/chat-panel.scss | 47 ++++++++++++++++++-- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/editor/components/widgets/AIChatPanel.js b/src/editor/components/widgets/AIChatPanel.js index 31d93135b..d760fbc61 100644 --- a/src/editor/components/widgets/AIChatPanel.js +++ b/src/editor/components/widgets/AIChatPanel.js @@ -4,6 +4,29 @@ import { getGenerativeModel } from 'firebase/vertexai'; import Collapsible from '../Collapsible'; import JSONPretty from 'react-json-pretty'; import 'react-json-pretty/themes/monikai.css'; +import { Copy32Icon } from '../../icons'; + +// Helper component for the copy button +const CopyButton = ({ jsonData }) => { + const [copied, setCopied] = useState(false); + + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(JSON.stringify(jsonData, null, 2)); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (err) { + console.error('Failed to copy:', err); + } + }; + + return ( + + ); +}; // Helper component to render message content with JSON formatting const MessageContent = ({ content }) => { @@ -58,7 +81,10 @@ const MessageContent = ({ content }) => { {parts.map((part, index) => (
{part.type === 'json' ? ( - + <> + + + ) : ( {part.content} )} diff --git a/src/editor/style/chat-panel.scss b/src/editor/style/chat-panel.scss index afa7aba04..a215bffa5 100644 --- a/src/editor/style/chat-panel.scss +++ b/src/editor/style/chat-panel.scss @@ -34,29 +34,37 @@ &.assistant { align-self: flex-start; background-color: variables.$darkgray-500; + width: 100%; // Ensure full width for JSON content // Ensure JSON blocks expand properly within assistant messages .json-block { width: 100%; margin: 0.5em 0; + position: relative; + padding-right: 80px; // Make room for the copy button + background-color: variables.$darkgray-900; // Darker background for JSON + border-radius: 6px; + overflow: hidden; // Contain the JSON content } // Override react-json-pretty default styles .json-pretty { width: 100% !important; max-width: none !important; - font-family: 'Fira Code', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', + font-family: Monaco, 'Andale Mono', 'Ubuntu Mono', 'Fira Code', Consolas, monospace !important; font-size: 13px !important; line-height: 1.4 !important; background-color: variables.$darkgray-900 !important; - padding: 8px !important; + padding: 12px !important; border-radius: 6px !important; overflow-x: auto !important; + color: variables.$white !important; // Ensure base text is visible // Style JSON keys .__json-key__ { color: variables.$purple-100 !important; + font-weight: 600 !important; } // Style JSON strings @@ -73,6 +81,37 @@ .__json-punctuation__ { color: variables.$gray-300 !important; } + + // Add some spacing between properties + .json-pretty-key { + margin-right: 8px !important; + } + } + + .copy-button { + position: absolute; + right: 8px; + top: 8px; + background: variables.$darkgray-700; + border: 1px solid variables.$darkgray-600; + cursor: pointer; + padding: 4px 8px; + border-radius: 4px; + color: variables.$gray-300; + display: flex; + align-items: center; + gap: 4px; + font-size: 12px; + z-index: 1; + + &:hover { + background: variables.$darkgray-600; + color: variables.$white; + } + + &:active { + background: variables.$darkgray-500; + } } } } @@ -106,11 +145,11 @@ cursor: pointer; &:hover { - background-color: variables.$purple-100; + background-color: variables.$purple-700; } &:active { - background-color: variables.$purple-200; + background-color: variables.$purple-600; } &:disabled { From c14779c8b62aa016792313553004b8425189b71f Mon Sep 17 00:00:00 2001 From: Kieran Farr Date: Tue, 31 Dec 2024 09:51:34 -0800 Subject: [PATCH 5/7] move and provide better context --- src/editor/components/Main.js | 4 ++-- .../{widgets => scenegraph}/AIChatPanel.js | 20 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) rename src/editor/components/{widgets => scenegraph}/AIChatPanel.js (90%) diff --git a/src/editor/components/Main.js b/src/editor/components/Main.js index 5c596d756..ebf49f46d 100644 --- a/src/editor/components/Main.js +++ b/src/editor/components/Main.js @@ -21,7 +21,7 @@ import { NewModal } from './modals/NewModal'; import { ToolbarWrapper } from './scenegraph/ToolbarWrapper.js'; import useStore from '@/store'; import { AIChatProvider } from '../contexts/AIChatContext'; -import AIChatPanel from './widgets/AIChatPanel'; +import AIChatPanel from './scenegraph/AIChatPanel'; THREE.ImageUtils.crossOrigin = ''; @@ -120,7 +120,7 @@ export default function Main() { selectedEntity={state.entity} visible={state.visible.scenegraph} /> - +
{ @@ -94,7 +94,7 @@ const MessageContent = ({ content }) => { ); }; -const AIChatPanel = ({ scene }) => { +const AIChatPanel = () => { const [messages, setMessages] = useState([]); const [input, setInput] = useState(''); const [isLoading, setIsLoading] = useState(false); @@ -103,7 +103,6 @@ const AIChatPanel = ({ scene }) => { useEffect(() => { console.log('AIChatPanel mounted'); - console.log('Scene available:', !!scene); const initializeAI = async () => { try { console.log('Initializing Vertex AI'); @@ -128,14 +127,17 @@ const AIChatPanel = ({ scene }) => { setInput(''); try { - // Get the current scene state - const sceneState = scene.current - ? scene.current.getAttribute('managed-street') - : null; + // generate json from 3dstreet core + const entity = document.getElementById('street-container'); + const data = STREET.utils.convertDOMElToObject(entity); + const filteredData = JSON.parse(STREET.utils.filterJSONstreet(data)); + + // fetch the same serialized data from the scene that is used for saving + const sceneJSON = filteredData.data; const prompt = ` Context: You are a 3D street scene assistant. The current scene has the following state: - ${JSON.stringify(sceneState, null, 2)} + ${JSON.stringify(sceneJSON, null, 2)} User request: ${input} From 0a1c06c03c61482f4688a3d180edfd9aa5e16f5d Mon Sep 17 00:00:00 2001 From: Kieran Farr Date: Thu, 2 Jan 2025 19:08:29 -0800 Subject: [PATCH 6/7] barely working vertex ai --- .../components/scenegraph/AIChatPanel.js | 236 ++++++++++++++++-- src/editor/services/aiChatService.js | 37 --- 2 files changed, 222 insertions(+), 51 deletions(-) diff --git a/src/editor/components/scenegraph/AIChatPanel.js b/src/editor/components/scenegraph/AIChatPanel.js index 6dde6cc9e..be4094864 100644 --- a/src/editor/components/scenegraph/AIChatPanel.js +++ b/src/editor/components/scenegraph/AIChatPanel.js @@ -28,6 +28,163 @@ const CopyButton = ({ jsonData }) => { ); }; +function calculateArithmeticExpression(expression) { + console.log('calculateArithmeticExpression:', expression); + + // Remove all whitespace + const cleanExpr = expression.replace(/\s+/g, ''); + + // Only allow numbers, basic operators, and parentheses + if (!/^[-+0-9\s()*/%.]*$/.test(cleanExpr)) { + throw new Error('Invalid expression: contains forbidden characters'); + } + + const numbers = []; + const operators = []; + + const precedence = { + '+': 1, + '-': 1, + '*': 2, + '/': 2, + '%': 2, + '(': 0 + }; + + const applyOperation = () => { + const b = numbers.pop(); + const a = numbers.pop(); + const op = operators.pop(); + + if (a === undefined || b === undefined) { + throw new Error('Invalid expression: not enough operands'); + } + + switch (op) { + case '+': + numbers.push(a + b); + break; + case '-': + numbers.push(a - b); + break; + case '*': + numbers.push(a * b); + break; + case '/': + if (b === 0) throw new Error('Division by zero'); + numbers.push(a / b); + break; + case '%': + if (b === 0) throw new Error('Modulo by zero'); + numbers.push(a % b); + break; + default: + throw new Error(`Invalid operator: ${op}`); + } + }; + + let i = 0; + while (i < cleanExpr.length) { + // Handle numbers (including decimals and negatives) + if (cleanExpr[i] === '-' && (i === 0 || cleanExpr[i - 1] === '(')) { + // This is a negative number, not a subtraction operator + let numStr = '-'; + i++; + while ( + i < cleanExpr.length && + (/\d/.test(cleanExpr[i]) || cleanExpr[i] === '.') + ) { + numStr += cleanExpr[i]; + i++; + } + numbers.push(parseFloat(numStr)); + continue; + } + + if (/\d/.test(cleanExpr[i])) { + let numStr = ''; + while ( + i < cleanExpr.length && + (/\d/.test(cleanExpr[i]) || cleanExpr[i] === '.') + ) { + numStr += cleanExpr[i]; + i++; + } + numbers.push(parseFloat(numStr)); + continue; + } + + // Handle operators and parentheses + if (cleanExpr[i] === '(') { + operators.push(cleanExpr[i]); + } else if (cleanExpr[i] === ')') { + while (operators.length > 0 && operators[operators.length - 1] !== '(') { + applyOperation(); + } + if (operators.length === 0) { + throw new Error('Invalid expression: mismatched parentheses'); + } + operators.pop(); // Remove the '(' + } else if (['+', '-', '*', '/', '%'].includes(cleanExpr[i])) { + while ( + operators.length > 0 && + operators[operators.length - 1] !== '(' && + precedence[operators[operators.length - 1]] >= precedence[cleanExpr[i]] + ) { + applyOperation(); + } + operators.push(cleanExpr[i]); + } + i++; + } + + // Process remaining operators + while (operators.length > 0) { + if (operators[operators.length - 1] === '(') { + throw new Error('Invalid expression: mismatched parentheses'); + } + applyOperation(); + } + + if (numbers.length !== 1) { + throw new Error('Invalid expression: incorrect number of operands'); + } + + console.log('Result:', numbers[0]); + return numbers[0]; +} + +function evaluateEmbeddedExpressions(obj) { + if (Array.isArray(obj)) { + return obj.map(evaluateEmbeddedExpressions); + } else if (typeof obj === 'object' && obj !== null) { + const newObj = {}; + for (const key in obj) { + if (key.startsWith('expression-for-')) { + newObj[key.replace('expression-for-', '')] = + calculateArithmeticExpression(obj[key]); + } else { + newObj[key] = evaluateEmbeddedExpressions(obj[key]); + } + } + return newObj; + } + return obj; +} + +function executeCommand(command) { + if (command.command && command.payload) { + const newCommandPayload = { + entity: document.getElementById(command.payload['entity-id']), + component: command.payload.component, + property: command.payload.property, + value: command.payload.value + }; + console.log('newCommandPayload:', newCommandPayload); + AFRAME.INSPECTOR.execute(command.command, newCommandPayload); + } +} + // Helper component to render message content with JSON formatting const MessageContent = ({ content }) => { const formatContent = (text) => { @@ -37,7 +194,6 @@ const MessageContent = ({ content }) => { let match; while ((match = jsonBlockRegex.exec(text)) !== null) { - // Add text before the JSON block if (match.index > currentIndex) { parts.push({ type: 'text', @@ -46,14 +202,12 @@ const MessageContent = ({ content }) => { } try { - // Try to parse the JSON const jsonContent = JSON.parse(match[1]); parts.push({ type: 'json', content: jsonContent }); } catch (e) { - // If parsing fails, treat as regular text parts.push({ type: 'text', content: match[0] @@ -63,7 +217,6 @@ const MessageContent = ({ content }) => { currentIndex = match.index + match[0].length; } - // Add any remaining text if (currentIndex < text.length) { parts.push({ type: 'text', @@ -107,7 +260,7 @@ const AIChatPanel = () => { try { console.log('Initializing Vertex AI'); modelRef.current = getGenerativeModel(vertexAI, { - model: 'gemini-1.5-flash' + model: 'gemini-2.0-flash-exp' }); console.log('Vertex AI initialized successfully'); } catch (error) { @@ -125,29 +278,66 @@ const AIChatPanel = () => { const userMessage = { role: 'user', content: input }; setMessages((prev) => [...prev, userMessage]); setInput(''); + let aiMessage; try { - // generate json from 3dstreet core const entity = document.getElementById('street-container'); const data = STREET.utils.convertDOMElToObject(entity); const filteredData = JSON.parse(STREET.utils.filterJSONstreet(data)); - - // fetch the same serialized data from the scene that is used for saving const sceneJSON = filteredData.data; const prompt = ` - Context: You are a 3D street scene assistant. The current scene has the following state: - ${JSON.stringify(sceneJSON, null, 2)} + Context: You are a 3D street scene assistant for the 3DStreet application. + The current scene has the following state: + ${JSON.stringify(sceneJSON, null, 2)} + + User request: ${input} + + Please analyze the request and provide one of the following: + 1. If the user is asking about the scene, provide a natural language explanation + 2. If the user is asking to modify the scene, provide specific JSON-formatted changes + 3. If the user needs help, provide relevant guidance about the 3DStreet editor + + In the scene state, units for length are in meters, and rotations are in degrees. + + Write your response directly to the user. Do not describe the user's request. - User request: ${input} + For scene modifications, imagine a JSON format similar to this: + { + "command": "entityupdate", + "payload": { + "entity-id": "n9eLgB9C635T_edXuXIgz", + "component": "position", + "property": "x", + "value": 10 + } + } + + This describes a change to entities in an A-Frame scene. + + When changing a model, use the "entityupdate" command with the following payload: + { + "entity-id": "n9eLgB9C635T_edXuXIgz", + "component": "mixin", + "value": "fire-truck-rig" + } + + The possible model (mixin) values are: Bicycle_1, bus, sedan-rig, sedan-taxi-rig, suv-rig, box-truck-rig, food-trailer-rig, fire-truck-rig, fire-ladder-rig, trash-truck-side-loading, self-driving-cruise-car-rig, self-driving-waymo-car, tuk-tuk, motorbike, cyclist-cargo, cyclist1, cyclist2, cyclist3, cyclist-kid, cyclist-dutch, char1, char2, char3, char4, char5, char6, char7, char8, char9, char10, char11, char12, char13, char14, char15, char16, tram, trolley, minibus, dividers-flowers, dividers-planting-strip, dividers-planter-box, dividers-bush, dividers-dome, safehit, bollard, temporary-barricade, temporary-traffic-cone, temporary-jersey-barrier-plastic, temporary-jersey-barrier-concrete, street-element-crosswalk-raised, street-element-traffic-island-end-rounded, street-element-sign-warning-ped-rrfb, street-element-traffic-post-k71, street-element-traffic-island, street-element-speed-hump, crosswalk-zebra-box, traffic-calming-bumps, corner-island, brt-station, outdoor_dining, bench_orientation_center, parklet, utility_pole, lamp-modern, lamp-modern-double, bikerack, bikeshare, lamp-traditional, palm-tree, bench, seawall, track, tree3, bus-stop, bus-stop-alternate, wayfinding, signal_left, signal_right, stop_sign, trash-bin, lending-library, residential-mailbox, USPS-mailbox, picnic-bench, large-parklet, SM3D_Bld_Mixed_Corner_4fl, SM3D_Bld_Mixed_Double_5fl, SM3D_Bld_Mixed_4fl_2, SM3D_Bld_Mixed_5fl, SM3D_Bld_Mixed_4fl, SM_Bld_House_Preset_03_1800, SM_Bld_House_Preset_08_1809, SM_Bld_House_Preset_09_1845, arched-building-01, arched-building-02, arched-building-03, arched-building-04, ElectricScooter_1, Character_1_M, magic-carpet, cyclist-cargo - Please provide suggestions for modifying the scene. Format your response as JSON when suggesting specific changes. + The orientation of axis to cardinal directions is as follows: x+ (positive) is north; x- (negative) is south; y+ (positive) is up; y- (negative) is down; z- (negative) is west; z+ (positive) is east; + Models face z- (east) when at 0ยบ Y rotation. + + Make sure you convert everything to the appropriate units, even if the user uses different units. + + If you have to pass an arithmetic expression, like 5 - 2, put it in quotes like "5 - 2", and replace + the name of the key with "expression-for-" prepended, so, for example, "value" would become + "expression-for-value". `; const result = await modelRef.current.generateContent(prompt); const response = await result.response; - const aiMessage = { role: 'assistant', content: response.text() }; - + const responseText = response.text(); + aiMessage = { role: 'assistant', content: responseText }; setMessages((prev) => [...prev, aiMessage]); } catch (error) { console.error('Error generating response:', error); @@ -160,6 +350,24 @@ const AIChatPanel = () => { ]); } finally { setIsLoading(false); + + // Parse the most recent message for commands and execute them + const lastMessage = aiMessage; + console.log('lastMessage', lastMessage); + if (lastMessage && lastMessage.role === 'assistant') { + const jsonBlockRegex = /```(?:json)?\s*(\{[\s\S]*?\})\s*```/g; + let match; + while ((match = jsonBlockRegex.exec(lastMessage.content)) !== null) { + try { + const jsonContent = JSON.parse(match[1]); + console.log('jsonContent', jsonContent); + const evaluatedContent = evaluateEmbeddedExpressions(jsonContent); + executeCommand(evaluatedContent); + } catch (e) { + console.error('Error processing command:', e); + } + } + } } }; diff --git a/src/editor/services/aiChatService.js b/src/editor/services/aiChatService.js index f3e371ace..9d779a5e5 100644 --- a/src/editor/services/aiChatService.js +++ b/src/editor/services/aiChatService.js @@ -18,43 +18,6 @@ class AIChatService { } } - async generateResponse(prompt, sceneState) { - if (!this.model) { - throw new Error('AI model not initialized'); - } - - const formattedPrompt = this.formatPrompt(prompt, sceneState); - const result = await this.model.generateContent(formattedPrompt); - return result.response.text(); - } - - formatPrompt(userInput, sceneState) { - return ` - Context: You are a 3D street scene assistant for the 3DStreet application. - The current scene has the following state: - ${JSON.stringify(sceneState, null, 2)} - - User request: ${userInput} - - Please analyze the request and provide one of the following: - 1. If the user is asking to modify the scene, provide specific JSON-formatted changes - 2. If the user is asking about the scene, provide a natural language explanation - 3. If the user needs help, provide relevant guidance about the 3DStreet editor - - For scene modifications, use this JSON format: - { - "action": "modify_scene", - "changes": [ - { - "type": "add"|"remove"|"update", - "element": "", - "properties": {} - } - ] - } - `; - } - parseResponse(response) { try { // Check if the response is JSON From 4ffd563fa344b58c23536d8496f789548395fe66 Mon Sep 17 00:00:00 2001 From: Kieran Farr Date: Fri, 3 Jan 2025 10:31:37 -0800 Subject: [PATCH 7/7] add old model in comment --- src/editor/components/scenegraph/AIChatPanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor/components/scenegraph/AIChatPanel.js b/src/editor/components/scenegraph/AIChatPanel.js index be4094864..38e8e8532 100644 --- a/src/editor/components/scenegraph/AIChatPanel.js +++ b/src/editor/components/scenegraph/AIChatPanel.js @@ -260,7 +260,7 @@ const AIChatPanel = () => { try { console.log('Initializing Vertex AI'); modelRef.current = getGenerativeModel(vertexAI, { - model: 'gemini-2.0-flash-exp' + model: 'gemini-2.0-flash-exp' // model: 'gemini-1.5-flash' }); console.log('Vertex AI initialized successfully'); } catch (error) {