From 796d8031e8d2c82fa18de6ec8de1cd94c2ed0128 Mon Sep 17 00:00:00 2001 From: Daniel Avila Date: Tue, 14 Mar 2023 20:21:41 -0400 Subject: [PATCH] fix: ensure custom params are not passed to non custom models --- api/package-lock.json | 274 +++++++++++++++++- api/package.json | 3 +- api/server/routes/ask.js | 92 +++--- api/server/routes/askBing.js | 94 +++--- api/server/routes/askSydney.js | 96 +++--- client/package-lock.json | 12 +- .../components/Conversations/Conversation.jsx | 16 +- client/src/components/Models/ModelMenu.jsx | 6 +- client/src/components/Nav/index.jsx | 56 ++-- client/src/store/submitSlice.js | 5 +- 10 files changed, 503 insertions(+), 151 deletions(-) diff --git a/api/package-lock.json b/api/package-lock.json index daa36e69e..f934f00b8 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -19,7 +19,8 @@ "keyv-file": "^0.2.0", "lodash": "^4.17.21", "mongoose": "^6.9.0", - "openai": "^3.1.0" + "openai": "^3.1.0", + "sanitize-html": "^2.10.0" }, "devDependencies": { "nodemon": "^2.0.20", @@ -2211,6 +2212,14 @@ } } }, + "node_modules/deepmerge": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", + "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -2247,6 +2256,57 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dotenv": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", @@ -2278,6 +2338,17 @@ "node": ">= 0.8" } }, + "node_modules/entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2751,6 +2822,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/htmlparser2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -2958,6 +3047,14 @@ "node": ">=0.12.0" } }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -3273,6 +3370,17 @@ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -3469,6 +3577,11 @@ "p-defer": "^3.0.0" } }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -3577,6 +3690,29 @@ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.1.0.tgz", "integrity": "sha512-KO0m2f1HkrPe9S0ldjx7za9BJjeHqBku5Ch8JyxETxT8dEFGz1PwgrHaOQupVYitpzbFSYm7nnljxD8dik2c+g==" }, + "node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -3796,6 +3932,30 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sanitize-html": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.10.0.tgz", + "integrity": "sha512-JqdovUd81dG4k87vZt6uA6YhDfWkUGruUu/aPmXLxXi45gZExnt9Bnw/qeQU8oGf82vPyaE0vO4aH0PbobB9JQ==", + "dependencies": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^8.0.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + } + }, + "node_modules/sanitize-html/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/saslprep": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", @@ -3985,6 +4145,14 @@ "atomic-sleep": "^1.0.0" } }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", @@ -6275,6 +6443,11 @@ "ms": "2.1.2" } }, + "deepmerge": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", + "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==" + }, "defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -6298,6 +6471,39 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "requires": { + "domelementtype": "^2.3.0" + } + }, + "domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + } + }, "dotenv": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", @@ -6323,6 +6529,11 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, + "entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -6687,6 +6898,17 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, + "htmlparser2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" + } + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -6826,6 +7048,11 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -7074,6 +7301,11 @@ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -7217,6 +7449,11 @@ "p-defer": "^3.0.0" } }, + "parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -7303,6 +7540,16 @@ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.1.0.tgz", "integrity": "sha512-KO0m2f1HkrPe9S0ldjx7za9BJjeHqBku5Ch8JyxETxT8dEFGz1PwgrHaOQupVYitpzbFSYm7nnljxD8dik2c+g==" }, + "postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -7458,6 +7705,26 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "sanitize-html": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.10.0.tgz", + "integrity": "sha512-JqdovUd81dG4k87vZt6uA6YhDfWkUGruUu/aPmXLxXi45gZExnt9Bnw/qeQU8oGf82vPyaE0vO4aH0PbobB9JQ==", + "requires": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^8.0.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + } + } + }, "saslprep": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", @@ -7615,6 +7882,11 @@ "atomic-sleep": "^1.0.0" } }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + }, "sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", diff --git a/api/package.json b/api/package.json index 6dcf344ea..561908fad 100644 --- a/api/package.json +++ b/api/package.json @@ -29,7 +29,8 @@ "keyv-file": "^0.2.0", "lodash": "^4.17.21", "mongoose": "^6.9.0", - "openai": "^3.1.0" + "openai": "^3.1.0", + "sanitize-html": "^2.10.0" }, "devDependencies": { "nodemon": "^2.0.20", diff --git a/api/server/routes/ask.js b/api/server/routes/ask.js index 8d20b808d..265672db8 100644 --- a/api/server/routes/ask.js +++ b/api/server/routes/ask.js @@ -7,7 +7,7 @@ const { titleConvo, askClient, browserClient, - customClient, + customClient // detectCode } = require('../../app/'); const { getConvo, saveMessage, getConvoTitle, saveConvo } = require('../../models'); @@ -18,7 +18,7 @@ router.use('/bing', askBing); router.use('/sydney', askSydney); router.post('/', async (req, res) => { - let { model, text, parentMessageId, conversationId: oldConversationId , ...convo } = req.body; + let { model, text, parentMessageId, conversationId: oldConversationId, ...convo } = req.body; if (text.length === 0) { return handleError(res, { text: 'Prompt empty or too short' }); } @@ -26,14 +26,14 @@ router.post('/', async (req, res) => { const conversationId = oldConversationId || crypto.randomUUID(); const userMessageId = crypto.randomUUID(); - const userParentMessageId = parentMessageId || '00000000-0000-0000-0000-000000000000' + const userParentMessageId = parentMessageId || '00000000-0000-0000-0000-000000000000'; let userMessage = { - messageId: userMessageId, - sender: 'User', - text, + messageId: userMessageId, + sender: 'User', + text, parentMessageId: userParentMessageId, - conversationId, - isCreatedByUser: true + conversationId, + isCreatedByUser: true }; console.log('ask log', { @@ -55,27 +55,28 @@ router.post('/', async (req, res) => { await saveConvo({ ...userMessage, model, ...convo }); return await ask({ - userMessage, + userMessage, model, convo, preSendRequest: true, - req, res + req, + res }); -}) +}); router.post('/regenerate', async (req, res) => { - const { parentMessageId, model, chatGptLabel, promptPrefix } = req.body; + const { model } = req.body; - const oldUserMessage = await getMessages({ messageId: req.body }) + const oldUserMessage = await getMessages({ messageId: req.body }); if (oldUserMessage) { - const convo = await getConvo(userMessage?.conversationId) + const convo = await getConvo(userMessage?.conversationId); const userMessageId = crypto.randomUUID(); let userMessage = { ...userMessage, - messageId: userMessageId, + messageId: userMessageId }; console.log('ask log for regeneration', { @@ -85,14 +86,14 @@ router.post('/regenerate', async (req, res) => { }); return await ask({ - userMessage, + userMessage, model, convo, preSendRequest: false, - req, res + req, + res }); - } else - return handleError(res, { text: 'Parent message not found' }); + } else return handleError(res, { text: 'Parent message not found' }); // if (model === 'chatgptCustom' && !chatGptLabel && conversationId) { // const convo = await getConvo({ conversationId }); @@ -106,15 +107,21 @@ router.post('/regenerate', async (req, res) => { // await saveConvo({ ...userMessage, model, chatGptLabel, promptPrefix }); }); -const ask = async ({ - userMessage, +const ask = async ({ + userMessage, overrideParentMessageId = null, model, convo, preSendRequest = true, - req, res + req, + res }) => { - let { sender, text, parentMessageId: userParentMessageId, conversationId, messageId: userMessageId } = userMessage; + let { + text, + parentMessageId: userParentMessageId, + conversationId, + messageId: userMessageId + } = userMessage; let client; @@ -134,14 +141,13 @@ const ask = async ({ 'X-Accel-Buffering': 'no' }); - if (preSendRequest) - sendMessage(res, { message: userMessage, created: true }); + if (preSendRequest) sendMessage(res, { message: userMessage, created: true }); try { const progressCallback = createOnProgress(); let gptResponse = await client({ text, - onProgress: progressCallback.call(null, model, {res, text }), + onProgress: progressCallback.call(null, model, { res, text }), convo: { parentMessageId: userParentMessageId, conversationId, @@ -168,16 +174,20 @@ const ask = async ({ gptResponse.text.toLowerCase().includes('no response') || gptResponse.text.toLowerCase().includes('no answer') ) { - await saveMessage({ - messageId: crypto.randomUUID(), sender: model, - conversationId, parentMessageId: overrideParentMessageId || userMessageId, - error: true, text: 'Prompt empty or too short'}); + await saveMessage({ + messageId: crypto.randomUUID(), + sender: model, + conversationId, + parentMessageId: overrideParentMessageId || userMessageId, + error: true, + text: 'Prompt empty or too short' + }); return handleError(res, { text: 'Prompt empty or too short' }); } gptResponse.sender = model === 'chatgptCustom' ? convo.chatGptLabel : model; + gptResponse.model = model; // gptResponse.final = true; - // gptResponse.text = await detectCode(gptResponse.text); gptResponse.text = await handleText(gptResponse.text); if (convo.chatGptLabel?.length > 0 && model === 'chatgptCustom') { @@ -189,14 +199,14 @@ const ask = async ({ } // override the parentMessageId, for the regeneration. - gptResponse.parentMessageId = overrideParentMessageId || userMessageId + gptResponse.parentMessageId = overrideParentMessageId || userMessageId; await saveMessage(gptResponse); await saveConvo(gptResponse); sendMessage(res, { title: await getConvoTitle(conversationId), - final: true, - requestMessage: userMessage, + final: true, + requestMessage: userMessage, responseMessage: gptResponse }); res.end(); @@ -213,15 +223,19 @@ const ask = async ({ await saveConvo({ conversationId, title - }) + }); } } catch (error) { console.log(error); // await deleteMessages({ messageId: userMessageId }); - const errorMessage = { - messageId: crypto.randomUUID(), sender: model, - conversationId, parentMessageId: overrideParentMessageId || userMessageId, - error: true, text: error.message} + const errorMessage = { + messageId: crypto.randomUUID(), + sender: model, + conversationId, + parentMessageId: overrideParentMessageId || userMessageId, + error: true, + text: error.message + }; await saveMessage(errorMessage); handleError(res, errorMessage); } diff --git a/api/server/routes/askBing.js b/api/server/routes/askBing.js index 5bb8abd4f..066b64fae 100644 --- a/api/server/routes/askBing.js +++ b/api/server/routes/askBing.js @@ -7,26 +7,32 @@ const { handleError, sendMessage, createOnProgress, handleText } = require('./ha const citationRegex = /\[\^\d+?\^]/g; router.post('/', async (req, res) => { - const { model, text, parentMessageId, conversationId: oldConversationId, ...convo } = req.body; + const { + model, + text, + parentMessageId, + conversationId: oldConversationId, + ...convo + } = req.body; if (text.length === 0) { return handleError(res, { text: 'Prompt empty or too short' }); } const conversationId = oldConversationId || crypto.randomUUID(); - const isNewConversation = !oldConversationId + const isNewConversation = !oldConversationId; const userMessageId = crypto.randomUUID(); - const userParentMessageId = parentMessageId || '00000000-0000-0000-0000-000000000000' + const userParentMessageId = parentMessageId || '00000000-0000-0000-0000-000000000000'; let userMessage = { - messageId: userMessageId, - sender: 'User', - text, + messageId: userMessageId, + sender: 'User', + text, parentMessageId: userParentMessageId, - conversationId, - isCreatedByUser: true - }; + conversationId, + isCreatedByUser: true + }; - console.log('ask log', { + console.log('ask log', { model, ...userMessage, ...convo @@ -37,24 +43,31 @@ router.post('/', async (req, res) => { return await ask({ isNewConversation, - userMessage, + userMessage, model, convo, preSendRequest: true, - req, res + req, + res }); -}) +}); -const ask = async ({ +const ask = async ({ isNewConversation, overrideParentMessageId = null, - userMessage, + userMessage, model, convo, preSendRequest = true, - req, res + req, + res }) => { - let { sender, text, parentMessageId: userParentMessageId, conversationId, messageId: userMessageId } = userMessage; + let { + text, + parentMessageId: userParentMessageId, + conversationId, + messageId: userMessageId + } = userMessage; res.writeHead(200, { Connection: 'keep-alive', @@ -64,19 +77,22 @@ const ask = async ({ 'X-Accel-Buffering': 'no' }); - if (preSendRequest) - sendMessage(res, { message: userMessage, created: true }); + if (preSendRequest) sendMessage(res, { message: userMessage, created: true }); try { const progressCallback = createOnProgress(); let response = await askBing({ text, - onProgress: progressCallback.call(null, model, {res, text, parentMessageId: overrideParentMessageId || userMessageId }), + onProgress: progressCallback.call(null, model, { + res, + text, + parentMessageId: overrideParentMessageId || userMessageId + }), convo: { ...convo, parentMessageId: userParentMessageId, - conversationId, - }, + conversationId + } }); console.log('BING RESPONSE', response); @@ -88,13 +104,16 @@ const ask = async ({ userMessage.conversationId = response.conversationId || conversationId; userMessage.invocationId = response.invocationId; await saveMessage(userMessage); - + // Bing API will not use our conversationId at the first time, // so change the placeholder conversationId to the real one. // Attition: the api will also create new conversationId while using invalid userMessage.parentMessageId, // but in this situation, don't change the conversationId, but create new convo. - if (conversationId != userMessage.conversationId && isNewConversation) - await saveConvo({ conversationId: conversationId, newConversationId: userMessage.conversationId }); + if (conversationId != userMessage.conversationId && isNewConversation) + await saveConvo({ + conversationId: conversationId, + newConversationId: userMessage.conversationId + }); conversationId = userMessage.conversationId; response.text = response.response; @@ -107,7 +126,8 @@ const ask = async ({ // response.final = true; // override the parentMessageId, for the regeneration. - response.parentMessageId = overrideParentMessageId || response.parentMessageId || userMessageId; + response.parentMessageId = + overrideParentMessageId || response.parentMessageId || userMessageId; const links = getCitations(response); response.text = @@ -116,11 +136,11 @@ const ask = async ({ response.text = await handleText(response.text); await saveMessage(response); - await saveConvo({...response, model, ...convo}); + await saveConvo({ ...response, model, chatGptLabel: null, promptPrefix: null, ...convo }); sendMessage(res, { title: await getConvoTitle(conversationId), - final: true, - requestMessage: userMessage, + final: true, + requestMessage: userMessage, responseMessage: response }); res.end(); @@ -133,19 +153,23 @@ const ask = async ({ }); console.log('CONVERSATION TITLE', title); - + await saveConvo({ conversationId, title - }) + }); } } catch (error) { console.log(error); // await deleteMessages({ messageId: userMessageId }); - const errorMessage = { - messageId: crypto.randomUUID(), sender: model, - conversationId, parentMessageId: overrideParentMessageId || userMessageId, - error: true, text: error.message} + const errorMessage = { + messageId: crypto.randomUUID(), + sender: model, + conversationId, + parentMessageId: overrideParentMessageId || userMessageId, + error: true, + text: error.message + }; await saveMessage(errorMessage); handleError(res, errorMessage); } diff --git a/api/server/routes/askSydney.js b/api/server/routes/askSydney.js index a0a3bd32d..03e3479be 100644 --- a/api/server/routes/askSydney.js +++ b/api/server/routes/askSydney.js @@ -7,26 +7,32 @@ const { handleError, sendMessage, createOnProgress, handleText } = require('./ha const citationRegex = /\[\^\d+?\^]/g; router.post('/', async (req, res) => { - const { model, text, parentMessageId, conversationId: oldConversationId, ...convo } = req.body; + const { + model, + text, + parentMessageId, + conversationId: oldConversationId, + ...convo + } = req.body; if (text.length === 0) { return handleError(res, { text: 'Prompt empty or too short' }); } const conversationId = oldConversationId || crypto.randomUUID(); - const isNewConversation = !oldConversationId + const isNewConversation = !oldConversationId; const userMessageId = crypto.randomUUID(); - const userParentMessageId = parentMessageId || '00000000-0000-0000-0000-000000000000' + const userParentMessageId = parentMessageId || '00000000-0000-0000-0000-000000000000'; let userMessage = { - messageId: userMessageId, - sender: 'User', - text, + messageId: userMessageId, + sender: 'User', + text, parentMessageId: userParentMessageId, - conversationId, - isCreatedByUser: true - }; + conversationId, + isCreatedByUser: true + }; - console.log('ask log', { + console.log('ask log', { model, ...userMessage, ...convo @@ -37,24 +43,31 @@ router.post('/', async (req, res) => { return await ask({ isNewConversation, - userMessage, + userMessage, model, convo, preSendRequest: true, - req, res + req, + res }); -}) +}); -const ask = async ({ +const ask = async ({ isNewConversation, overrideParentMessageId = null, - userMessage, + userMessage, model, convo, preSendRequest = true, - req, res + req, + res }) => { - let { sender, text, parentMessageId: userParentMessageId, conversationId, messageId: userMessageId } = userMessage; + let { + text, + parentMessageId: userParentMessageId, + conversationId, + messageId: userMessageId + } = userMessage; res.writeHead(200, { Connection: 'keep-alive', @@ -64,19 +77,22 @@ const ask = async ({ 'X-Accel-Buffering': 'no' }); - if (preSendRequest) - sendMessage(res, { message: userMessage, created: true }); + if (preSendRequest) sendMessage(res, { message: userMessage, created: true }); try { const progressCallback = createOnProgress(); let response = await askSydney({ text, - onProgress: progressCallback.call(null, model, {res, text, parentMessageId: overrideParentMessageId || userMessageId }), + onProgress: progressCallback.call(null, model, { + res, + text, + parentMessageId: overrideParentMessageId || userMessageId + }), convo: { parentMessageId: userParentMessageId, conversationId, ...convo - }, + } }); console.log('SYDNEY RESPONSE', response); @@ -89,13 +105,11 @@ const ask = async ({ userMessage.invocationId = response.invocationId; // Unlike gpt and bing, Sydney will never accept our given userMessage.messageId, it will generate its own one. await saveMessage(userMessage); - + // Save sydney response // response.id = response.messageId; response.invocationId = convo.invocationId ? convo.invocationId + 1 : 1; - response.conversationId = conversationId - ? conversationId - : crypto.randomUUID(); + response.conversationId = conversationId ? conversationId : crypto.randomUUID(); response.conversationSignature = convo.conversationSignature ? convo.conversationSignature : crypto.randomUUID(); @@ -108,7 +122,8 @@ const ask = async ({ // response.final = true; // override the parentMessageId, for the regeneration. - response.parentMessageId = overrideParentMessageId || response.parentMessageId || userMessageId; + response.parentMessageId = + overrideParentMessageId || response.parentMessageId || userMessageId; const links = getCitations(response); response.text = @@ -124,17 +139,20 @@ const ask = async ({ // so change the placeholder conversationId to the real one. // Attition: the api will also create new conversationId while using invalid userMessage.parentMessageId, // but in this situation, don't change the conversationId, but create new convo. - if (conversationId != userMessage.conversationId && isNewConversation) - await saveConvo({ conversationId: conversationId, newConversationId: userMessage.conversationId }); + if (conversationId != userMessage.conversationId && isNewConversation) + await saveConvo({ + conversationId: conversationId, + newConversationId: userMessage.conversationId + }); conversationId = userMessage.conversationId; // Save sydney response & convo, then send await saveMessage(response); - await saveConvo({...response, model, ...convo}); + await saveConvo({ ...response, model, chatGptLabel: null, promptPrefix: null, ...convo }); sendMessage(res, { title: await getConvoTitle(conversationId), - final: true, - requestMessage: userMessage, + final: true, + requestMessage: userMessage, responseMessage: response }); res.end(); @@ -147,19 +165,23 @@ const ask = async ({ }); console.log('CONVERSATION TITLE', title); - + await saveConvo({ conversationId, title - }) + }); } } catch (error) { console.log(error); // await deleteMessages({ messageId: userMessageId }); - const errorMessage = { - messageId: crypto.randomUUID(), sender: model, - conversationId, parentMessageId: overrideParentMessageId || userMessageId, - error: true, text: error.message} + const errorMessage = { + messageId: crypto.randomUUID(), + sender: model, + conversationId, + parentMessageId: overrideParentMessageId || userMessageId, + error: true, + text: error.message + }; await saveMessage(errorMessage); handleError(res, errorMessage); } diff --git a/client/package-lock.json b/client/package-lock.json index fbfcb2b34..d5e302475 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11125,9 +11125,9 @@ } }, "node_modules/webpack": { - "version": "5.75.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", - "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", + "version": "5.76.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", + "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -19431,9 +19431,9 @@ } }, "webpack": { - "version": "5.75.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", - "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", + "version": "5.76.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", + "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.3", diff --git a/client/src/components/Conversations/Conversation.jsx b/client/src/components/Conversations/Conversation.jsx index 4d90ecb2c..b89f9c862 100644 --- a/client/src/components/Conversations/Conversation.jsx +++ b/client/src/components/Conversations/Conversation.jsx @@ -42,6 +42,8 @@ export default function Conversation({ dispatch(setEmptyMessage()); const convo = { title, error: false, conversationId: id, chatGptLabel, promptPrefix }; + // debugging + console.log(model, chatGptLabel, promptPrefix); if (bingData) { const { @@ -77,17 +79,19 @@ export default function Conversation({ if (chatGptLabel) { dispatch(setModel('chatgptCustom')); + dispatch(setCustomModel(chatGptLabel.toLowerCase())); } else { dispatch(setModel(model)); - } - - if (modelMap[model.toLowerCase()]) { - console.log('sender', model); - dispatch(setCustomModel(model.toLowerCase())); - } else { dispatch(setCustomModel(null)); } + // if (modelMap[chatGptLabel.toLowerCase()]) { + // console.log('custom model', chatGptLabel); + // dispatch(setCustomModel(chatGptLabel.toLowerCase())); + // } else { + // dispatch(setCustomModel(null)); + // } + dispatch(setMessages(data)); dispatch(setCustomGpt(convo)); dispatch(setText('')); diff --git a/client/src/components/Models/ModelMenu.jsx b/client/src/components/Models/ModelMenu.jsx index 64d8a427b..05bafc676 100644 --- a/client/src/components/Models/ModelMenu.jsx +++ b/client/src/components/Models/ModelMenu.jsx @@ -46,7 +46,10 @@ export default function ModelMenu() { mutate(); try { const lastSelected = JSON.parse(localStorage.getItem('model')); - if (lastSelected && lastSelected !== 'chatgptCustom' && initial[lastSelected]) { + + if (lastSelected === 'chatgptCustom') { + return; + } else if (initial[lastSelected]) { dispatch(setModel(lastSelected)); } } catch (err) { @@ -72,6 +75,7 @@ export default function ModelMenu() { dispatch(setModel(value)); dispatch(setDisabled(false)); dispatch(setCustomModel(null)); + dispatch(setCustomGpt({ chatGptLabel: null, promptPrefix: null })); } else if (!initial[value]) { const chatGptLabel = modelMap[value]?.chatGptLabel; const promptPrefix = modelMap[value]?.promptPrefix; diff --git a/client/src/components/Nav/index.jsx b/client/src/components/Nav/index.jsx index ea95559cd..9c02a5e1e 100644 --- a/client/src/components/Nav/index.jsx +++ b/client/src/components/Nav/index.jsx @@ -11,22 +11,23 @@ import { increasePage, decreasePage, setPage, setConvos, setPages } from '~/stor export default function Nav({ navVisible, setNavVisible }) { const dispatch = useDispatch(); const [isHovering, setIsHovering] = useState(false); - const { conversationId, convos, pages, pageNumber, refreshConvoHint } = useSelector((state) => state.convo); + const { conversationId, convos, pages, pageNumber, refreshConvoHint } = useSelector( + (state) => state.convo + ); const onSuccess = (data) => { const { conversations, pages } = data; - if (pageNumber > pages) + if (pageNumber > pages) { dispatch(setPage(pages)); - else + } else { dispatch(setConvos(conversations)); - dispatch(setPages(pages)); + dispatch(setPages(pages)); + } }; - const { data, isLoading, mutate } = swr( - `/api/convos?pageNumber=${pageNumber}`, - onSuccess, - {revalidateOnMount: false} - ); + const { data, isLoading, mutate } = swr(`/api/convos?pageNumber=${pageNumber}`, onSuccess, { + revalidateOnMount: false + }); const containerRef = useRef(null); const scrollPositionRef = useRef(null); @@ -36,23 +37,25 @@ export default function Nav({ navVisible, setNavVisible }) { if (container) { scrollPositionRef.current = container.scrollTop; } - } + }; const nextPage = async () => { - moveToTop() + moveToTop(); dispatch(increasePage()); await mutate(); }; const previousPage = async () => { - moveToTop() - + moveToTop(); + dispatch(decreasePage()); await mutate(); }; - useEffect(() => {mutate()}, [pageNumber, conversationId, refreshConvoHint]); + useEffect(() => { + mutate(); + }, [pageNumber, conversationId, refreshConvoHint]); useEffect(() => { const container = containerRef.current; @@ -66,14 +69,14 @@ export default function Nav({ navVisible, setNavVisible }) { }, [data]); useEffect(() => { - setNavVisible(false) - }, [conversationId, ]) + setNavVisible(false); + }, [conversationId]); const toggleNavVisible = () => { setNavVisible((prev) => { - return !prev - }) - } + return !prev; + }); + }; const containerClasses = isLoading && pageNumber === 1 @@ -82,7 +85,12 @@ export default function Nav({ navVisible, setNavVisible }) { return ( <> -
+
-
-
+
); } diff --git a/client/src/store/submitSlice.js b/client/src/store/submitSlice.js index a1b4afee3..a965c2933 100644 --- a/client/src/store/submitSlice.js +++ b/client/src/store/submitSlice.js @@ -6,8 +6,8 @@ const initialState = { stopStream: false, disabled: false, model: 'chatgpt', - promptPrefix: '', - chatGptLabel: '', + promptPrefix: null, + chatGptLabel: null, customModel: null, }; @@ -34,6 +34,7 @@ const currentSlice = createSlice({ state.model = action.payload; }, setCustomGpt: (state, action) => { + console.log('setCustomGpt', action.payload); state.promptPrefix = action.payload.promptPrefix; state.chatGptLabel = action.payload.chatGptLabel; },