diff --git a/.env b/.env index 609e21b05ea..95017b46544 100644 --- a/.env +++ b/.env @@ -109,7 +109,9 @@ PUBLIC_ANNOUNCEMENT_BANNERS=`[ PARQUET_EXPORT_DATASET= PARQUET_EXPORT_HF_TOKEN= -PARQUET_EXPORT_SECRET= +ADMIN_API_SECRET=# secret to admin API calls, like computing usage stats or exporting parquet data + +PARQUET_EXPORT_SECRET=#DEPRECATED, use ADMIN_API_SECRET instead RATE_LIMIT= # requests per minute MESSAGES_BEFORE_LOGIN=# how many messages a user can send in a conversation before having to login. set to 0 to force login right away diff --git a/.env.template b/.env.template index fd895c723bc..889c6526ff7 100644 --- a/.env.template +++ b/.env.template @@ -4,7 +4,9 @@ MODELS=`[ { "name" : "mistralai/Mixtral-8x7B-Instruct-v0.1", "description" : "The latest MoE model from Mistral AI! 8x7B and outperforms Llama 2 70B in most benchmarks.", + "logoUrl": "https://huggingface.co/datasets/huggingchat/models-logo/resolve/main/mistral-logo.png", "websiteUrl" : "https://mistral.ai/news/mixtral-of-experts/", + "modelUrl": "https://huggingface.co/mistralai/Mixtral-8x7B-Instruct-v0.1", "preprompt" : "", "chatPromptTemplate": " {{#each messages}}{{#ifUser}}[INST]{{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}} {{content}} [/INST]{{/ifUser}}{{#ifAssistant}} {{content}} {{/ifAssistant}}{{/each}}", "parameters" : { @@ -29,10 +31,39 @@ MODELS=`[ } ] }, - { + { + "name" : "google/gemma-7b-it", + "description": "Gemma 7B belongs to a family of lightweight models built by Google, based on the same research and technology used to create the Gemini models.", + "websiteUrl" : "https://blog.google/technology/developers/gemma-open-models/", + "logoUrl": "https://huggingface.co/datasets/huggingchat/models-logo/resolve/main/google-logo.png", + "modelUrl": "https://huggingface.co/google/gemma-7b-it", + "preprompt": "", + "chatPromptTemplate" : "{{#each messages}}{{#ifUser}}user\n{{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}}{{content}}\nmodel\n{{/ifUser}}{{#ifAssistant}}{{content}}\n{{/ifAssistant}}{{/each}}", + "promptExamples": [ + { + "title": "Write an email from bullet list", + "prompt": "As a restaurant owner, write a professional email to the supplier to get these products every week: \n\n- Wine (x10)\n- Eggs (x24)\n- Bread (x12)" + }, { + "title": "Code a snake game", + "prompt": "Code a basic snake game in python, give explanations for each step." + }, { + "title": "Assist in a task", + "prompt": "How do I make a delicious lemon cheesecake?" + } + ], + "parameters": { + "do_sample": true, + "truncate": 7168, + "max_new_tokens": 1024, + "stop" : [""] + } + }, + { "name": "meta-llama/Llama-2-70b-chat-hf", "description": "The latest and biggest model from Meta, fine-tuned for chat.", + "logoUrl": "https://huggingface.co/datasets/huggingchat/models-logo/resolve/main/meta-logo.png", "websiteUrl": "https://ai.meta.com/llama/", + "modelUrl": "https://huggingface.co/meta-llama/Llama-2-70b-chat-hf", "preprompt": " ", "chatPromptTemplate" : "[INST] <>\n{{preprompt}}\n<>\n\n{{#each messages}}{{#ifUser}}{{content}} [/INST] {{/ifUser}}{{#ifAssistant}}{{content}} [INST] {{/ifAssistant}}{{/each}}", "promptExamples": [ @@ -60,7 +91,9 @@ MODELS=`[ { "name" : "NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO", "description" : "Nous Hermes 2 Mixtral 8x7B DPO is the new flagship Nous Research model trained over the Mixtral 8x7B MoE LLM.", + "logoUrl": "https://huggingface.co/datasets/huggingchat/models-logo/resolve/main/nous-logo.png", "websiteUrl" : "https://nousresearch.com/", + "modelUrl": "https://huggingface.co/NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO", "chatPromptTemplate" : "{{#if @root.preprompt}}<|im_start|>system\n{{@root.preprompt}}<|im_end|>\n{{/if}}{{#each messages}}{{#ifUser}}<|im_start|>user\n{{content}}<|im_end|>\n<|im_start|>assistant\n{{/ifUser}}{{#ifAssistant}}{{content}}<|im_end|>\n{{/ifAssistant}}{{/each}}", "promptExamples": [ { @@ -88,7 +121,9 @@ MODELS=`[ "name": "codellama/CodeLlama-70b-Instruct-hf", "displayName": "codellama/CodeLlama-70b-Instruct-hf", "description": "Code Llama, a state of the art code model from Meta. Now in 70B!", + "logoUrl": "https://huggingface.co/datasets/huggingchat/models-logo/resolve/main/meta-logo.png", "websiteUrl": "https://ai.meta.com/blog/code-llama-large-language-model-coding/", + "modelUrl": "https://huggingface.co/codellama/CodeLlama-70b-Instruct-hf", "preprompt": "", "chatPromptTemplate" : "{{#if @root.preprompt}}Source: system\n\n {{@root.preprompt}} {{/if}}{{#each messages}}{{#ifUser}}Source: user\n\n {{content}} {{/ifUser}}{{#ifAssistant}}Source: assistant\n\n {{content}} {{/ifAssistant}}{{/each}}Source: assistant\nDestination: user\n\n ", "promptExamples": [ @@ -117,7 +152,9 @@ MODELS=`[ "name": "mistralai/Mistral-7B-Instruct-v0.1", "displayName": "mistralai/Mistral-7B-Instruct-v0.1", "description": "Mistral 7B is a new Apache 2.0 model, released by Mistral AI that outperforms Llama2 13B in benchmarks.", + "logoUrl": "https://huggingface.co/datasets/huggingchat/models-logo/resolve/main/mistral-logo.png", "websiteUrl": "https://mistral.ai/news/announcing-mistral-7b/", + "modelUrl": "https://huggingface.co/mistralai/Mistral-7B-Instruct-v0.1", "preprompt": "", "chatPromptTemplate" : "{{#each messages}}{{#ifUser}}[INST] {{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}}{{content}} [/INST]{{/ifUser}}{{#ifAssistant}}{{content}}{{/ifAssistant}}{{/each}}", "parameters": { @@ -147,7 +184,9 @@ MODELS=`[ "name": "mistralai/Mistral-7B-Instruct-v0.2", "displayName": "mistralai/Mistral-7B-Instruct-v0.2", "description": "Mistral 7B is a new Apache 2.0 model, released by Mistral AI that outperforms Llama2 13B in benchmarks.", + "logoUrl": "https://huggingface.co/datasets/huggingchat/models-logo/resolve/main/mistral-logo.png", "websiteUrl": "https://mistral.ai/news/announcing-mistral-7b/", + "modelUrl": "https://huggingface.co/mistralai/Mistral-7B-Instruct-v0.2", "preprompt": "", "chatPromptTemplate" : "{{#each messages}}{{#ifUser}}[INST] {{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}}{{content}} [/INST]{{/ifUser}}{{#ifAssistant}}{{content}}{{/ifAssistant}}{{/each}}", "parameters": { @@ -176,7 +215,9 @@ MODELS=`[ "name": "openchat/openchat-3.5-0106", "displayName": "openchat/openchat-3.5-0106", "description": "OpenChat 3.5 is the #1 model on MT-Bench, with only 7B parameters.", + "logoUrl": "https://huggingface.co/datasets/huggingchat/models-logo/resolve/main/openchat-logo.png", "websiteUrl": "https://huggingface.co/openchat/openchat-3.5-0106", + "modelUrl": "https://huggingface.co/openchat/openchat-3.5-0106", "preprompt": "", "chatPromptTemplate" : "{{#each messages}}{{#ifUser}}GPT4 Correct User: {{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}}{{content}}<|end_of_turn|>GPT4 Correct Assistant:{{/ifUser}}{{#ifAssistant}}{{content}}<|end_of_turn|>{{/ifAssistant}}{{/each}}", "parameters": { diff --git a/.github/workflows/deploy-release.yml b/.github/workflows/deploy-release.yml index d6254130a3e..2c3553fa4c5 100644 --- a/.github/workflows/deploy-release.yml +++ b/.github/workflows/deploy-release.yml @@ -26,6 +26,7 @@ jobs: MONGODB_URL: ${{ secrets.MONGODB_URL }} HF_DEPLOYMENT_TOKEN: ${{ secrets.HF_DEPLOYMENT_TOKEN }} WEBHOOK_URL_REPORT_ASSISTANT: ${{ secrets.WEBHOOK_URL_REPORT_ASSISTANT }} + ADMIN_API_SECRET: ${{ secrets.ADMIN_API_SECRET }} run: npm run updateProdEnv sync-to-hub: runs-on: ubuntu-latest diff --git a/PROMPTS.md b/PROMPTS.md index 4f921a6d5e9..1847e0dcaa3 100644 --- a/PROMPTS.md +++ b/PROMPTS.md @@ -61,3 +61,9 @@ System: {{preprompt}}\nUser:{{#each messages}}{{#ifUser}}{{content}}\nFalcon:{{/ ```env {{#if @root.preprompt}}Source: system\n\n {{@root.preprompt}} {{/if}}{{#each messages}}{{#ifUser}}Source: user\n\n {{content}} {{/ifUser}}{{#ifAssistant}}Source: assistant\n\n {{content}} {{/ifAssistant}}{{/each}}Source: assistant\nDestination: user\n\n `` ``` + +## Gemma + +```env +{{#each messages}}{{#ifUser}}user\n{{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}}{{content}}\nmodel\n{{/ifUser}}{{#ifAssistant}}{{content}}\n{{/ifAssistant}}{{/each}} +``` diff --git a/README.md b/README.md index 99456a5ddad..5a79c95648e 100644 --- a/README.md +++ b/README.md @@ -616,3 +616,37 @@ npm run updateLocalEnv ``` This will replace your `.env.local` file with the one that will be used in prod (simply taking `.env.template + .env.SECRET_CONFIG`). + +### Populate database + +> [!WARNING] +> The `MONGODB_URL` used for this script will be fetched from `.env.local`. Make sure it's correct! The command runs directly on the database. + +You can populate the database using faker data using the `populate` script: + +```bash +npm run populate +``` + +At least one flag must be specified, the following flags are available: + +- `reset` - resets the database +- `all` - populates all tables +- `users` - populates the users table +- `settings` - populates the settings table for existing users +- `assistants` - populates the assistants table for existing users +- `conversations` - populates the conversations table for existing users + +For example, you could use it like so: + +```bash +npm run populate reset +``` + +to clear out the database. Then login in the app to create your user and run the following command: + +```bash +npm run populate users settings assistants conversations +``` + +to populate the database with fake data, including fake conversations and assistants for your user. diff --git a/package-lock.json b/package-lock.json index 602b4d61eaf..ffdf0259945 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,23 +35,28 @@ "sharp": "^0.33.2", "tailwind-scrollbar": "^3.0.0", "tailwindcss": "^3.4.0", + "uuid": "^9.0.1", "zod": "^3.22.3" }, "devDependencies": { + "@faker-js/faker": "^8.4.1", "@iconify-json/carbon": "^1.1.16", "@iconify-json/eos-icons": "^1.1.6", "@sveltejs/adapter-node": "^1.3.1", - "@sveltejs/kit": "^1.27.6", + "@sveltejs/kit": "^1.30.4", "@tailwindcss/typography": "^0.5.9", "@types/jsdom": "^21.1.1", "@types/marked": "^4.0.8", + "@types/minimist": "^1.2.5", "@types/parquetjs": "^0.10.3", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^6.x", "@typescript-eslint/parser": "^6.x", "eslint": "^8.28.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-svelte": "^2.30.0", "marked-katex-extension": "^3.0.6", + "minimist": "^1.2.8", "prettier": "^2.8.0", "prettier-plugin-svelte": "^2.10.1", "prettier-plugin-tailwindcss": "^0.2.7", @@ -62,6 +67,7 @@ "typescript": "^5.0.0", "unplugin-icons": "^0.16.1", "vite": "^4.5.2", + "vite-node": "^1.3.1", "vitest": "^0.31.0" }, "optionalDependencies": { @@ -146,6 +152,22 @@ "tslib": "^2.4.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", @@ -554,6 +576,22 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@faker-js/faker": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.1.tgz", + "integrity": "sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0", + "npm": ">=6.14.13" + } + }, "node_modules/@fastify/busboy": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz", @@ -1568,6 +1606,175 @@ } } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz", + "integrity": "sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.0.tgz", + "integrity": "sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.0.tgz", + "integrity": "sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.0.tgz", + "integrity": "sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.0.tgz", + "integrity": "sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.0.tgz", + "integrity": "sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.0.tgz", + "integrity": "sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.0.tgz", + "integrity": "sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.0.tgz", + "integrity": "sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.0.tgz", + "integrity": "sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.0.tgz", + "integrity": "sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.0.tgz", + "integrity": "sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.0.tgz", + "integrity": "sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@shuding/opentype.js": { "version": "1.4.0-beta.0", "resolved": "https://registry.npmjs.org/@shuding/opentype.js/-/opentype.js-1.4.0-beta.0.tgz", @@ -1599,9 +1806,9 @@ } }, "node_modules/@sveltejs/kit": { - "version": "1.27.6", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.27.6.tgz", - "integrity": "sha512-GsjTkMbKzXdbeRg0tk8S7HNShQ4879ftRr0ZHaZfjbig1xQwG57Bvcm9U9/mpLJtCapLbLWUnygKrgcLISLC8A==", + "version": "1.30.4", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.30.4.tgz", + "integrity": "sha512-JSQIQT6XvdchCRQEm7BABxPC56WP5RYVONAi+09S8tmzeP43fBsRlr95bFmsTQM2RHBldfgQk+jgdnsKI75daA==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -1617,7 +1824,7 @@ "set-cookie-parser": "^2.6.0", "sirv": "^2.0.2", "tiny-glob": "^0.2.9", - "undici": "~5.26.2" + "undici": "^5.28.3" }, "bin": { "svelte-kit": "svelte-kit.js" @@ -1751,9 +1958,9 @@ "dev": true }, "node_modules/@types/estree": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", - "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@types/jsdom": { @@ -1790,6 +1997,12 @@ "integrity": "sha512-HVNzMT5QlWCOdeuBsgXP8EZzKUf0+AXzN+sLmjvaB3ZlLqO+e4u0uXrdw9ub69wBKFs+c6/pA4r9sy6cCDvImw==", "dev": true }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true + }, "node_modules/@types/node": { "version": "18.13.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", @@ -1847,6 +2060,12 @@ "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", "dev": true }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "node_modules/@types/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -2198,9 +2417,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "devOptional": true, "bin": { "acorn": "bin/acorn" @@ -3726,9 +3945,9 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "optional": true, "os": [ @@ -4093,10 +4312,17 @@ "resolved": "https://registry.npmjs.org/int53/-/int53-0.2.4.tgz", "integrity": "sha512-a5jlKftS7HUOhkUyYD7j2sJ/ZnvWiNlZS1ldR+g1ifQ+/UuZXIE+YTc/lK1qGj/GwAU5F8Z0e1eVq2t1J5Ob2g==" }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } }, "node_modules/is-arrayish": { "version": "0.3.2", @@ -4267,6 +4493,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, "node_modules/jsdom": { "version": "22.0.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.0.0.tgz", @@ -4355,9 +4586,9 @@ } }, "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", "dev": true }, "node_modules/katex": { @@ -4728,15 +4959,15 @@ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "node_modules/mlly": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.2.1.tgz", - "integrity": "sha512-1aMEByaWgBPEbWV2BOPEMySRrzl7rIHXmQxam4DM8jVjalTQDjpN2ZKOLUrwyhfZQO7IXHml2StcHMhooDeEEQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz", + "integrity": "sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==", "dev": true, "dependencies": { - "acorn": "^8.8.2", - "pathe": "^1.1.0", + "acorn": "^8.11.3", + "pathe": "^1.1.2", "pkg-types": "^1.0.3", - "ufo": "^1.1.2" + "ufo": "^1.3.2" } }, "node_modules/mongodb": { @@ -5285,9 +5516,9 @@ } }, "node_modules/pathe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz", - "integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "dev": true }, "node_modules/pathval": { @@ -5377,9 +5608,9 @@ "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "funding": [ { "type": "opencollective", @@ -5395,7 +5626,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -5544,9 +5775,9 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/postcss/node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -6294,15 +6525,15 @@ "integrity": "sha512-YIK6I2lsH072UE0aOFxxY1dPDCS43I5ktqHpeAsuLNYWkE5pGxRGWfDM4/vSUfNzXjC1Ivzt3qx31PCLmc9yqg==" }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.3.tgz", + "integrity": "sha512-vfuYK48HXCTFD03G/1/zkIls3Ebr2YNa4qU9gHDZdblHLiqhJrJGkY3+0Nx0JpN9qBhJbVObc1CNciT1bIZJxw==", "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, @@ -6345,6 +6576,11 @@ "memory-pager": "^1.0.2" } }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -7084,9 +7320,9 @@ } }, "node_modules/ufo": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.1.2.tgz", - "integrity": "sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", + "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==", "dev": true }, "node_modules/uglify-js": { @@ -7107,9 +7343,9 @@ "integrity": "sha512-qh4mBffhlkiXwDAOxvSGxhL0QEQsTbnP9BozOK3OYPEGvPvdWzvAUaXNtUSMdNsKDtuyjEbyVUPFZ52SSLhLqw==" }, "node_modules/undici": { - "version": "5.26.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.26.4.tgz", - "integrity": "sha512-OG+QOf0fTLtazL9P9X7yqWxQ+Z0395Wk6DSkyTxtaq3wQEjIroVe7Y4asCX/vcCxYpNGMnwz8F0qbRYUoaQVMw==", + "version": "5.28.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", + "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -7232,6 +7468,18 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -7299,97 +7547,573 @@ } }, "node_modules/vite-node": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.31.0.tgz", - "integrity": "sha512-8x1x1LNuPvE2vIvkSB7c1mApX5oqlgsxzHQesYF7l5n1gKrEmrClIiZuOFbFDQcjLsmcWSwwmrWrcGWm9Fxc/g==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.3.1.tgz", + "integrity": "sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==", "dev": true, "dependencies": { "cac": "^6.7.14", "debug": "^4.3.4", - "mlly": "^1.2.0", - "pathe": "^1.1.0", + "pathe": "^1.1.1", "picocolors": "^1.0.0", - "vite": "^3.0.0 || ^4.0.0" + "vite": "^5.0.0" }, "bin": { "vite-node": "vite-node.mjs" }, "engines": { - "node": ">=v14.18.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/vitefu": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz", - "integrity": "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==", + "node_modules/vite-node/node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], "dev": true, - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vitest": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.31.0.tgz", - "integrity": "sha512-JwWJS9p3GU9GxkG7eBSmr4Q4x4bvVBSswaCFf1PBNHiPx00obfhHRJfgHcnI0ffn+NMlIh9QGvG75FlaIBdKGA==", + "node_modules/vite-node/node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@types/chai": "^4.3.4", - "@types/chai-subset": "^1.3.3", - "@types/node": "*", - "@vitest/expect": "0.31.0", - "@vitest/runner": "0.31.0", - "@vitest/snapshot": "0.31.0", - "@vitest/spy": "0.31.0", - "@vitest/utils": "0.31.0", - "acorn": "^8.8.2", - "acorn-walk": "^8.2.0", - "cac": "^6.7.14", - "chai": "^4.3.7", - "concordance": "^5.0.4", - "debug": "^4.3.4", - "local-pkg": "^0.4.3", - "magic-string": "^0.30.0", - "pathe": "^1.1.0", - "picocolors": "^1.0.0", - "std-env": "^3.3.2", - "strip-literal": "^1.0.1", - "tinybench": "^2.4.0", - "tinypool": "^0.5.0", - "vite": "^3.0.0 || ^4.0.0", - "vite-node": "0.31.0", - "why-is-node-running": "^2.2.2" - }, - "bin": { - "vitest": "vitest.mjs" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=v14.18.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@vitest/browser": "*", - "@vitest/ui": "*", - "happy-dom": "*", - "jsdom": "*", - "playwright": "*", - "safaridriver": "*", - "webdriverio": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/vite-node/node_modules/rollup": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.0.tgz", + "integrity": "sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.12.0", + "@rollup/rollup-android-arm64": "4.12.0", + "@rollup/rollup-darwin-arm64": "4.12.0", + "@rollup/rollup-darwin-x64": "4.12.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.12.0", + "@rollup/rollup-linux-arm64-gnu": "4.12.0", + "@rollup/rollup-linux-arm64-musl": "4.12.0", + "@rollup/rollup-linux-riscv64-gnu": "4.12.0", + "@rollup/rollup-linux-x64-gnu": "4.12.0", + "@rollup/rollup-linux-x64-musl": "4.12.0", + "@rollup/rollup-win32-arm64-msvc": "4.12.0", + "@rollup/rollup-win32-ia32-msvc": "4.12.0", + "@rollup/rollup-win32-x64-msvc": "4.12.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/vite-node/node_modules/vite": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.4.tgz", + "integrity": "sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==", + "dev": true, + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.35", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitefu": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz", + "integrity": "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==", + "dev": true, + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.31.0.tgz", + "integrity": "sha512-JwWJS9p3GU9GxkG7eBSmr4Q4x4bvVBSswaCFf1PBNHiPx00obfhHRJfgHcnI0ffn+NMlIh9QGvG75FlaIBdKGA==", + "dev": true, + "dependencies": { + "@types/chai": "^4.3.4", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "@vitest/expect": "0.31.0", + "@vitest/runner": "0.31.0", + "@vitest/snapshot": "0.31.0", + "@vitest/spy": "0.31.0", + "@vitest/utils": "0.31.0", + "acorn": "^8.8.2", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", + "chai": "^4.3.7", + "concordance": "^5.0.4", + "debug": "^4.3.4", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.0", + "pathe": "^1.1.0", + "picocolors": "^1.0.0", + "std-env": "^3.3.2", + "strip-literal": "^1.0.1", + "tinybench": "^2.4.0", + "tinypool": "^0.5.0", + "vite": "^3.0.0 || ^4.0.0", + "vite-node": "0.31.0", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@vitest/browser": "*", + "@vitest/ui": "*", + "happy-dom": "*", + "jsdom": "*", + "playwright": "*", + "safaridriver": "*", + "webdriverio": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, "@vitest/browser": { "optional": true }, @@ -7413,6 +8137,29 @@ } } }, + "node_modules/vitest/node_modules/vite-node": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.31.0.tgz", + "integrity": "sha512-8x1x1LNuPvE2vIvkSB7c1mApX5oqlgsxzHQesYF7l5n1gKrEmrClIiZuOFbFDQcjLsmcWSwwmrWrcGWm9Fxc/g==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "mlly": "^1.2.0", + "pathe": "^1.1.0", + "picocolors": "^1.0.0", + "vite": "^3.0.0 || ^4.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", diff --git a/package.json b/package.json index 0c2484b9c1f..b0c6493c471 100644 --- a/package.json +++ b/package.json @@ -13,23 +13,28 @@ "format": "prettier --plugin-search-dir . --write .", "test": "MONGODB_URL=mongodb://127.0.0.1:27017/ vitest", "updateLocalEnv": "node --loader ts-node/esm scripts/updateLocalEnv.ts", - "updateProdEnv": "node --loader ts-node/esm scripts/updateProdEnv.ts" + "updateProdEnv": "node --loader ts-node/esm scripts/updateProdEnv.ts", + "populate": "vite-node --options.transformMode.ssr='/.*/' scripts/populate.ts" }, "devDependencies": { + "@faker-js/faker": "^8.4.1", "@iconify-json/carbon": "^1.1.16", "@iconify-json/eos-icons": "^1.1.6", "@sveltejs/adapter-node": "^1.3.1", - "@sveltejs/kit": "^1.27.6", + "@sveltejs/kit": "^1.30.4", "@tailwindcss/typography": "^0.5.9", "@types/jsdom": "^21.1.1", "@types/marked": "^4.0.8", + "@types/minimist": "^1.2.5", "@types/parquetjs": "^0.10.3", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^6.x", "@typescript-eslint/parser": "^6.x", "eslint": "^8.28.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-svelte": "^2.30.0", "marked-katex-extension": "^3.0.6", + "minimist": "^1.2.8", "prettier": "^2.8.0", "prettier-plugin-svelte": "^2.10.1", "prettier-plugin-tailwindcss": "^0.2.7", @@ -40,6 +45,7 @@ "typescript": "^5.0.0", "unplugin-icons": "^0.16.1", "vite": "^4.5.2", + "vite-node": "^1.3.1", "vitest": "^0.31.0" }, "type": "module", @@ -71,6 +77,7 @@ "sharp": "^0.33.2", "tailwind-scrollbar": "^3.0.0", "tailwindcss": "^3.4.0", + "uuid": "^9.0.1", "zod": "^3.22.3" }, "optionalDependencies": { diff --git a/scripts/populate.ts b/scripts/populate.ts new file mode 100644 index 00000000000..2a3e12a541e --- /dev/null +++ b/scripts/populate.ts @@ -0,0 +1,264 @@ +import readline from "readline"; +import minimist from "minimist"; + +// @ts-expect-error: vite-node makes the var available but the typescript compiler doesn't see them +import { MONGODB_URL } from "$env/static/private"; + +import { faker } from "@faker-js/faker"; +import { ObjectId } from "mongodb"; + +import { collections } from "../src/lib/server/database.ts"; +import { models } from "../src/lib/server/models.ts"; +import type { User } from "../src/lib/types/User"; +import type { Assistant } from "../src/lib/types/Assistant"; +import type { Conversation } from "../src/lib/types/Conversation"; +import type { Settings } from "../src/lib/types/Settings"; +import { defaultEmbeddingModel } from "../src/lib/server/embeddingModels.ts"; +import { Message } from "../src/lib/types/Message.ts"; + +import { addChildren } from "../src/lib/utils/tree/addChildren.ts"; + +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); + +rl.on("close", function () { + process.exit(0); +}); + +const possibleFlags = ["reset", "all", "users", "settings", "assistants", "conversations"]; +const argv = minimist(process.argv.slice(2)); +const flags = argv["_"].filter((flag) => possibleFlags.includes(flag)); + +async function generateMessages(preprompt?: string): Promise { + const isLinear = faker.datatype.boolean(0.5); + const isInterrupted = faker.datatype.boolean(0.05); + + const messages: Message[] = []; + + messages.push({ + id: crypto.randomUUID(), + from: "system", + content: preprompt ?? "", + createdAt: faker.date.recent({ days: 30 }), + updatedAt: faker.date.recent({ days: 30 }), + }); + + let isUser = true; + let lastId = messages[0].id; + if (isLinear) { + const convLength = faker.number.int({ min: 1, max: 25 }) * 2; // must always be even + + for (let i = 0; i < convLength; i++) { + lastId = addChildren( + { + messages, + rootMessageId: messages[0].id, + }, + { + from: isUser ? "user" : "assistant", + content: faker.lorem.sentence({ + min: 10, + max: isUser ? 50 : 200, + }), + createdAt: faker.date.recent({ days: 30 }), + updatedAt: faker.date.recent({ days: 30 }), + interrupted: i === convLength - 1 && isInterrupted, + }, + lastId + ); + isUser = !isUser; + } + } else { + const convLength = faker.number.int({ min: 2, max: 200 }); + + for (let i = 0; i < convLength; i++) { + addChildren( + { + messages, + rootMessageId: messages[0].id, + }, + { + from: isUser ? "user" : "assistant", + content: faker.lorem.sentence({ + min: 10, + max: isUser ? 50 : 200, + }), + createdAt: faker.date.recent({ days: 30 }), + updatedAt: faker.date.recent({ days: 30 }), + interrupted: i === convLength - 1 && isInterrupted, + }, + faker.helpers.arrayElement([ + messages[0].id, + ...messages.filter((m) => m.from === (isUser ? "assistant" : "user")).map((m) => m.id), + ]) + ); + + isUser = !isUser; + } + } + return messages; +} + +async function seed() { + console.log("Seeding..."); + const modelIds = models.map((model) => model.id); + + if (flags.includes("reset")) { + console.log("Starting reset of DB"); + await collections.users.deleteMany({}); + await collections.settings.deleteMany({}); + await collections.assistants.deleteMany({}); + await collections.conversations.deleteMany({}); + console.log("Reset done"); + } + + if (flags.includes("users") || flags.includes("all")) { + console.log("Creating 100 new users"); + const newUsers: User[] = Array.from({ length: 100 }, () => ({ + _id: new ObjectId(), + createdAt: faker.date.recent({ days: 30 }), + updatedAt: faker.date.recent({ days: 30 }), + username: faker.internet.userName(), + name: faker.person.fullName(), + hfUserId: faker.string.alphanumeric(24), + avatarUrl: faker.image.avatar(), + })); + + await collections.users.insertMany(newUsers); + console.log("Done creating users."); + } + + const users = await collections.users.find().toArray(); + if (flags.includes("settings") || flags.includes("all")) { + console.log("Updating settings for all users"); + users.forEach(async (user) => { + const settings: Settings = { + userId: user._id, + shareConversationsWithModelAuthors: faker.datatype.boolean(0.25), + hideEmojiOnSidebar: faker.datatype.boolean(0.25), + ethicsModalAcceptedAt: faker.date.recent({ days: 30 }), + activeModel: faker.helpers.arrayElement(modelIds), + createdAt: faker.date.recent({ days: 30 }), + updatedAt: faker.date.recent({ days: 30 }), + customPrompts: {}, + assistants: [], + }; + await collections.settings.updateOne( + { userId: user._id }, + { $set: { ...settings } }, + { upsert: true } + ); + }); + console.log("Done updating settings."); + } + + if (flags.includes("assistants") || flags.includes("all")) { + console.log("Creating assistants for all users"); + await Promise.all( + users.map(async (user) => { + const assistants = faker.helpers.multiple( + () => ({ + _id: new ObjectId(), + name: faker.animal.insect(), + createdById: user._id, + createdByName: user.username, + createdAt: faker.date.recent({ days: 30 }), + updatedAt: faker.date.recent({ days: 30 }), + userCount: faker.number.int({ min: 1, max: 100000 }), + featured: faker.datatype.boolean(0.25), + modelId: faker.helpers.arrayElement(modelIds), + description: faker.lorem.sentence(), + preprompt: faker.hacker.phrase(), + exampleInputs: faker.helpers.multiple(() => faker.lorem.sentence(), { + count: faker.number.int({ min: 0, max: 4 }), + }), + }), + { count: faker.number.int({ min: 3, max: 10 }) } + ); + await collections.assistants.insertMany(assistants); + await collections.settings.updateOne( + { userId: user._id }, + { $set: { assistants: assistants.map((a) => a._id.toString()) } }, + { upsert: true } + ); + }) + ); + console.log("Done creating assistants."); + } + + if (flags.includes("conversations") || flags.includes("all")) { + console.log("Creating conversations for all users"); + await Promise.all( + users.map(async (user) => { + const conversations = faker.helpers.multiple( + async () => { + const settings = await collections.settings.findOne({ userId: user._id }); + + const assistantId = + settings?.assistants && settings.assistants.length > 0 && faker.datatype.boolean(0.1) + ? faker.helpers.arrayElement(settings.assistants) + : undefined; + + const preprompt = + (assistantId + ? await collections.assistants + .findOne({ _id: assistantId }) + .then((assistant: Assistant) => assistant?.preprompt ?? "") + : faker.helpers.maybe(() => faker.hacker.phrase(), { probability: 0.5 })) ?? ""; + + const messages = await generateMessages(preprompt); + + const conv = { + _id: new ObjectId(), + userId: user._id, + assistantId, + preprompt, + createdAt: faker.date.recent({ days: 145 }), + updatedAt: faker.date.recent({ days: 145 }), + model: faker.helpers.arrayElement(modelIds), + title: faker.internet.emoji() + " " + faker.hacker.phrase(), + embeddingModel: defaultEmbeddingModel.id, + messages, + rootMessageId: messages[0].id, + } satisfies Conversation; + + return conv; + }, + { count: faker.number.int({ min: 10, max: 200 }) } + ); + + await collections.conversations.insertMany(await Promise.all(conversations)); + }) + ); + console.log("Done creating conversations."); + } +} + +// run seed +(async () => { + try { + rl.question( + "You're about to run a seeding script on the following MONGODB_URL: \x1b[31m" + + MONGODB_URL + + "\x1b[0m\n\n With the following flags: \x1b[31m" + + flags.join("\x1b[0m , \x1b[31m") + + "\x1b[0m\n \n\n Are you sure you want to continue? (yes/no): ", + async (confirm) => { + if (confirm !== "yes") { + console.log("Not 'yes', exiting."); + rl.close(); + process.exit(0); + } + console.log("Starting seeding..."); + await seed(); + console.log("Seeding done."); + rl.close(); + } + ); + } catch (e) { + console.error(e); + process.exit(1); + } +})(); diff --git a/scripts/updateProdEnv.ts b/scripts/updateProdEnv.ts index 2512b79bcbf..ab1f0d0bc39 100644 --- a/scripts/updateProdEnv.ts +++ b/scripts/updateProdEnv.ts @@ -7,6 +7,7 @@ const OPENID_CONFIG = process.env.OPENID_CONFIG; const MONGODB_URL = process.env.MONGODB_URL; const HF_TOKEN = process.env.HF_TOKEN ?? process.env.HF_ACCESS_TOKEN; // token used for API requests in prod const WEBHOOK_URL_REPORT_ASSISTANT = process.env.WEBHOOK_URL_REPORT_ASSISTANT; // slack webhook url used to get "report assistant" events +const ADMIN_API_SECRET = process.env.ADMIN_API_SECRET; // Read the content of the file .env.template const PUBLIC_CONFIG = fs.readFileSync(".env.template", "utf8"); @@ -18,6 +19,7 @@ OPENID_CONFIG=${OPENID_CONFIG} SERPER_API_KEY=${SERPER_API_KEY} HF_TOKEN=${HF_TOKEN} WEBHOOK_URL_REPORT_ASSISTANT=${WEBHOOK_URL_REPORT_ASSISTANT} +ADMIN_API_SECRET=${ADMIN_API_SECRET} `; // Make an HTTP POST request to add the space secrets diff --git a/src/hooks.server.ts b/src/hooks.server.ts index ef1202b23eb..783479cc3a8 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,4 +1,10 @@ -import { COOKIE_NAME, EXPOSE_API, MESSAGES_BEFORE_LOGIN } from "$env/static/private"; +import { + ADMIN_API_SECRET, + COOKIE_NAME, + EXPOSE_API, + MESSAGES_BEFORE_LOGIN, + PARQUET_EXPORT_SECRET, +} from "$env/static/private"; import type { Handle } from "@sveltejs/kit"; import { PUBLIC_GOOGLE_ANALYTICS_ID, @@ -11,6 +17,12 @@ import { findUser, refreshSessionCookie, requiresUser } from "$lib/server/auth"; import { ERROR_MESSAGES } from "$lib/stores/errors"; import { sha256 } from "$lib/utils/sha256"; import { addWeeks } from "date-fns"; +import { checkAndRunMigrations } from "$lib/migrations/migrations"; +import { building } from "$app/environment"; + +if (!building) { + await checkAndRunMigrations(); +} export const handle: Handle = async ({ event, resolve }) => { if (event.url.pathname.startsWith(`${base}/api/`) && EXPOSE_API !== "true") { @@ -29,6 +41,18 @@ export const handle: Handle = async ({ event, resolve }) => { }); } + if (event.url.pathname.startsWith(`${base}/admin/`) || event.url.pathname === `${base}/admin`) { + const ADMIN_SECRET = ADMIN_API_SECRET || PARQUET_EXPORT_SECRET; + + if (!ADMIN_SECRET) { + return errorResponse(500, "Admin API is not configured"); + } + + if (event.request.headers.get("Authorization") !== `Bearer ${ADMIN_SECRET}`) { + return errorResponse(401, "Unauthorized"); + } + } + const token = event.cookies.get(COOKIE_NAME); let secretSessionId: string; diff --git a/src/lib/components/ExpandNavigation.svelte b/src/lib/components/ExpandNavigation.svelte new file mode 100644 index 00000000000..cda0207c576 --- /dev/null +++ b/src/lib/components/ExpandNavigation.svelte @@ -0,0 +1,14 @@ + + + diff --git a/src/lib/components/MobileNav.svelte b/src/lib/components/MobileNav.svelte index 5c2bfac28f7..f400c06fd1b 100644 --- a/src/lib/components/MobileNav.svelte +++ b/src/lib/components/MobileNav.svelte @@ -12,7 +12,7 @@ export let isOpen = false; export let title: string | undefined; - $: title = title || "New Chat"; + $: title = title ?? "New Chat"; let closeEl: HTMLButtonElement; let openEl: HTMLButtonElement; diff --git a/src/lib/components/NavMenu.svelte b/src/lib/components/NavMenu.svelte index 4ebea55c2b1..52b69f72495 100644 --- a/src/lib/components/NavMenu.svelte +++ b/src/lib/components/NavMenu.svelte @@ -8,6 +8,7 @@ import NavConversationItem from "./NavConversationItem.svelte"; import type { LayoutData } from "../../routes/$types"; import type { ConvSidebar } from "$lib/types/ConvSidebar"; + import type { Model } from "$lib/types/Model"; import { page } from "$app/stores"; export let conversations: ConvSidebar[] = []; @@ -41,6 +42,8 @@ month: "This month", older: "Older", } as const; + + const nModels: number = $page.data.models.filter((el: Model) => !el.unlisted).length; - {#if isAuthor && !loading && message.content} + {#if !loading && message.content}
- - + + ? 'text-red-500 hover:text-red-500 dark:text-red-400 hover:dark:text-red-400' + : ''}" + title={message.score === -1 ? "Remove -1" : "-1"} + type="button" + on:click={() => + dispatch("vote", { score: message.score === -1 ? 0 : -1, id: message.id })} + > + + + {/if} + +
{#if data.assistant.avatar} { const modelId = url.searchParams.get("modelId"); const pageIndex = parseInt(url.searchParams.get("p") ?? "0"); const username = url.searchParams.get("user"); + const query = url.searchParams.get("q")?.trim() ?? null; const createdByCurrentUser = locals.user?.username && locals.user.username === username; let user: Pick | null = null; @@ -34,6 +36,7 @@ export const load = async ({ url, locals }) => { ...(modelId && { modelId }), ...(!createdByCurrentUser && { userCount: { $gt: 1 } }), ...(user ? { createdById: user._id } : { featured: true }), + ...(query && { searchTokens: { $all: generateQueryTokens(query) } }), }; const assistants = await collections.assistants .find(filter) @@ -49,5 +52,6 @@ export const load = async ({ url, locals }) => { selectedModel: modelId ?? "", numTotalItems, numItemsPerPage: NUM_PER_PAGE, + query, }; }; diff --git a/src/routes/assistants/+page.svelte b/src/routes/assistants/+page.svelte index c58ac9d675d..aeab29ddf67 100644 --- a/src/routes/assistants/+page.svelte +++ b/src/routes/assistants/+page.svelte @@ -4,6 +4,7 @@ import { PUBLIC_APP_ASSETS, PUBLIC_ORIGIN } from "$env/static/public"; import { isHuggingChat } from "$lib/utils/isHuggingChat"; + import { tick } from "svelte"; import { goto } from "$app/navigation"; import { base } from "$app/paths"; import { page } from "$app/stores"; @@ -14,15 +15,22 @@ import CarbonArrowUpRight from "~icons/carbon/arrow-up-right"; import CarbonEarthAmerica from "~icons/carbon/earth-americas-filled"; import CarbonUserMultiple from "~icons/carbon/user-multiple"; + import CarbonSearch from "~icons/carbon/search"; import Pagination from "$lib/components/Pagination.svelte"; import { formatUserCount } from "$lib/utils/formatUserCount"; import { getHref } from "$lib/utils/getHref"; + import { debounce } from "$lib/utils/debounce"; + import { useSettingsStore } from "$lib/stores/settings"; export let data: PageData; $: assistantsCreator = $page.url.searchParams.get("user"); $: createdByMe = data.user?.username && data.user.username === assistantsCreator; + const SEARCH_DEBOUNCE_DELAY = 400; + let filterInputEl: HTMLInputElement; + let searchDisabled = false; + const onModelChange = (e: Event) => { const newUrl = getHref($page.url, { newKeys: { modelId: (e.target as HTMLSelectElement).value }, @@ -30,6 +38,23 @@ }); goto(newUrl); }; + + const filterOnName = debounce(async (e: Event) => { + searchDisabled = true; + const value = (e.target as HTMLInputElement).value; + const newUrl = getHref($page.url, { + newKeys: { q: value }, + existingKeys: { behaviour: "delete", keys: ["p"] }, + }); + await goto(newUrl); + setTimeout(async () => { + searchDisabled = false; + await tick(); + filterInputEl.focus(); + }, 0); + }, SEARCH_DEBOUNCE_DELAY); + + const settings = useSettingsStore(); @@ -50,7 +75,7 @@ {/if} -
+
{#each data.assistants as assistant (assistant._id)} - { + if (data.settings.assistants.includes(assistant._id.toString())) { + settings.instantSet({ activeModel: assistant._id.toString() }); + goto(`${base}` || "/"); + } else { + goto(`${base}/assistant/${assistant._id}`); + } + }} > {#if assistant.userCount && assistant.userCount > 1}

{/if} -
+ {:else} No assistants found {/each} diff --git a/src/routes/conversation/+server.ts b/src/routes/conversation/+server.ts index e7f4c8a7e24..df3787b25d2 100644 --- a/src/routes/conversation/+server.ts +++ b/src/routes/conversation/+server.ts @@ -7,6 +7,7 @@ import { z } from "zod"; import type { Message } from "$lib/types/Message"; import { models, validateModel } from "$lib/server/models"; import { defaultEmbeddingModel } from "$lib/server/embeddingModels"; +import { v4 } from "uuid"; export const POST: RequestHandler = async ({ locals, request }) => { const body = await request.text(); @@ -24,7 +25,7 @@ export const POST: RequestHandler = async ({ locals, request }) => { let messages: Message[] = [ { - id: crypto.randomUUID(), + id: v4(), from: "system", content: values.preprompt ?? "", createdAt: new Date(), diff --git a/src/routes/conversation/[id]/+page.svelte b/src/routes/conversation/[id]/+page.svelte index b19001ed165..97b730ebf04 100644 --- a/src/routes/conversation/[id]/+page.svelte +++ b/src/routes/conversation/[id]/+page.svelte @@ -4,10 +4,9 @@ import { isAborted } from "$lib/stores/isAborted"; import { onMount } from "svelte"; import { page } from "$app/stores"; - import { goto, invalidate } from "$app/navigation"; + import { goto, invalidateAll } from "$app/navigation"; import { base } from "$app/paths"; import { shareConversation } from "$lib/shareConversation"; - import { UrlDependency } from "$lib/types/UrlDependency"; import { ERROR_MESSAGES, error } from "$lib/stores/errors"; import { findCurrentModel } from "$lib/utils/models"; import { webSearchParameters } from "$lib/stores/webSearchParameters"; @@ -18,17 +17,11 @@ import { addChildren } from "$lib/utils/tree/addChildren"; import { addSibling } from "$lib/utils/tree/addSibling"; import { createConvTreeStore } from "$lib/stores/convTree"; + import type { v4 } from "uuid"; export let data; - let messages = data.messages; - let lastLoadedMessages = data.messages; - - // Since we modify the messages array locally, we don't want to reset it if an old version is passed - $: if (data.messages !== lastLoadedMessages) { - messages = data.messages; - lastLoadedMessages = data.messages; - } + $: ({ messages } = data); let loading = false; let pending = false; @@ -72,7 +65,7 @@ isContinue = false, }: { prompt?: string; - messageId?: ReturnType; + messageId?: ReturnType; isRetry?: boolean; isContinue?: boolean; }): Promise { @@ -231,9 +224,16 @@ // this is a bit ugly // we read the stream until we get the final answer + + let readerClosed = false; + + reader.closed.then(() => { + readerClosed = true; + }); + while (finalAnswer === "") { // check for abort - if ($isAborted) { + if ($isAborted || $error || readerClosed) { reader?.cancel(); break; } @@ -243,7 +243,6 @@ // we read, if it's done we cancel if (done) { reader.cancel(); - return; } if (!value) { @@ -264,10 +263,8 @@ if (update.type === "finalAnswer") { finalAnswer = update.text; - reader.cancel(); loading = false; pending = false; - invalidate(UrlDependency.Conversation); } else if (update.type === "stream") { pending = false; messageToWriteTo.content += update.token; @@ -306,7 +303,6 @@ } messageToWriteTo.updates = messageUpdates; - await invalidate(UrlDependency.ConversationList); } catch (err) { if (err instanceof Error && err.message.includes("overloaded")) { $error = "Too much traffic, please try again."; @@ -321,7 +317,7 @@ } finally { loading = false; pending = false; - await invalidate(UrlDependency.Conversation); + await invalidateAll(); } } diff --git a/src/routes/conversation/[id]/+server.ts b/src/routes/conversation/[id]/+server.ts index ed7c2ec2969..7aeda860c8a 100644 --- a/src/routes/conversation/[id]/+server.ts +++ b/src/routes/conversation/[id]/+server.ts @@ -72,18 +72,17 @@ export async function POST({ request, locals, params, getClientAddress }) { ip: getClientAddress(), }); + const messagesBeforeLogin = MESSAGES_BEFORE_LOGIN ? parseInt(MESSAGES_BEFORE_LOGIN) : 0; + // guest mode check - if ( - !locals.user?._id && - requiresUser && - (MESSAGES_BEFORE_LOGIN ? parseInt(MESSAGES_BEFORE_LOGIN) : 0) > 0 - ) { + if (!locals.user?._id && requiresUser && messagesBeforeLogin) { const totalMessages = ( await collections.conversations .aggregate([ - { $match: authCondition(locals) }, + { $match: { ...authCondition(locals), "messages.from": "assistant" } }, { $project: { messages: 1 } }, + { $limit: messagesBeforeLogin + 1 }, { $unwind: "$messages" }, { $match: { "messages.from": "assistant" } }, { $count: "messages" }, @@ -91,7 +90,7 @@ export async function POST({ request, locals, params, getClientAddress }) { .toArray() )[0]?.messages ?? 0; - if (totalMessages > parseInt(MESSAGES_BEFORE_LOGIN)) { + if (totalMessages > messagesBeforeLogin) { throw error(429, "Exceeded number of messages before login"); } } @@ -325,6 +324,7 @@ export async function POST({ request, locals, params, getClientAddress }) { // inject websearch result & optionally images into the messages const processedMessages = await preprocessMessages( messagesForPrompt, + messageToWriteTo.webSearch, model.multimodal, convId ); @@ -377,6 +377,15 @@ export async function POST({ request, locals, params, getClientAddress }) { } } catch (e) { update({ type: "status", status: "error", message: (e as Error).message }); + } finally { + // check if no output was generated + if (messageToWriteTo.content === previousText) { + update({ + type: "status", + status: "error", + message: "No output was generated. Something went wrong.", + }); + } } await collections.conversations.updateOne( diff --git a/src/routes/login/callback/updateUser.ts b/src/routes/login/callback/updateUser.ts index 94062d4aa69..f2fac350531 100644 --- a/src/routes/login/callback/updateUser.ts +++ b/src/routes/login/callback/updateUser.ts @@ -18,6 +18,12 @@ export async function updateUser(params: { }) { const { userData, locals, cookies, userAgent, ip } = params; + // Microsoft Entra v1 tokens do not provide preferred_username, instead the username is provided in the upn + // claim. See https://learn.microsoft.com/en-us/entra/identity-platform/access-token-claims-reference + if (!userData.preferred_username && userData.upn) { + userData.preferred_username = userData.upn as string; + } + const { preferred_username: username, name, @@ -28,7 +34,7 @@ export async function updateUser(params: { .object({ preferred_username: z.string().optional(), name: z.string(), - picture: z.string(), + picture: z.string().optional(), sub: z.string(), email: z.string().email().optional(), }) diff --git a/src/routes/models/+page.svelte b/src/routes/models/+page.svelte new file mode 100644 index 00000000000..6c92f19b973 --- /dev/null +++ b/src/routes/models/+page.svelte @@ -0,0 +1,72 @@ + + + + {#if isHuggingChat} + HuggingChat - Models + + + + + {/if} + + +
+
+
+

Models

+ {#if isHuggingChat} + + + + {/if} +
+

All models available on {PUBLIC_APP_NAME}

+
+ {#each data.models.filter((el) => !el.unlisted) as model, index (model.id)} + +
+
+
diff --git a/src/routes/settings/+layout.server.ts b/src/routes/settings/+layout.server.ts index 63daa415ad8..140b1a7e149 100644 --- a/src/routes/settings/+layout.server.ts +++ b/src/routes/settings/+layout.server.ts @@ -1,17 +1,9 @@ import { collections } from "$lib/server/database"; -import { ObjectId } from "mongodb"; import type { LayoutServerLoad } from "./$types"; import type { Report } from "$lib/types/Report"; export const load = (async ({ locals, parent }) => { - const { settings } = await parent(); - - // find assistants matching the settings assistants - const assistants = await collections.assistants - .find({ - _id: { $in: settings.assistants.map((el) => new ObjectId(el)) }, - }) - .toArray(); + const { assistants } = await parent(); let reportsByUser: string[] = []; const createdBy = locals.user?._id ?? locals.sessionId; @@ -25,10 +17,7 @@ export const load = (async ({ locals, parent }) => { return { assistants: assistants.map((el) => ({ ...el, - _id: el._id.toString(), - createdById: undefined, - createdByMe: el.createdById.toString() === (locals.user?._id ?? locals.sessionId).toString(), - reported: reportsByUser.includes(el._id.toString()), + reported: reportsByUser.includes(el._id), })), }; }) satisfies LayoutServerLoad; diff --git a/src/routes/settings/+layout.svelte b/src/routes/settings/+layout.svelte index 05b5c87fac1..48b8850e9bd 100644 --- a/src/routes/settings/+layout.svelte +++ b/src/routes/settings/+layout.svelte @@ -34,7 +34,7 @@
{ goto(previousPage); }} - class="xl: z-10 grid h-[95dvh] w-[90dvw] grid-cols-1 content-start gap-x-8 overflow-hidden rounded-2xl bg-white p-4 shadow-2xl outline-none sm:h-[80dvh] md:grid-cols-3 md:grid-rows-[auto,1fr] md:p-8 xl:w-[1200px] 2xl:h-[70dvh]" + class="grid h-[95dvh] w-[90dvw] grid-cols-1 content-start gap-x-8 overflow-hidden rounded-2xl bg-white p-4 shadow-2xl outline-none sm:h-[80dvh] md:grid-cols-3 md:grid-rows-[auto,1fr] md:p-8 xl:w-[1200px] 2xl:h-[70dvh]" >

Settings

diff --git a/src/routes/settings/assistants/[assistantId]/edit/+page.server.ts b/src/routes/settings/assistants/[assistantId]/edit/+page.server.ts index 9310324ab6d..83f8cc7f24f 100644 --- a/src/routes/settings/assistants/[assistantId]/edit/+page.server.ts +++ b/src/routes/settings/assistants/[assistantId]/edit/+page.server.ts @@ -8,6 +8,7 @@ import { z } from "zod"; import { sha256 } from "$lib/utils/sha256"; import sharp from "sharp"; +import { generateSearchTokens } from "$lib/utils/searchTokens"; const newAsssistantSchema = z.object({ name: z.string().min(1), @@ -130,6 +131,7 @@ export const actions: Actions = { exampleInputs, avatar: deleteAvatar ? undefined : hash ?? assistant.avatar, updatedAt: new Date(), + searchTokens: generateSearchTokens(parse.data.name), }, } ); diff --git a/src/routes/settings/assistants/new/+page.server.ts b/src/routes/settings/assistants/new/+page.server.ts index f58adabd91f..678c52457cc 100644 --- a/src/routes/settings/assistants/new/+page.server.ts +++ b/src/routes/settings/assistants/new/+page.server.ts @@ -7,6 +7,7 @@ import { ObjectId } from "mongodb"; import { z } from "zod"; import { sha256 } from "$lib/utils/sha256"; import sharp from "sharp"; +import { generateSearchTokens } from "$lib/utils/searchTokens"; const newAsssistantSchema = z.object({ name: z.string().min(1), @@ -99,6 +100,7 @@ export const actions: Actions = { updatedAt: new Date(), userCount: 1, featured: false, + searchTokens: generateSearchTokens(parse.data.name), }); // add insertedId to user settings diff --git a/vite.config.ts b/vite.config.ts index 54405234b72..0ffbd0482e3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -26,6 +26,6 @@ export default defineConfig({ loadTTFAsArrayBuffer(), ], optimizeDeps: { - include: ["browser-image-resizer"], + include: ["browser-image-resizer", "uuid"], }, });