diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index dc5be29..f5316be 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -16,8 +16,9 @@ body: multiple: true options: - "Library (gpt-turbo)" - - "CLI (gpt-turbo-cli)" + - "Stats Plugin (gpt-turbo-plugin-stats)" - "Web (gpt-turbo-web)" + - "CLI (gpt-turbo-cli)" - "Nest (gpt-turbo-nest)" - "Discord (gpt-turbo-discord)" validations: diff --git a/.github/ISSUE_TEMPLATE/docs_report.yml b/.github/ISSUE_TEMPLATE/docs_report.yml index 950224a..1c82b67 100644 --- a/.github/ISSUE_TEMPLATE/docs_report.yml +++ b/.github/ISSUE_TEMPLATE/docs_report.yml @@ -16,8 +16,9 @@ body: options: - "Monorepo" - "Library (gpt-turbo)" - - "CLI (gpt-turbo-cli)" + - "Stats Plugin (gpt-turbo-plugin-stats)" - "Web (gpt-turbo-web)" + - "CLI (gpt-turbo-cli)" - "Nest (gpt-turbo-nest)" - "Discord (gpt-turbo-discord)" validations: diff --git a/.github/ISSUE_TEMPLATE/feat_request.yml b/.github/ISSUE_TEMPLATE/feat_request.yml index 2ec3c1c..4e247ed 100644 --- a/.github/ISSUE_TEMPLATE/feat_request.yml +++ b/.github/ISSUE_TEMPLATE/feat_request.yml @@ -15,8 +15,9 @@ body: multiple: true options: - "Library (gpt-turbo)" - - "CLI (gpt-turbo-cli)" + - "Stats Plugin (gpt-turbo-plugin-stats)" - "Web (gpt-turbo-web)" + - "CLI (gpt-turbo-cli)" - "Nest (gpt-turbo-nest)" - "Discord (gpt-turbo-discord)" - type: dropdown diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a38516c..d2c61ce 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,6 +9,8 @@ Issue: # - [ ] Library +- Plugins + - [ ] gpt-turbo-plugin-stats - Implementations - [ ] CLI - [ ] Web diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b84e7e9..10a27be 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -168,8 +168,9 @@ Overall, try to keep consistency with the existing codebase, even if it's not ho There are no strict rules for commit messages as all PRs will be squashed into a single commit by a maintainer when merging. However, we try to follow the following convention, which you can use (or not) in your contribution to help reviewers when reviewing your PRs. - `[library]`: for changes to the library or its documentation. -- `[cli]`: for changes to the CLI implementation or its documentation. +- `[stats]`: for changes to the `gpt-turbo-plugin-stats` plugin or its documentation. - `[web]`: for changes to the Web implementation or its documentation. +- `[cli]`: for changes to the CLI implementation or its documentation. - `[nest]`: for changes to the Nest implementation or its documentation. - `[discord]`: for changes to the Discord implementation or its documentation. - `[docs]`: for changes to the documentation **not related to the library or one of its implementations**. (e.g. changes to the root README.md file or this contributing guide). These are usually markdown files. diff --git a/README.md b/README.md index 322e91b..66d1b27 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,17 @@ GPT Turbo [![npm i gpt-turbo](https://img.shields.io/npm/v/gpt-turbo?color=brightgreen&label=gpt-turbo&logo=npm)](https://www.npmjs.com/package/gpt-turbo) + + Implementations using GPT Turbo + [![npm i -g gpt-turbo-cli](https://img.shields.io/npm/v/gpt-turbo-cli?color=brightgreen&label=gpt-turbo-cli&logo=windowsterminal&logoColor=white)](https://www.npmjs.com/package/gpt-turbo-cli) - [![https://gpt-turbo-web.chintristan.io/](https://img.shields.io/github/package-json/v/maxijonson/gpt-turbo?color=brightgreen&filename=packages%2Fweb%2Fpackage.json&label=gpt-turbo-web&logo=react)](https://gpt-turbo-web.chintristan.io/) - [![GPT Turbo - Nest](https://img.shields.io/github/package-json/v/maxijonson/gpt-turbo?color=brightgreen&filename=packages%2Fnest%2Fpackage.json&label=gpt-turbo-nest&logo=nestjs)](https://github.com/maxijonson/gpt-turbo/tree/develop/packages/nest) - [![GPT Turbo - Discord](https://img.shields.io/github/package-json/v/maxijonson/gpt-turbo?color=brightgreen&filename=packages%2Fdiscord%2Fpackage.json&label=gpt-turbo-discord&logo=discord)](https://discord.gg/Aa77KCmwRx) + [![https://gpt-turbo-web.chintristan.io/](https://img.shields.io/github/package-json/v/maxijonson/gpt-turbo?color=brightgreen&filename=packages/implementations/web/package.json&label=gpt-turbo-web&logo=react)](https://gpt-turbo-web.chintristan.io/) + [![GPT Turbo - Nest](https://img.shields.io/github/package-json/v/maxijonson/gpt-turbo?color=brightgreen&filename=packages/implementations/nest/package.json&label=gpt-turbo-nest&logo=nestjs)](https://github.com/maxijonson/gpt-turbo/tree/develop/packages/implementations/nest) + [![GPT Turbo - Discord](https://img.shields.io/github/package-json/v/maxijonson/gpt-turbo?color=brightgreen&filename=packages/implementations/discord/package.json&label=gpt-turbo-discord&logo=discord)](https://discord.gg/Aa77KCmwRx) + + Plugins for GPT Turbo + + [![npm i gpt-turbo-plugin-stats](https://img.shields.io/npm/v/gpt-turbo-plugin-stats?color=brightgreen&label=gpt-turbo-plugin-stats&logo=npm)](https://www.npmjs.com/package/gpt-turbo-plugin-stats) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) @@ -14,7 +21,7 @@ > Are you a dev looking for the library? [Click here](./packages/lib/)! -GPT Turbo is a JavaScript library for seamless integration with OpenAI's Chat Completion API. It ensures smooth conversation continuity and message history tracking, perfect for creating conversational AI applications. +GPT Turbo is a JavaScript library for seamless integration with OpenAI's Chat Completion API. It allows you to manage conversation history for smooth conversation continuity, fine-tune chat completion parameters and define callable functions. The library also supports plugins for extending its functionality beyond the core features. ## Features @@ -30,10 +37,12 @@ GPT Turbo is a JavaScript library for seamless integration with OpenAI's Chat Co 📜 Keeps track of the conversation history for you, making conversation continuity a breeze. -💰 Estimate the cost and size of conversations before sending them to the API. +💰 Estimate the cost and size of conversations before sending them to the API. (*through the `gpt-turbo-plugin-stats` plugin*) 💾 Easily persist conversations with serialization and deserialization methods. +🔌 Includes a plugin system for extending the library's functionality. + 💻 Built entirely with TypeScript. ⚔️ Battle-tested in multiple environments. (See [implementations](#implementations)) @@ -42,10 +51,16 @@ GPT Turbo is a JavaScript library for seamless integration with OpenAI's Chat Co This repo is a mono-repo containing both the [Library](./packages/lib/) and small projects powered by it. Here's a list of all the projects that were built with the GPT Turbo [Library](./packages/lib/) -- [CLI](./packages/cli/): A command-line interface to chat straight from your terminal. -- [Web](./packages/web/): A web app, very similar to ChatGPT, for handling chats in the browser. -- [Nest](./packages/nest/): A NestJS backend, for interacting with the library via a REST API. -- [Discord](./packages/discord/): A Discord bot for chatting in Discord servers, similar to Discord's own Clyde AI bot. +- [Web](./packages/implementations/web/): A web app, very similar to ChatGPT, for handling chats in the browser. +- [Discord](./packages/implementations/discord/): A Discord bot for chatting in Discord servers, similar to Discord's own Clyde AI bot. +- [CLI](./packages/implementations/cli/): A command-line interface to chat straight from your terminal. +- [Nest](./packages/implementations/nest/): A NestJS backend, for interacting with the library via a REST API. + +## Plugins + +GPT Turbo has a plugin system for extending the library's functionality. While anyone can create and publish custom plugins, this repo contains the following home-made plugins: + +- [gpt-turbo-plugin-stats](./packages/plugins/gpt-turbo-plugin-stats/): A plugin for estimating the cost and size of conversations before sending them to the API. ## Discord diff --git a/lerna.json b/lerna.json index c153fc6..fee2e8b 100644 --- a/lerna.json +++ b/lerna.json @@ -1,4 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "4.5.0" + "version": "4.5.0", + "useNx": false } diff --git a/package-lock.json b/package-lock.json index de3797e..5d019a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "name": "root", "hasInstallScript": true, "workspaces": [ - "packages/*" + "packages/**" ], "dependencies": { "immer": "^10.0.2" @@ -3719,18 +3719,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.1.tgz", + "integrity": "sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -3785,9 +3785,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "version": "8.46.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.46.0.tgz", + "integrity": "sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4139,10 +4139,43 @@ "node": ">=8" } }, + "node_modules/@mantine/core": { + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@mantine/core/-/core-6.0.17.tgz", + "integrity": "sha512-g3EDxcTJKisvEGTsGJPCGXiDumwr4O0nGNXwoGLnrg19nh3FAMfEIq18sJJLtRrBuarSbrvgMVYvKx1R6rTOWg==", + "dependencies": { + "@floating-ui/react": "^0.19.1", + "@mantine/styles": "6.0.17", + "@mantine/utils": "6.0.17", + "@radix-ui/react-scroll-area": "1.0.2", + "react-remove-scroll": "^2.5.5", + "react-textarea-autosize": "8.3.4" + }, + "peerDependencies": { + "@mantine/hooks": "6.0.17", + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@mantine/dropzone": { + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@mantine/dropzone/-/dropzone-6.0.17.tgz", + "integrity": "sha512-LUyNnW2qo41WIDcHgxMssol41r6nXfb1bvICbAwzBHzWcaVHjIXiqRJ1GV8N6Y6o7ilSXxyWTnNVw0fEJ8dkbw==", + "dependencies": { + "@mantine/utils": "6.0.17", + "react-dropzone": "14.2.3" + }, + "peerDependencies": { + "@mantine/core": "6.0.17", + "@mantine/hooks": "6.0.17", + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/@mantine/form": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/@mantine/form/-/form-6.0.16.tgz", - "integrity": "sha512-4TwxJKGQQRx7rj5yb9WgS0z/Ud8ckg0mMCiD3grKTxDCp0g8Tvk2Df7ptWFx2n+hxhBYVwMQSKggWuuDMFWBNA==", + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@mantine/form/-/form-6.0.17.tgz", + "integrity": "sha512-hrWlBukErklaFSvKfz4PCl3Cd7UgHf5Q/FyZPD+WvBDT0zZ5uMjatQpVs/HAfhFOA5O2DFKAcs654mLzmJJ6Wg==", "dependencies": { "fast-deep-equal": "^3.1.3", "klona": "^2.0.5" @@ -4151,6 +4184,101 @@ "react": ">=16.8.0" } }, + "node_modules/@mantine/hooks": { + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-6.0.17.tgz", + "integrity": "sha512-7vf2w1NlzKlUynSuyI2DAIKoEOYKYC8k+tlSsk3BRdbzhbJAiWxcYzJy5seg5dFW1WIpKAZ0wiVdHXf/WRlRgg==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@mantine/modals": { + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@mantine/modals/-/modals-6.0.17.tgz", + "integrity": "sha512-57S4+G7+iPZOd6utzx3aYRKA1FcfJX7tfnbPafk303gSbZ9KQ3UWKJn9bk1HWev8AQsrNDyPH1zhjxVGpnqTZA==", + "dependencies": { + "@mantine/utils": "6.0.17" + }, + "peerDependencies": { + "@mantine/core": "6.0.17", + "@mantine/hooks": "6.0.17", + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@mantine/notifications": { + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-6.0.17.tgz", + "integrity": "sha512-iY8hdRG4RcrsA7U06AOWLbKrQJAzEhKi2mESOnGE4s7RBWJjLTXJf+gTKi+QtVa3XNIF0I/adpEh8MEFD5zGWw==", + "dependencies": { + "@mantine/utils": "6.0.17", + "react-transition-group": "4.4.2" + }, + "peerDependencies": { + "@mantine/core": "6.0.17", + "@mantine/hooks": "6.0.17", + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@mantine/prism": { + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@mantine/prism/-/prism-6.0.17.tgz", + "integrity": "sha512-oUnvLIU/ERvGqYVDasVIQH5pJpmi4DooGB5tucef1uS7u/rt68iAaNKCpPK4ghYZekCC8VO/cXdB9BzZACj5EA==", + "dependencies": { + "@mantine/utils": "6.0.17", + "prism-react-renderer": "^1.2.1" + }, + "peerDependencies": { + "@mantine/core": "6.0.17", + "@mantine/hooks": "6.0.17", + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@mantine/styles": { + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@mantine/styles/-/styles-6.0.17.tgz", + "integrity": "sha512-utNwQJgKHguNS0iPyyeFRJy4nbt280XMbmfUf4GCxXlyl/mQxq+JoaKP/OmU7+8kfbtLS9kHeuBSghrC65Nt1g==", + "dependencies": { + "clsx": "1.1.1", + "csstype": "3.0.9" + }, + "peerDependencies": { + "@emotion/react": ">=11.9.0", + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@mantine/styles/node_modules/csstype": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.9.tgz", + "integrity": "sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw==" + }, + "node_modules/@mantine/tiptap": { + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@mantine/tiptap/-/tiptap-6.0.17.tgz", + "integrity": "sha512-yTPkFyDeaff8Rl9DMkPXWvn/qoGkXn9u+yr+zupF4y+lzvtz4h/Zxp5Q2nAaCXa1zSmTanWhJunN5QVzRZy4Yg==", + "dependencies": { + "@mantine/utils": "6.0.17" + }, + "peerDependencies": { + "@mantine/core": "6.0.17", + "@mantine/hooks": "6.0.17", + "@tabler/icons-react": ">=2.1.0", + "@tiptap/extension-link": "^2.0.0-beta.202", + "@tiptap/react": "^2.0.0-beta.202", + "react": ">=16.8.0" + } + }, + "node_modules/@mantine/utils": { + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@mantine/utils/-/utils-6.0.17.tgz", + "integrity": "sha512-U6SWV/asYE6NhiHx4ltmVZdQR3HwGVqJxVulhOylMcV1tX/P1LMQUCbGV2Oe4O9jbX4/YW5B/CBb4BbEhENQFQ==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@nestjs/cli": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.5.0.tgz", @@ -9241,27 +9369,27 @@ } }, "node_modules/eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "version": "8.46.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.46.0.tgz", + "integrity": "sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.1", + "@eslint/js": "^8.46.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.2", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -9295,9 +9423,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.9.0.tgz", + "integrity": "sha512-+sbni7NfVXnOpnRadUA8S28AUlsZt9GjgFvABIRL9Hkn8KqNzOp+7Lw4QWtrwn20KzU3wqu1QoOj2m+7rKRqkA==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -9362,9 +9490,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz", + "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -9390,9 +9518,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -10623,29 +10751,36 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gpt-token-utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gpt-token-utils/-/gpt-token-utils-1.2.0.tgz", - "integrity": "sha512-s8twaU38UE2Vp65JhQEjz8qvWhWY8KZYvmvYHapxlPT03Ok35Clq+gm9eE27wQILdFisseMVRSiC5lJR9GBklA==" + "node_modules/gpt-tokenizer": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/gpt-tokenizer/-/gpt-tokenizer-2.1.1.tgz", + "integrity": "sha512-WlX+vj6aPaZ71U6Bf18fem+5k58zlgh2a4nbc7KHy6aGVIyq3nCh709b/8momu34sV/5t/SpzWi8LayWD9uyDw==", + "dependencies": { + "rfc4648": "^1.5.2" + } }, "node_modules/gpt-turbo": { "resolved": "packages/lib", "link": true }, "node_modules/gpt-turbo-cli": { - "resolved": "packages/cli", + "resolved": "packages/implementations/cli", "link": true }, "node_modules/gpt-turbo-discord": { - "resolved": "packages/discord", + "resolved": "packages/implementations/discord", "link": true }, "node_modules/gpt-turbo-nest": { - "resolved": "packages/nest", + "resolved": "packages/implementations/nest", + "link": true + }, + "node_modules/gpt-turbo-plugin-stats": { + "resolved": "packages/plugins/gpt-turbo-plugin-stats", "link": true }, "node_modules/gpt-turbo-web": { - "resolved": "packages/web", + "resolved": "packages/implementations/web", "link": true }, "node_modules/graceful-fs": { @@ -15025,13 +15160,13 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", - "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1", - "minipass": "^5.0.0 || ^6.0.2" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -16585,6 +16720,11 @@ "node": ">=0.10.0" } }, + "node_modules/rfc4648": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.2.tgz", + "integrity": "sha512-tLOizhR6YGovrEBLatX1sdcuhoSCXddw3mqNVAcKxGJ+J0hFeJ+SjeWCv5UPA/WU3YzWPPuCVYgXBKZUPGpKtg==" + }, "node_modules/rimraf": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", @@ -16838,9 +16978,9 @@ "dev": true }, "node_modules/semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -20291,12 +20431,77 @@ } }, "packages/cli": { + "name": "gpt-turbo-cli", + "version": "4.5.0", + "extraneous": true, + "license": "MIT", + "dependencies": { + "dotenv": "^16.0.3", + "gpt-turbo": "^4.5.0", + "ink": "^4.0.0", + "ink-spinner": "^5.0.0", + "ink-text-input": "^5.0.0", + "react": "^18.2.0", + "uuid": "^9.0.0", + "yargs": "^17.7.1", + "zod": "^3.21.4" + }, + "bin": { + "gpt-turbo": "dist/index.js" + }, + "devDependencies": { + "@types/react": "^18.0.28", + "@types/yargs": "^17.0.22", + "@typescript-eslint/eslint-plugin": "^5.54.0", + "@typescript-eslint/parser": "^5.54.0", + "copyfiles": "^2.4.1", + "eslint": "^8.35.0", + "eslint-config-prettier": "^8.6.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react-hooks": "^4.6.0", + "nodemon": "^2.0.21", + "prettier": "^2.8.4", + "rimraf": "^4.2.0", + "ts-node": "^10.9.1", + "typescript": "^4.9.5" + } + }, + "packages/discord": { + "name": "gpt-turbo-discord", + "version": "4.5.0", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@keyv/mongo": "^2.1.8", + "@keyv/mysql": "^1.6.3", + "@keyv/postgres": "^1.4.4", + "discord.js": "^14.9.0", + "dotenv": "^16.0.3", + "gpt-turbo": "^4.5.0", + "keyv": "^4.5.2" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^5.54.0", + "@typescript-eslint/parser": "^5.54.0", + "copyfiles": "^2.4.1", + "eslint": "^8.35.0", + "eslint-config-prettier": "^8.6.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.4", + "rimraf": "^4.2.0", + "ts-node": "^10.9.1", + "tsx": "^3.12.6", + "typescript": "^4.9.5" + } + }, + "packages/implementations/cli": { "name": "gpt-turbo-cli", "version": "4.5.0", "license": "MIT", "dependencies": { "dotenv": "^16.0.3", "gpt-turbo": "^4.5.0", + "gpt-turbo-plugin-stats": "^4.5.0", "ink": "^4.0.0", "ink-spinner": "^5.0.0", "ink-text-input": "^5.0.0", @@ -20325,7 +20530,7 @@ "typescript": "^4.9.5" } }, - "packages/cli/node_modules/cliui": { + "packages/implementations/cli/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", @@ -20338,7 +20543,7 @@ "node": ">=12" } }, - "packages/cli/node_modules/typescript": { + "packages/implementations/cli/node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", @@ -20351,7 +20556,7 @@ "node": ">=4.2.0" } }, - "packages/cli/node_modules/wrap-ansi": { + "packages/implementations/cli/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", @@ -20367,7 +20572,7 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "packages/cli/node_modules/yargs": { + "packages/implementations/cli/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", @@ -20384,7 +20589,7 @@ "node": ">=12" } }, - "packages/cli/node_modules/yargs-parser": { + "packages/implementations/cli/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", @@ -20392,7 +20597,7 @@ "node": ">=12" } }, - "packages/discord": { + "packages/implementations/discord": { "name": "gpt-turbo-discord", "version": "4.5.0", "license": "MIT", @@ -20403,6 +20608,7 @@ "discord.js": "^14.9.0", "dotenv": "^16.0.3", "gpt-turbo": "^4.5.0", + "gpt-turbo-plugin-stats": "^4.5.0", "keyv": "^4.5.2" }, "devDependencies": { @@ -20419,44 +20625,7 @@ "typescript": "^4.9.5" } }, - "packages/discord/node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "packages/lib": { - "name": "gpt-turbo", - "version": "4.5.0", - "license": "MIT", - "dependencies": { - "gpt-token-utils": "^1.2.0", - "uuid": "^9.0.0", - "zod": "^3.21.4" - }, - "devDependencies": { - "@types/uuid": "^9.0.1", - "@typescript-eslint/eslint-plugin": "^5.54.0", - "@typescript-eslint/parser": "^5.54.0", - "copyfiles": "^2.4.1", - "eslint": "^8.35.0", - "eslint-config-prettier": "^8.6.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.4", - "rimraf": "^4.2.0", - "ts-node": "^10.9.1", - "typedoc": "^0.24.1", - "typescript": "^4.9.5" - } - }, - "packages/lib/node_modules/typescript": { + "packages/implementations/discord/node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", @@ -20469,7 +20638,7 @@ "node": ">=4.2.0" } }, - "packages/nest": { + "packages/implementations/nest": { "name": "gpt-turbo-nest", "version": "4.5.0", "license": "MIT", @@ -20480,6 +20649,7 @@ "@nestjs/swagger": "^6.3.0", "dotenv": "^16.0.3", "gpt-turbo": "^4.5.0", + "gpt-turbo-plugin-stats": "^4.5.0", "lowdb": "^5.1.0", "nestjs-zod": "^2.0.3", "reflect-metadata": "^0.1.13", @@ -20506,13 +20676,13 @@ "typescript": "^4.7.4" } }, - "packages/nest/node_modules/@types/node": { + "packages/implementations/nest/node_modules/@types/node": { "version": "18.11.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", "dev": true }, - "packages/nest/node_modules/typescript": { + "packages/implementations/nest/node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", @@ -20525,20 +20695,20 @@ "node": ">=4.2.0" } }, - "packages/web": { + "packages/implementations/web": { "name": "gpt-turbo-web", "version": "4.5.0", "license": "MIT", "dependencies": { "@emotion/react": "^11.11.1", - "@mantine/core": "^6.0.16", - "@mantine/dropzone": "6.0.16", - "@mantine/form": "^6.0.16", - "@mantine/hooks": "^6.0.16", - "@mantine/modals": "^6.0.16", - "@mantine/notifications": "^6.0.16", - "@mantine/prism": "^6.0.16", - "@mantine/tiptap": "^6.0.16", + "@mantine/core": "^6.0.17", + "@mantine/dropzone": "6.0.17", + "@mantine/form": "^6.0.17", + "@mantine/hooks": "^6.0.17", + "@mantine/modals": "^6.0.17", + "@mantine/notifications": "^6.0.17", + "@mantine/prism": "^6.0.17", + "@mantine/tiptap": "^6.0.17", "@tabler/icons-react": "^2.25.0", "@tiptap/extension-code-block-lowlight": "^2.0.3", "@tiptap/extension-link": "^2.0.3", @@ -20546,6 +20716,7 @@ "@tiptap/react": "^2.0.3", "@tiptap/starter-kit": "^2.0.3", "gpt-turbo": "^4.5.0", + "gpt-turbo-plugin-stats": "^4.5.0", "lowlight": "^2.9.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -20574,147 +20745,280 @@ "vite-plugin-pwa": "^0.16.4" } }, - "packages/web/node_modules/@mantine/core": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/@mantine/core/-/core-6.0.16.tgz", - "integrity": "sha512-ai7HfWo214JLmf+QNEmFfTaBgxreMpY/ZK7dIDNkFfCmDAWjFxwCSc7flh8NHX2ZJN5uTc82p2i0MLJ/GZ5xrA==", + "packages/implementations/web/node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.2.0.tgz", + "integrity": "sha512-rClGrMuyS/3j0ETa1Ui7s6GkLhfZGKZL3ZrChLeAiACBE/tRc1wq8SNZESUuluxhLj9FkUefRs2l6bCIArWBiQ==", + "dev": true, "dependencies": { - "@floating-ui/react": "^0.19.1", - "@mantine/styles": "6.0.16", - "@mantine/utils": "6.0.16", - "@radix-ui/react-scroll-area": "1.0.2", - "react-remove-scroll": "^2.5.5", - "react-textarea-autosize": "8.3.4" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.2.0", + "@typescript-eslint/type-utils": "6.2.0", + "@typescript-eslint/utils": "6.2.0", + "@typescript-eslint/visitor-keys": "6.2.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@mantine/hooks": "6.0.16", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "packages/web/node_modules/@mantine/dropzone": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/@mantine/dropzone/-/dropzone-6.0.16.tgz", - "integrity": "sha512-zVmJFPesI4NyLvjvhM77WwE+AO+ixPq934fjrtCvHTtFRVrbuuUa+tOk6LNPX0grQLOZMb0fnlZXy8KH03ES+w==", + "packages/implementations/web/node_modules/@typescript-eslint/parser": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.2.0.tgz", + "integrity": "sha512-igVYOqtiK/UsvKAmmloQAruAdUHihsOCvplJpplPZ+3h4aDkC/UKZZNKgB6h93ayuYLuEymU3h8nF1xMRbh37g==", + "dev": true, "dependencies": { - "@mantine/utils": "6.0.16", - "react-dropzone": "14.2.3" + "@typescript-eslint/scope-manager": "6.2.0", + "@typescript-eslint/types": "6.2.0", + "@typescript-eslint/typescript-estree": "6.2.0", + "@typescript-eslint/visitor-keys": "6.2.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@mantine/core": "6.0.16", - "@mantine/hooks": "6.0.16", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "packages/web/node_modules/@mantine/hooks": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-6.0.16.tgz", - "integrity": "sha512-DnfMYSTSjYxbQJ80TzKHO5gRXGTIQKxBnRQVc+n4RANTwgWMiwEmxIwqRjbulfLzIhEvplskhqGgElunIAfw7g==", - "peerDependencies": { - "react": ">=16.8.0" + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "packages/web/node_modules/@mantine/modals": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/@mantine/modals/-/modals-6.0.16.tgz", - "integrity": "sha512-RMDp5jZTrbXgMJN3aPBt82LsIL91xepQDq/zmtLnj2JJnDYTKZarvpOJPvUO/Ewyr6GYJ3iNbcXkV0w0CqCNGg==", + "packages/implementations/web/node_modules/@typescript-eslint/scope-manager": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.2.0.tgz", + "integrity": "sha512-1ZMNVgm5nnHURU8ZSJ3snsHzpFeNK84rdZjluEVBGNu7jDymfqceB3kdIZ6A4xCfEFFhRIB6rF8q/JIqJd2R0Q==", + "dev": true, "dependencies": { - "@mantine/utils": "6.0.16" + "@typescript-eslint/types": "6.2.0", + "@typescript-eslint/visitor-keys": "6.2.0" }, - "peerDependencies": { - "@mantine/core": "6.0.16", - "@mantine/hooks": "6.0.16", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "packages/web/node_modules/@mantine/notifications": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-6.0.16.tgz", - "integrity": "sha512-KqlPW51sxgQoJmIC2lEWMVlwPqy04D35iRMkCSget8aNgzk0K5csJppXo6qwMFn2GHKVGXFKJMBUp06IXQbiig==", + "packages/implementations/web/node_modules/@typescript-eslint/type-utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.2.0.tgz", + "integrity": "sha512-DnGZuNU2JN3AYwddYIqrVkYW0uUQdv0AY+kz2M25euVNlujcN2u+rJgfJsBFlUEzBB6OQkUqSZPyuTLf2bP5mw==", + "dev": true, "dependencies": { - "@mantine/utils": "6.0.16", - "react-transition-group": "4.4.2" + "@typescript-eslint/typescript-estree": "6.2.0", + "@typescript-eslint/utils": "6.2.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@mantine/core": "6.0.16", - "@mantine/hooks": "6.0.16", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "packages/web/node_modules/@mantine/prism": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/@mantine/prism/-/prism-6.0.16.tgz", - "integrity": "sha512-bWnwRMA7fBfSMpZO2YHIsJ4yt3JTZmPp1nQ62JKpey7rfCJMMuzuCXagCHZthEChZZoQnwmndr4agEzuNIIxmA==", + "packages/implementations/web/node_modules/@typescript-eslint/types": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.2.0.tgz", + "integrity": "sha512-1nRRaDlp/XYJQLvkQJG5F3uBTno5SHPT7XVcJ5n1/k2WfNI28nJsvLakxwZRNY5spuatEKO7d5nZWsQpkqXwBA==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/implementations/web/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.2.0.tgz", + "integrity": "sha512-Mts6+3HQMSM+LZCglsc2yMIny37IhUgp1Qe8yJUYVyO6rHP7/vN0vajKu3JvHCBIy8TSiKddJ/Zwu80jhnGj1w==", + "dev": true, "dependencies": { - "@mantine/utils": "6.0.16", - "prism-react-renderer": "^1.2.1" + "@typescript-eslint/types": "6.2.0", + "@typescript-eslint/visitor-keys": "6.2.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, - "peerDependencies": { - "@mantine/core": "6.0.16", - "@mantine/hooks": "6.0.16", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "packages/web/node_modules/@mantine/styles": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/@mantine/styles/-/styles-6.0.16.tgz", - "integrity": "sha512-0rDE3BzJOKVdPAbnL3XokVWNYgo1z323UgAURdB+WvzwZY7PhblwvrxUDwvvV77qCUENg2vU0LKHqTQD1DDLTg==", + "packages/implementations/web/node_modules/@typescript-eslint/utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.2.0.tgz", + "integrity": "sha512-RCFrC1lXiX1qEZN8LmLrxYRhOkElEsPKTVSNout8DMzf8PeWoQG7Rxz2SadpJa3VSh5oYKGwt7j7X/VRg+Y3OQ==", + "dev": true, "dependencies": { - "clsx": "1.1.1", - "csstype": "3.0.9" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.2.0", + "@typescript-eslint/types": "6.2.0", + "@typescript-eslint/typescript-estree": "6.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@emotion/react": ">=11.9.0", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "eslint": "^7.0.0 || ^8.0.0" } }, - "packages/web/node_modules/@mantine/tiptap": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/@mantine/tiptap/-/tiptap-6.0.16.tgz", - "integrity": "sha512-W/289lRW7AoNOh4/1WX31K0z+Uk9lJpZyC+m3TuywPSJCINU2ETmj1r+RZl3szf2hLCt5FhSspIAcPgkA2LYQw==", + "packages/implementations/web/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.2.0.tgz", + "integrity": "sha512-QbaYUQVKKo9bgCzpjz45llCfwakyoxHetIy8CAvYCtd16Zu1KrpzNHofwF8kGkpPOxZB2o6kz+0nqH8ZkIzuoQ==", + "dev": true, "dependencies": { - "@mantine/utils": "6.0.16" + "@typescript-eslint/types": "6.2.0", + "eslint-visitor-keys": "^3.4.1" }, - "peerDependencies": { - "@mantine/core": "6.0.16", - "@mantine/hooks": "6.0.16", - "@tabler/icons-react": ">=2.1.0", - "@tiptap/extension-link": "^2.0.0-beta.202", - "@tiptap/react": "^2.0.0-beta.202", - "react": ">=16.8.0" + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "packages/web/node_modules/@mantine/utils": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/@mantine/utils/-/utils-6.0.16.tgz", - "integrity": "sha512-UFel9DbifL3zS8pTJlr6GfwGd6464OWXCJdUq0oLydgimbC1VV2PnptBr6FMwIpPVcxouLOtY1cChzwFH95PSA==", + "packages/implementations/web/node_modules/eslint-plugin-prettier": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", + "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/prettier" + }, "peerDependencies": { - "react": ">=16.8.0" + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "packages/web/node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.0.0.tgz", - "integrity": "sha512-xuv6ghKGoiq856Bww/yVYnXGsKa588kY3M0XK7uUW/3fJNNULKRfZfSBkMTSpqGG/8ZCXCadfh8G/z/B4aqS/A==", + "packages/implementations/web/node_modules/prettier": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz", + "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "packages/lib": { + "name": "gpt-turbo", + "version": "4.5.0", + "license": "MIT", + "dependencies": { + "uuid": "^9.0.0", + "zod": "^3.21.4" + }, + "devDependencies": { + "@types/uuid": "^9.0.2", + "@typescript-eslint/eslint-plugin": "^6.2.0", + "@typescript-eslint/parser": "^6.2.0", + "copyfiles": "^2.4.1", + "eslint": "^8.46.0", + "eslint-config-prettier": "^8.9.0", + "eslint-plugin-prettier": "^5.0.0", + "prettier": "^3.0.0", + "rimraf": "^5.0.1", + "ts-node": "^10.9.1", + "typedoc": "^0.24.8", + "typescript": "^5.1.6" + } + }, + "packages/lib/node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.2.0.tgz", + "integrity": "sha512-rClGrMuyS/3j0ETa1Ui7s6GkLhfZGKZL3ZrChLeAiACBE/tRc1wq8SNZESUuluxhLj9FkUefRs2l6bCIArWBiQ==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.5.0", - "@typescript-eslint/scope-manager": "6.0.0", - "@typescript-eslint/type-utils": "6.0.0", - "@typescript-eslint/utils": "6.0.0", - "@typescript-eslint/visitor-keys": "6.0.0", + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.2.0", + "@typescript-eslint/type-utils": "6.2.0", + "@typescript-eslint/utils": "6.2.0", + "@typescript-eslint/visitor-keys": "6.2.0", "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", "natural-compare": "^1.4.0", "natural-compare-lite": "^1.4.0", - "semver": "^7.5.0", + "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, "engines": { @@ -20734,16 +21038,16 @@ } } }, - "packages/web/node_modules/@typescript-eslint/parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.0.0.tgz", - "integrity": "sha512-TNaufYSPrr1U8n+3xN+Yp9g31vQDJqhXzzPSHfQDLcaO4tU+mCfODPxCwf4H530zo7aUBE3QIdxCXamEnG04Tg==", + "packages/lib/node_modules/@typescript-eslint/parser": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.2.0.tgz", + "integrity": "sha512-igVYOqtiK/UsvKAmmloQAruAdUHihsOCvplJpplPZ+3h4aDkC/UKZZNKgB6h93ayuYLuEymU3h8nF1xMRbh37g==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.0.0", - "@typescript-eslint/types": "6.0.0", - "@typescript-eslint/typescript-estree": "6.0.0", - "@typescript-eslint/visitor-keys": "6.0.0", + "@typescript-eslint/scope-manager": "6.2.0", + "@typescript-eslint/types": "6.2.0", + "@typescript-eslint/typescript-estree": "6.2.0", + "@typescript-eslint/visitor-keys": "6.2.0", "debug": "^4.3.4" }, "engines": { @@ -20762,14 +21066,14 @@ } } }, - "packages/web/node_modules/@typescript-eslint/scope-manager": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.0.0.tgz", - "integrity": "sha512-o4q0KHlgCZTqjuaZ25nw5W57NeykZT9LiMEG4do/ovwvOcPnDO1BI5BQdCsUkjxFyrCL0cSzLjvIMfR9uo7cWg==", + "packages/lib/node_modules/@typescript-eslint/scope-manager": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.2.0.tgz", + "integrity": "sha512-1ZMNVgm5nnHURU8ZSJ3snsHzpFeNK84rdZjluEVBGNu7jDymfqceB3kdIZ6A4xCfEFFhRIB6rF8q/JIqJd2R0Q==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.0.0", - "@typescript-eslint/visitor-keys": "6.0.0" + "@typescript-eslint/types": "6.2.0", + "@typescript-eslint/visitor-keys": "6.2.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -20779,14 +21083,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "packages/web/node_modules/@typescript-eslint/type-utils": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.0.0.tgz", - "integrity": "sha512-ah6LJvLgkoZ/pyJ9GAdFkzeuMZ8goV6BH7eC9FPmojrnX9yNCIsfjB+zYcnex28YO3RFvBkV6rMV6WpIqkPvoQ==", + "packages/lib/node_modules/@typescript-eslint/type-utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.2.0.tgz", + "integrity": "sha512-DnGZuNU2JN3AYwddYIqrVkYW0uUQdv0AY+kz2M25euVNlujcN2u+rJgfJsBFlUEzBB6OQkUqSZPyuTLf2bP5mw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.0.0", - "@typescript-eslint/utils": "6.0.0", + "@typescript-eslint/typescript-estree": "6.2.0", + "@typescript-eslint/utils": "6.2.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -20806,10 +21110,10 @@ } } }, - "packages/web/node_modules/@typescript-eslint/types": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.0.0.tgz", - "integrity": "sha512-Zk9KDggyZM6tj0AJWYYKgF0yQyrcnievdhG0g5FqyU3Y2DRxJn4yWY21sJC0QKBckbsdKKjYDV2yVrrEvuTgxg==", + "packages/lib/node_modules/@typescript-eslint/types": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.2.0.tgz", + "integrity": "sha512-1nRRaDlp/XYJQLvkQJG5F3uBTno5SHPT7XVcJ5n1/k2WfNI28nJsvLakxwZRNY5spuatEKO7d5nZWsQpkqXwBA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -20819,18 +21123,18 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "packages/web/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.0.0.tgz", - "integrity": "sha512-2zq4O7P6YCQADfmJ5OTDQTP3ktajnXIRrYAtHM9ofto/CJZV3QfJ89GEaM2BNGeSr1KgmBuLhEkz5FBkS2RQhQ==", + "packages/lib/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.2.0.tgz", + "integrity": "sha512-Mts6+3HQMSM+LZCglsc2yMIny37IhUgp1Qe8yJUYVyO6rHP7/vN0vajKu3JvHCBIy8TSiKddJ/Zwu80jhnGj1w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.0.0", - "@typescript-eslint/visitor-keys": "6.0.0", + "@typescript-eslint/types": "6.2.0", + "@typescript-eslint/visitor-keys": "6.2.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.5.0", + "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, "engines": { @@ -20846,20 +21150,19 @@ } } }, - "packages/web/node_modules/@typescript-eslint/utils": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.0.0.tgz", - "integrity": "sha512-SOr6l4NB6HE4H/ktz0JVVWNXqCJTOo/mHnvIte1ZhBQ0Cvd04x5uKZa3zT6tiodL06zf5xxdK8COiDvPnQ27JQ==", + "packages/lib/node_modules/@typescript-eslint/utils": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.2.0.tgz", + "integrity": "sha512-RCFrC1lXiX1qEZN8LmLrxYRhOkElEsPKTVSNout8DMzf8PeWoQG7Rxz2SadpJa3VSh5oYKGwt7j7X/VRg+Y3OQ==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.3.0", - "@types/json-schema": "^7.0.11", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "6.0.0", - "@typescript-eslint/types": "6.0.0", - "@typescript-eslint/typescript-estree": "6.0.0", - "eslint-scope": "^5.1.1", - "semver": "^7.5.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.2.0", + "@typescript-eslint/types": "6.2.0", + "@typescript-eslint/typescript-estree": "6.2.0", + "semver": "^7.5.4" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -20872,13 +21175,13 @@ "eslint": "^7.0.0 || ^8.0.0" } }, - "packages/web/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.0.0.tgz", - "integrity": "sha512-cvJ63l8c0yXdeT5POHpL0Q1cZoRcmRKFCtSjNGJxPkcP571EfZMcNbzWAc7oK3D1dRzm/V5EwtkANTZxqvuuUA==", + "packages/lib/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.2.0.tgz", + "integrity": "sha512-QbaYUQVKKo9bgCzpjz45llCfwakyoxHetIy8CAvYCtd16Zu1KrpzNHofwF8kGkpPOxZB2o6kz+0nqH8ZkIzuoQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.0.0", + "@typescript-eslint/types": "6.2.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -20889,12 +21192,16 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "packages/web/node_modules/csstype": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.9.tgz", - "integrity": "sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw==" + "packages/lib/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } }, - "packages/web/node_modules/eslint-plugin-prettier": { + "packages/lib/node_modules/eslint-plugin-prettier": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==", @@ -20923,7 +21230,44 @@ } } }, - "packages/web/node_modules/prettier": { + "packages/lib/node_modules/glob": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/lib/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/lib/node_modules/prettier": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz", "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==", @@ -20937,6 +21281,147 @@ "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } + }, + "packages/lib/node_modules/rimraf": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", + "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", + "dev": true, + "dependencies": { + "glob": "^10.2.5" + }, + "bin": { + "rimraf": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/nest": { + "name": "gpt-turbo-nest", + "version": "4.5.0", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@nestjs/common": "^9.0.0", + "@nestjs/core": "^9.0.0", + "@nestjs/platform-express": "^9.0.0", + "@nestjs/swagger": "^6.3.0", + "dotenv": "^16.0.3", + "gpt-turbo": "^4.5.0", + "lowdb": "^5.1.0", + "nestjs-zod": "^2.0.3", + "reflect-metadata": "^0.1.13", + "rxjs": "^7.2.0" + }, + "devDependencies": { + "@nestjs/cli": "^9.0.0", + "@nestjs/schematics": "^9.0.0", + "@nestjs/testing": "^9.0.0", + "@types/express": "^4.17.13", + "@types/node": "18.11.18", + "@types/supertest": "^2.0.11", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "cross-env": "^7.0.3", + "eslint": "^8.0.1", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0", + "prettier": "^2.3.2", + "source-map-support": "^0.5.20", + "ts-loader": "^9.2.3", + "ts-node": "^10.0.0", + "tsconfig-paths": "4.1.1", + "typescript": "^4.7.4" + } + }, + "packages/plugins/gpt-turbo-plugin-stats": { + "version": "4.5.0", + "license": "MIT", + "dependencies": { + "gpt-tokenizer": "^2.1.1" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^5.54.0", + "@typescript-eslint/parser": "^5.54.0", + "copyfiles": "^2.4.1", + "eslint": "^8.35.0", + "eslint-config-prettier": "^8.6.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.4", + "rimraf": "^4.2.0", + "ts-node": "^10.9.1", + "typescript": "^4.9.5" + }, + "peerDependencies": { + "gpt-turbo": "4.5.0" + } + }, + "packages/plugins/gpt-turbo-plugin-stats/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "packages/web": { + "name": "gpt-turbo-web", + "version": "4.5.0", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@emotion/react": "^11.11.1", + "@mantine/core": "^6.0.16", + "@mantine/dropzone": "6.0.16", + "@mantine/form": "^6.0.16", + "@mantine/hooks": "^6.0.16", + "@mantine/modals": "^6.0.16", + "@mantine/notifications": "^6.0.16", + "@mantine/prism": "^6.0.16", + "@mantine/tiptap": "^6.0.16", + "@tabler/icons-react": "^2.25.0", + "@tiptap/extension-code-block-lowlight": "^2.0.3", + "@tiptap/extension-link": "^2.0.3", + "@tiptap/pm": "^2.0.3", + "@tiptap/react": "^2.0.3", + "@tiptap/starter-kit": "^2.0.3", + "gpt-turbo": "^4.5.0", + "lowlight": "^2.9.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-icons": "^4.10.1", + "react-router-dom": "^6.14.1", + "uuid": "^9.0.0", + "zod": "^3.21.4", + "zustand": "^4.3.9" + }, + "devDependencies": { + "@types/react": "^18.2.15", + "@types/react-dom": "^18.2.7", + "@types/uuid": "^9.0.2", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "@vitejs/plugin-react-swc": "^3.3.2", + "eslint": "^8.45.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.3", + "prettier": "^3.0.0", + "typescript": "^5.1.6", + "vite": "^4.4.4", + "vite-plugin-eslint": "^1.8.1", + "vite-plugin-pwa": "^0.16.4" + } } } } diff --git a/package.json b/package.json index e482355..4b2bc93 100644 --- a/package.json +++ b/package.json @@ -6,17 +6,21 @@ "dev": "lerna run build --scope \"gpt-turbo\" && lerna watch --scope \"gpt-turbo\" --include-dependencies -- lerna run build --scope=\"gpt-turbo\"", "build": "lerna run build", "build:lib": "lerna run build --scope \"gpt-turbo\"", + "build:stats": "lerna run build --scope \"gpt-turbo-plugin-stats\"", "build:web": "lerna run build --scope \"gpt-turbo-web\"", + "build:cli": "lerna run build --scope \"gpt-turbo-cli\"", + "build:discord": "lerna run build --scope \"gpt-turbo-discord\"", + "build:nest": "lerna run build --scope \"gpt-turbo-nest\"", "lint:strict": "lerna run lint:strict", "lint:fix": "lerna run lint:fix", "release": "npm run build && lerna publish", "release:patch": "npm run build && lerna publish patch --yes", "release:minor": "npm run build && lerna publish minor --yes", "release:major": "npm run build && lerna publish major --yes", - "postinstall": "npm run build:lib" + "postinstall": "npm run build:lib && npm run build:stats" }, "workspaces": [ - "packages/*" + "packages/**" ], "devDependencies": { "lerna": "^7.0.2", diff --git a/packages/cli/.env.example b/packages/implementations/cli/.env.example similarity index 100% rename from packages/cli/.env.example rename to packages/implementations/cli/.env.example diff --git a/packages/cli/.eslintrc.cjs b/packages/implementations/cli/.eslintrc.cjs similarity index 97% rename from packages/cli/.eslintrc.cjs rename to packages/implementations/cli/.eslintrc.cjs index 2ce4837..27da1b6 100644 --- a/packages/cli/.eslintrc.cjs +++ b/packages/implementations/cli/.eslintrc.cjs @@ -29,6 +29,7 @@ module.exports = { ], "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/await-thenable": "warn", "max-classes-per-file": "off", "no-useless-constructor": "off", "class-methods-use-this": "off", diff --git a/packages/cli/.prettierrc b/packages/implementations/cli/.prettierrc similarity index 100% rename from packages/cli/.prettierrc rename to packages/implementations/cli/.prettierrc diff --git a/packages/cli/LICENSE.md b/packages/implementations/cli/LICENSE.md similarity index 100% rename from packages/cli/LICENSE.md rename to packages/implementations/cli/LICENSE.md diff --git a/packages/cli/README.md b/packages/implementations/cli/README.md similarity index 97% rename from packages/cli/README.md rename to packages/implementations/cli/README.md index c98586d..1ca832b 100644 --- a/packages/cli/README.md +++ b/packages/implementations/cli/README.md @@ -1,4 +1,4 @@ -# GPT Turbo - CLI +# GPT Turbo - Implementation - CLI
@@ -9,7 +9,7 @@ A CLI that interacts with the gpt-turbo library

- GPT Turbo Demo + GPT Turbo Demo

## Installation diff --git a/packages/cli/demo.gif b/packages/implementations/cli/demo.gif similarity index 100% rename from packages/cli/demo.gif rename to packages/implementations/cli/demo.gif diff --git a/packages/cli/nodemon.json b/packages/implementations/cli/nodemon.json similarity index 100% rename from packages/cli/nodemon.json rename to packages/implementations/cli/nodemon.json diff --git a/packages/cli/package.json b/packages/implementations/cli/package.json similarity index 96% rename from packages/cli/package.json rename to packages/implementations/cli/package.json index 239a3a3..f9106c0 100644 --- a/packages/cli/package.json +++ b/packages/implementations/cli/package.json @@ -8,6 +8,7 @@ "lint": "eslint --ext .ts,.tsx src", "lint:strict": "npm run lint -- --max-warnings 0", "lint:fix": "npm run lint -- --fix", + "tscheck": "tsc --noEmit", "build": "npm run lint:strict && rimraf dist && tsc -p tsconfig.build.json && copyfiles -u 1 -e \"src/**/*.tsx\" \"src/**/*.ts\" \"src/**/*\" dist", "gpt-turbo": "nodemon", "ig": "npm run build && npm i -g ." @@ -62,6 +63,7 @@ "dependencies": { "dotenv": "^16.0.3", "gpt-turbo": "^4.5.0", + "gpt-turbo-plugin-stats": "^4.5.0", "ink": "^4.0.0", "ink-spinner": "^5.0.0", "ink-text-input": "^5.0.0", diff --git a/packages/cli/src/components/ApiKeyWarning.tsx b/packages/implementations/cli/src/components/ApiKeyWarning.tsx similarity index 100% rename from packages/cli/src/components/ApiKeyWarning.tsx rename to packages/implementations/cli/src/components/ApiKeyWarning.tsx diff --git a/packages/cli/src/components/App.tsx b/packages/implementations/cli/src/components/App.tsx similarity index 93% rename from packages/cli/src/components/App.tsx rename to packages/implementations/cli/src/components/App.tsx index 78d4548..fdb29d2 100644 --- a/packages/cli/src/components/App.tsx +++ b/packages/implementations/cli/src/components/App.tsx @@ -51,12 +51,14 @@ export default ({ if ((!apiKey && !dry) || loadFile) return; setConversation( new Conversation({ - dry, - model, - apiKey, - context, - disableModeration, - stream, + config: { + dry, + model, + apiKey, + context, + disableModeration, + stream, + }, }) ); }, [ diff --git a/packages/cli/src/components/BoxTitle.tsx b/packages/implementations/cli/src/components/BoxTitle.tsx similarity index 100% rename from packages/cli/src/components/BoxTitle.tsx rename to packages/implementations/cli/src/components/BoxTitle.tsx diff --git a/packages/cli/src/components/CenteredText.tsx b/packages/implementations/cli/src/components/CenteredText.tsx similarity index 100% rename from packages/cli/src/components/CenteredText.tsx rename to packages/implementations/cli/src/components/CenteredText.tsx diff --git a/packages/cli/src/components/CommandsBox.tsx b/packages/implementations/cli/src/components/CommandsBox.tsx similarity index 100% rename from packages/cli/src/components/CommandsBox.tsx rename to packages/implementations/cli/src/components/CommandsBox.tsx diff --git a/packages/cli/src/components/ConversationBox.tsx b/packages/implementations/cli/src/components/ConversationBox.tsx similarity index 94% rename from packages/cli/src/components/ConversationBox.tsx rename to packages/implementations/cli/src/components/ConversationBox.tsx index 2164e74..3a4a5a9 100644 --- a/packages/cli/src/components/ConversationBox.tsx +++ b/packages/implementations/cli/src/components/ConversationBox.tsx @@ -22,7 +22,7 @@ export default () => { null ); const [messages, setMessages] = React.useState( - conversation?.getMessages() ?? [] + conversation?.history.getMessages() ?? [] ); const pageableMessages = React.useMemo(() => { @@ -98,7 +98,7 @@ export default () => { if (!conversation) return; const unsubscribeMessageUpdate: (() => void)[] = []; const unsubscribeMessageStreaming: (() => void)[] = []; - const unsubscribeMessageAdded = conversation.onMessageAdded( + const unsubscribeMessageAdded = conversation.history.onMessageAdded( (message) => { if (message.role === "system") return; setPendingMessage(null); @@ -107,13 +107,13 @@ export default () => { if (message.role !== "assistant") return; unsubscribeMessageUpdate.push( - message.onMessageUpdate( + message.onUpdate( () => setMessages((messages) => [...messages]) // Force re-render by creating a new array ) ); unsubscribeMessageStreaming.push( - message.onMessageStreamingUpdate((streaming) => { + message.onStreamingUpdate((streaming) => { setIsStreaming(streaming); }) ); @@ -129,7 +129,7 @@ export default () => { React.useEffect(() => { if (!conversation) return; - return conversation.onMessageRemoved((message) => { + return conversation.history.onMessageRemoved((message) => { setMessages((messages) => messages.filter((m) => m.id !== message.id) ); diff --git a/packages/cli/src/components/DebugBox.tsx b/packages/implementations/cli/src/components/DebugBox.tsx similarity index 100% rename from packages/cli/src/components/DebugBox.tsx rename to packages/implementations/cli/src/components/DebugBox.tsx diff --git a/packages/cli/src/components/Message.tsx b/packages/implementations/cli/src/components/Message.tsx similarity index 100% rename from packages/cli/src/components/Message.tsx rename to packages/implementations/cli/src/components/Message.tsx diff --git a/packages/cli/src/components/Prompt.tsx b/packages/implementations/cli/src/components/Prompt.tsx similarity index 96% rename from packages/cli/src/components/Prompt.tsx rename to packages/implementations/cli/src/components/Prompt.tsx index 2609159..3ec8c5b 100644 --- a/packages/cli/src/components/Prompt.tsx +++ b/packages/implementations/cli/src/components/Prompt.tsx @@ -1,4 +1,4 @@ -import { getMessageSize } from "gpt-turbo"; +import { getMessageSize } from "gpt-turbo-plugin-stats"; import { Box, Text } from "ink"; import Spinner from "ink-spinner"; import TextInput from "ink-text-input"; diff --git a/packages/cli/src/components/UsageBox.tsx b/packages/implementations/cli/src/components/UsageBox.tsx similarity index 58% rename from packages/cli/src/components/UsageBox.tsx rename to packages/implementations/cli/src/components/UsageBox.tsx index 98ec2d9..b91bdcc 100644 --- a/packages/cli/src/components/UsageBox.tsx +++ b/packages/implementations/cli/src/components/UsageBox.tsx @@ -2,25 +2,39 @@ import { Box, Text } from "ink"; import React from "react"; import useConversationManager from "../hooks/useConversationManager.js"; import BoxTitle from "./BoxTitle.js"; +import { statsPluginName } from "gpt-turbo-plugin-stats"; const SEPARATOR = ": "; export default () => { const [, forceUpdate] = React.useReducer((x) => x + 1, 0); const { conversation } = useConversationManager(); - const cumulativeSize = conversation?.getCumulativeSize() ?? 0; - const cumulativeCost = conversation?.getCumulativeCost() ?? 0; - const size = conversation?.getSize() ?? 0; - const cost = conversation?.getCost() ?? 0; + const stats = + conversation?.plugins.getPluginOutput(statsPluginName) ?? null; - const usages = React.useMemo<{ label: string; value: string }[]>( + const usages: { + label: string; + value: string; + }[] = React.useMemo( () => [ - { label: "Cumul. Tokens", value: "" + cumulativeSize }, - { label: "Cumul. Cost", value: "$" + cumulativeCost.toFixed(5) }, - { label: "Convo. Tokens", value: "" + size }, - { label: "Convo. Cost", value: "$" + cost.toFixed(5) }, + { + label: "Cumul. Size", + value: `${stats?.cumulativeSize ?? 0} tkns`, + }, + { + label: "Cumul. Cost", + value: `$${stats?.cumulativeCost.toFixed(5) ?? 0}`, + }, + { + label: "Convo. Size", + value: `${stats?.size ?? 0} tkns`, + }, + { + label: "Convo. Cost", + value: `$${stats?.cost.toFixed(5) ?? 0}`, + }, ], - [cost, cumulativeCost, cumulativeSize, size] + [stats?.cost, stats?.cumulativeCost, stats?.cumulativeSize, stats?.size] ); const minWidth = React.useMemo( @@ -34,12 +48,14 @@ export default () => { React.useEffect(() => { if (!conversation) return; const offs: (() => void)[] = []; - const offMessageAdded = conversation.onMessageAdded((message) => { - offs.push( - message.onMessageStreamingUpdate(() => forceUpdate()), - message.onMessageUpdate(() => forceUpdate()) - ); - }); + const offMessageAdded = conversation.history.onMessageAdded( + (message) => { + offs.push( + message.onStreamingUpdate(() => forceUpdate()), + message.onUpdate(() => forceUpdate()) + ); + } + ); return () => { offs.forEach((off) => off()); diff --git a/packages/cli/src/config/constants.ts b/packages/implementations/cli/src/config/constants.ts similarity index 100% rename from packages/cli/src/config/constants.ts rename to packages/implementations/cli/src/config/constants.ts diff --git a/packages/cli/src/config/env.ts b/packages/implementations/cli/src/config/env.ts similarity index 100% rename from packages/cli/src/config/env.ts rename to packages/implementations/cli/src/config/env.ts diff --git a/packages/implementations/cli/src/config/gpt-turbo.ts b/packages/implementations/cli/src/config/gpt-turbo.ts new file mode 100644 index 0000000..60d1755 --- /dev/null +++ b/packages/implementations/cli/src/config/gpt-turbo.ts @@ -0,0 +1,10 @@ +import { Conversation } from "gpt-turbo"; +import statsPlugin from "gpt-turbo-plugin-stats"; + +const globalPlugins = [statsPlugin]; +Conversation.globalPlugins = [statsPlugin]; +declare module "gpt-turbo" { + export interface ConversationGlobalPluginsOverride { + globalPlugins: typeof globalPlugins; + } +} diff --git a/packages/cli/src/contexts/AppFocusContext.ts b/packages/implementations/cli/src/contexts/AppFocusContext.ts similarity index 100% rename from packages/cli/src/contexts/AppFocusContext.ts rename to packages/implementations/cli/src/contexts/AppFocusContext.ts diff --git a/packages/cli/src/contexts/ConfigContext.ts b/packages/implementations/cli/src/contexts/ConfigContext.ts similarity index 100% rename from packages/cli/src/contexts/ConfigContext.ts rename to packages/implementations/cli/src/contexts/ConfigContext.ts diff --git a/packages/cli/src/contexts/ConversationManagerContext.ts b/packages/implementations/cli/src/contexts/ConversationManagerContext.ts similarity index 100% rename from packages/cli/src/contexts/ConversationManagerContext.ts rename to packages/implementations/cli/src/contexts/ConversationManagerContext.ts diff --git a/packages/cli/src/contexts/DebugContext.ts b/packages/implementations/cli/src/contexts/DebugContext.ts similarity index 100% rename from packages/cli/src/contexts/DebugContext.ts rename to packages/implementations/cli/src/contexts/DebugContext.ts diff --git a/packages/cli/src/contexts/PersistenceContext.ts b/packages/implementations/cli/src/contexts/PersistenceContext.ts similarity index 100% rename from packages/cli/src/contexts/PersistenceContext.ts rename to packages/implementations/cli/src/contexts/PersistenceContext.ts diff --git a/packages/cli/src/contexts/providers/AppFocusProvider.tsx b/packages/implementations/cli/src/contexts/providers/AppFocusProvider.tsx similarity index 100% rename from packages/cli/src/contexts/providers/AppFocusProvider.tsx rename to packages/implementations/cli/src/contexts/providers/AppFocusProvider.tsx diff --git a/packages/cli/src/contexts/providers/ConfigProvider.tsx b/packages/implementations/cli/src/contexts/providers/ConfigProvider.tsx similarity index 100% rename from packages/cli/src/contexts/providers/ConfigProvider.tsx rename to packages/implementations/cli/src/contexts/providers/ConfigProvider.tsx diff --git a/packages/cli/src/contexts/providers/ConversationManagerProvider.tsx b/packages/implementations/cli/src/contexts/providers/ConversationManagerProvider.tsx similarity index 100% rename from packages/cli/src/contexts/providers/ConversationManagerProvider.tsx rename to packages/implementations/cli/src/contexts/providers/ConversationManagerProvider.tsx diff --git a/packages/cli/src/contexts/providers/DebugProvider.tsx b/packages/implementations/cli/src/contexts/providers/DebugProvider.tsx similarity index 100% rename from packages/cli/src/contexts/providers/DebugProvider.tsx rename to packages/implementations/cli/src/contexts/providers/DebugProvider.tsx diff --git a/packages/cli/src/contexts/providers/PersistenceProvider.tsx b/packages/implementations/cli/src/contexts/providers/PersistenceProvider.tsx similarity index 83% rename from packages/cli/src/contexts/providers/PersistenceProvider.tsx rename to packages/implementations/cli/src/contexts/providers/PersistenceProvider.tsx index 277860e..e72605e 100644 --- a/packages/cli/src/contexts/providers/PersistenceProvider.tsx +++ b/packages/implementations/cli/src/contexts/providers/PersistenceProvider.tsx @@ -44,7 +44,7 @@ export default ({ children }: PersistenceProviderProps) => { try { const data = fs.readFileSync(loadFile, "utf8"); const json = JSON.parse(data); - const newConversation = await Conversation.fromJSON(json); + const newConversation = Conversation.fromJSON(json); setConversation(newConversation); } catch (e) { console.error(e); @@ -63,24 +63,26 @@ export default ({ children }: PersistenceProviderProps) => { const attachMessageListeners = () => (message: Message) => { messageOffs.push( - message.onMessageStreamingStop(() => { + message.onStreamingStop(() => { save(); }), - message.onMessageUpdate((_, m) => { + message.onUpdate((_, m) => { if (m.isStreaming) return; save(); }) ); }; - conversation.getMessages().forEach(attachMessageListeners()); + conversation.history.getMessages().forEach(attachMessageListeners()); - const offMessageAdded = conversation.onMessageAdded((message) => { - save(); - attachMessageListeners()(message); - }); + const offMessageAdded = conversation.history.onMessageAdded( + (message) => { + save(); + attachMessageListeners()(message); + } + ); - const offMessageRemoved = conversation.onMessageRemoved(() => { + const offMessageRemoved = conversation.history.onMessageRemoved(() => { save(); }); diff --git a/packages/cli/src/contexts/providers/index.tsx b/packages/implementations/cli/src/contexts/providers/index.tsx similarity index 100% rename from packages/cli/src/contexts/providers/index.tsx rename to packages/implementations/cli/src/contexts/providers/index.tsx diff --git a/packages/cli/src/hooks/useAppFocus.ts b/packages/implementations/cli/src/hooks/useAppFocus.ts similarity index 100% rename from packages/cli/src/hooks/useAppFocus.ts rename to packages/implementations/cli/src/hooks/useAppFocus.ts diff --git a/packages/cli/src/hooks/useConfig.ts b/packages/implementations/cli/src/hooks/useConfig.ts similarity index 100% rename from packages/cli/src/hooks/useConfig.ts rename to packages/implementations/cli/src/hooks/useConfig.ts diff --git a/packages/cli/src/hooks/useConversationManager.ts b/packages/implementations/cli/src/hooks/useConversationManager.ts similarity index 100% rename from packages/cli/src/hooks/useConversationManager.ts rename to packages/implementations/cli/src/hooks/useConversationManager.ts diff --git a/packages/cli/src/hooks/useCustomFocus.ts b/packages/implementations/cli/src/hooks/useCustomFocus.ts similarity index 100% rename from packages/cli/src/hooks/useCustomFocus.ts rename to packages/implementations/cli/src/hooks/useCustomFocus.ts diff --git a/packages/cli/src/hooks/useCycle.ts b/packages/implementations/cli/src/hooks/useCycle.ts similarity index 100% rename from packages/cli/src/hooks/useCycle.ts rename to packages/implementations/cli/src/hooks/useCycle.ts diff --git a/packages/cli/src/hooks/useDebug.ts b/packages/implementations/cli/src/hooks/useDebug.ts similarity index 100% rename from packages/cli/src/hooks/useDebug.ts rename to packages/implementations/cli/src/hooks/useDebug.ts diff --git a/packages/cli/src/hooks/useElementDimensions.ts b/packages/implementations/cli/src/hooks/useElementDimensions.ts similarity index 100% rename from packages/cli/src/hooks/useElementDimensions.ts rename to packages/implementations/cli/src/hooks/useElementDimensions.ts diff --git a/packages/cli/src/hooks/usePagedMessages.ts b/packages/implementations/cli/src/hooks/usePagedMessages.ts similarity index 100% rename from packages/cli/src/hooks/usePagedMessages.ts rename to packages/implementations/cli/src/hooks/usePagedMessages.ts diff --git a/packages/cli/src/hooks/usePersistence.ts b/packages/implementations/cli/src/hooks/usePersistence.ts similarity index 100% rename from packages/cli/src/hooks/usePersistence.ts rename to packages/implementations/cli/src/hooks/usePersistence.ts diff --git a/packages/cli/src/hooks/useStdoutDimensions.ts b/packages/implementations/cli/src/hooks/useStdoutDimensions.ts similarity index 100% rename from packages/cli/src/hooks/useStdoutDimensions.ts rename to packages/implementations/cli/src/hooks/useStdoutDimensions.ts diff --git a/packages/cli/src/index.tsx b/packages/implementations/cli/src/index.tsx similarity index 99% rename from packages/cli/src/index.tsx rename to packages/implementations/cli/src/index.tsx index f2ade23..7353aee 100644 --- a/packages/cli/src/index.tsx +++ b/packages/implementations/cli/src/index.tsx @@ -1,5 +1,6 @@ #!/usr/bin/env node +import "./config/gpt-turbo.js"; import { GPTTURBO_APIKEY, GPTTURBO_CONTEXT, diff --git a/packages/cli/src/utils/getMessageHeight.ts b/packages/implementations/cli/src/utils/getMessageHeight.ts similarity index 100% rename from packages/cli/src/utils/getMessageHeight.ts rename to packages/implementations/cli/src/utils/getMessageHeight.ts diff --git a/packages/cli/src/utils/makeNotImplemented.ts b/packages/implementations/cli/src/utils/makeNotImplemented.ts similarity index 100% rename from packages/cli/src/utils/makeNotImplemented.ts rename to packages/implementations/cli/src/utils/makeNotImplemented.ts diff --git a/packages/cli/src/utils/splitMessage.ts b/packages/implementations/cli/src/utils/splitMessage.ts similarity index 100% rename from packages/cli/src/utils/splitMessage.ts rename to packages/implementations/cli/src/utils/splitMessage.ts diff --git a/packages/cli/tsconfig.build.json b/packages/implementations/cli/tsconfig.build.json similarity index 100% rename from packages/cli/tsconfig.build.json rename to packages/implementations/cli/tsconfig.build.json diff --git a/packages/cli/tsconfig.json b/packages/implementations/cli/tsconfig.json similarity index 100% rename from packages/cli/tsconfig.json rename to packages/implementations/cli/tsconfig.json diff --git a/packages/discord/.env.example b/packages/implementations/discord/.env.example similarity index 96% rename from packages/discord/.env.example rename to packages/implementations/discord/.env.example index d2bb47f..1e33c18 100644 --- a/packages/discord/.env.example +++ b/packages/implementations/discord/.env.example @@ -20,7 +20,7 @@ ALLOW_DMS="" # Warning: This is a priviledged intent, and you must enable it in the Discord Developer Portal for your bot. The bot will crash at startup if this is set to "true" and the intent is not enabled on the portal. USE_MESSAGE_CONTENT_INTENT="" -### GPT TURBO ### +######################### GPT Turbo ######################### # All options for GPT Turbo below # Your OpenAI API key. Leave empty for dry run mode. @@ -52,7 +52,7 @@ POSTGRES_SCHEMA="" # Optional. If not specified, defaults to "public". MYSQL_CONNECTION_STRING="" ######################### WHITELISTING ######################### -# Ommit ALL of these to allow anyone to use the bot. +# Omit ALL of these to allow anyone to use the bot. # Set ANY of these, whitelist checking will be enabled and only commands that meet the whitelist criteria will be accepted. # Comma-separated list of whitelisted user IDs. They may use the bot anywhere. diff --git a/packages/discord/.eslintrc.cjs b/packages/implementations/discord/.eslintrc.cjs similarity index 97% rename from packages/discord/.eslintrc.cjs rename to packages/implementations/discord/.eslintrc.cjs index 0456c92..d4873fb 100644 --- a/packages/discord/.eslintrc.cjs +++ b/packages/implementations/discord/.eslintrc.cjs @@ -30,6 +30,7 @@ module.exports = { "@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/no-this-alias": "off", "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/await-thenable": "warn", "max-classes-per-file": "off", "no-useless-constructor": "off", "class-methods-use-this": "off", diff --git a/packages/discord/.gitignore b/packages/implementations/discord/.gitignore similarity index 100% rename from packages/discord/.gitignore rename to packages/implementations/discord/.gitignore diff --git a/packages/discord/.prettierrc b/packages/implementations/discord/.prettierrc similarity index 100% rename from packages/discord/.prettierrc rename to packages/implementations/discord/.prettierrc diff --git a/packages/discord/LICENSE.md b/packages/implementations/discord/LICENSE.md similarity index 100% rename from packages/discord/LICENSE.md rename to packages/implementations/discord/LICENSE.md diff --git a/packages/discord/README.md b/packages/implementations/discord/README.md similarity index 99% rename from packages/discord/README.md rename to packages/implementations/discord/README.md index 0e98dbc..897002b 100644 --- a/packages/discord/README.md +++ b/packages/implementations/discord/README.md @@ -1,4 +1,4 @@ -# GPT Turbo - Discord +# GPT Turbo - Implementation - Discord
diff --git a/packages/discord/package.json b/packages/implementations/discord/package.json similarity index 94% rename from packages/discord/package.json rename to packages/implementations/discord/package.json index a06c7d9..78eab96 100644 --- a/packages/discord/package.json +++ b/packages/implementations/discord/package.json @@ -9,6 +9,7 @@ "lint": "eslint --ext .ts src", "lint:strict": "npm run lint -- --max-warnings 0", "lint:fix": "npm run lint -- --fix", + "tscheck": "tsc --noEmit", "build": "npm run lint:strict && rimraf dist && tsc -p tsconfig.build.json && copyfiles -u 1 -e \"src/**/*.ts\" \"src/**/*\" dist", "start": "node dist/index.js", "dev": "tsx watch --no-cache src/index.ts", @@ -37,7 +38,7 @@ "discordbot" ], "author": "Tristan Chin ", - "homepage": "https://github.com/maxijonson/gpt-turbo/tree/develop/packages/discord#readme", + "homepage": "https://github.com/maxijonson/gpt-turbo/tree/develop/packages/implementations/discord#readme", "repository": { "type": "git", "url": "git+https://github.com/maxijonson/gpt-turbo.git" @@ -69,6 +70,7 @@ "discord.js": "^14.9.0", "dotenv": "^16.0.3", "gpt-turbo": "^4.5.0", + "gpt-turbo-plugin-stats": "^4.5.0", "keyv": "^4.5.2" } } diff --git a/packages/discord/src/GPTTurboClient.ts b/packages/implementations/discord/src/GPTTurboClient.ts similarity index 100% rename from packages/discord/src/GPTTurboClient.ts rename to packages/implementations/discord/src/GPTTurboClient.ts diff --git a/packages/discord/src/access-rules/blacklist.ts b/packages/implementations/discord/src/access-rules/blacklist.ts similarity index 100% rename from packages/discord/src/access-rules/blacklist.ts rename to packages/implementations/discord/src/access-rules/blacklist.ts diff --git a/packages/discord/src/access-rules/bot.ts b/packages/implementations/discord/src/access-rules/bot.ts similarity index 100% rename from packages/discord/src/access-rules/bot.ts rename to packages/implementations/discord/src/access-rules/bot.ts diff --git a/packages/discord/src/access-rules/dm.ts b/packages/implementations/discord/src/access-rules/dm.ts similarity index 100% rename from packages/discord/src/access-rules/dm.ts rename to packages/implementations/discord/src/access-rules/dm.ts diff --git a/packages/discord/src/access-rules/whitelist.ts b/packages/implementations/discord/src/access-rules/whitelist.ts similarity index 100% rename from packages/discord/src/access-rules/whitelist.ts rename to packages/implementations/discord/src/access-rules/whitelist.ts diff --git a/packages/discord/src/commands/admin.ts b/packages/implementations/discord/src/commands/admin.ts similarity index 100% rename from packages/discord/src/commands/admin.ts rename to packages/implementations/discord/src/commands/admin.ts diff --git a/packages/discord/src/commands/ping.ts b/packages/implementations/discord/src/commands/ping.ts similarity index 100% rename from packages/discord/src/commands/ping.ts rename to packages/implementations/discord/src/commands/ping.ts diff --git a/packages/discord/src/commands/usage.ts b/packages/implementations/discord/src/commands/usage.ts similarity index 100% rename from packages/discord/src/commands/usage.ts rename to packages/implementations/discord/src/commands/usage.ts diff --git a/packages/discord/src/components/RoleSelect.ts b/packages/implementations/discord/src/components/RoleSelect.ts similarity index 100% rename from packages/discord/src/components/RoleSelect.ts rename to packages/implementations/discord/src/components/RoleSelect.ts diff --git a/packages/discord/src/components/UserIdButton.ts b/packages/implementations/discord/src/components/UserIdButton.ts similarity index 100% rename from packages/discord/src/components/UserIdButton.ts rename to packages/implementations/discord/src/components/UserIdButton.ts diff --git a/packages/discord/src/components/UserSelect.ts b/packages/implementations/discord/src/components/UserSelect.ts similarity index 100% rename from packages/discord/src/components/UserSelect.ts rename to packages/implementations/discord/src/components/UserSelect.ts diff --git a/packages/discord/src/config/constants.ts b/packages/implementations/discord/src/config/constants.ts similarity index 100% rename from packages/discord/src/config/constants.ts rename to packages/implementations/discord/src/config/constants.ts diff --git a/packages/discord/src/config/env.ts b/packages/implementations/discord/src/config/env.ts similarity index 100% rename from packages/discord/src/config/env.ts rename to packages/implementations/discord/src/config/env.ts diff --git a/packages/implementations/discord/src/config/gpt-turbo.ts b/packages/implementations/discord/src/config/gpt-turbo.ts new file mode 100644 index 0000000..60d1755 --- /dev/null +++ b/packages/implementations/discord/src/config/gpt-turbo.ts @@ -0,0 +1,10 @@ +import { Conversation } from "gpt-turbo"; +import statsPlugin from "gpt-turbo-plugin-stats"; + +const globalPlugins = [statsPlugin]; +Conversation.globalPlugins = [statsPlugin]; +declare module "gpt-turbo" { + export interface ConversationGlobalPluginsOverride { + globalPlugins: typeof globalPlugins; + } +} diff --git a/packages/discord/src/events/interactionCreate.ts b/packages/implementations/discord/src/events/interactionCreate.ts similarity index 100% rename from packages/discord/src/events/interactionCreate.ts rename to packages/implementations/discord/src/events/interactionCreate.ts diff --git a/packages/discord/src/events/messageCreate.ts b/packages/implementations/discord/src/events/messageCreate.ts similarity index 100% rename from packages/discord/src/events/messageCreate.ts rename to packages/implementations/discord/src/events/messageCreate.ts diff --git a/packages/discord/src/events/ready.ts b/packages/implementations/discord/src/events/ready.ts similarity index 100% rename from packages/discord/src/events/ready.ts rename to packages/implementations/discord/src/events/ready.ts diff --git a/packages/discord/src/exceptions/BotException.ts b/packages/implementations/discord/src/exceptions/BotException.ts similarity index 100% rename from packages/discord/src/exceptions/BotException.ts rename to packages/implementations/discord/src/exceptions/BotException.ts diff --git a/packages/discord/src/exceptions/UnauthorizedException.ts b/packages/implementations/discord/src/exceptions/UnauthorizedException.ts similarity index 100% rename from packages/discord/src/exceptions/UnauthorizedException.ts rename to packages/implementations/discord/src/exceptions/UnauthorizedException.ts diff --git a/packages/discord/src/index.ts b/packages/implementations/discord/src/index.ts similarity index 96% rename from packages/discord/src/index.ts rename to packages/implementations/discord/src/index.ts index 0b62b64..61cef5f 100644 --- a/packages/discord/src/index.ts +++ b/packages/implementations/discord/src/index.ts @@ -6,6 +6,7 @@ import { } from "discord.js"; import GPTTurboClient from "./GPTTurboClient.js"; import { USE_MESSAGE_CONTENT_INTENT } from "./config/env.js"; +import "./config/gpt-turbo.js"; const intents = [ GatewayIntentBits.Guilds, diff --git a/packages/discord/src/interaction-handlers/InteractionHandler.ts b/packages/implementations/discord/src/interaction-handlers/InteractionHandler.ts similarity index 100% rename from packages/discord/src/interaction-handlers/InteractionHandler.ts rename to packages/implementations/discord/src/interaction-handlers/InteractionHandler.ts diff --git a/packages/discord/src/interaction-handlers/SlashCommandHandler.ts b/packages/implementations/discord/src/interaction-handlers/SlashCommandHandler.ts similarity index 100% rename from packages/discord/src/interaction-handlers/SlashCommandHandler.ts rename to packages/implementations/discord/src/interaction-handlers/SlashCommandHandler.ts diff --git a/packages/discord/src/interaction-handlers/SnowflakeModalHandler.ts b/packages/implementations/discord/src/interaction-handlers/SnowflakeModalHandler.ts similarity index 100% rename from packages/discord/src/interaction-handlers/SnowflakeModalHandler.ts rename to packages/implementations/discord/src/interaction-handlers/SnowflakeModalHandler.ts diff --git a/packages/discord/src/interaction-handlers/admin/quota/AdminQuotaMenuHandler.ts b/packages/implementations/discord/src/interaction-handlers/admin/quota/AdminQuotaMenuHandler.ts similarity index 100% rename from packages/discord/src/interaction-handlers/admin/quota/AdminQuotaMenuHandler.ts rename to packages/implementations/discord/src/interaction-handlers/admin/quota/AdminQuotaMenuHandler.ts diff --git a/packages/discord/src/interaction-handlers/admin/quota/AdminQuotaRoleHandler.ts b/packages/implementations/discord/src/interaction-handlers/admin/quota/AdminQuotaRoleHandler.ts similarity index 100% rename from packages/discord/src/interaction-handlers/admin/quota/AdminQuotaRoleHandler.ts rename to packages/implementations/discord/src/interaction-handlers/admin/quota/AdminQuotaRoleHandler.ts diff --git a/packages/discord/src/interaction-handlers/admin/quota/AdminQuotaSnowflakeHandler.ts b/packages/implementations/discord/src/interaction-handlers/admin/quota/AdminQuotaSnowflakeHandler.ts similarity index 100% rename from packages/discord/src/interaction-handlers/admin/quota/AdminQuotaSnowflakeHandler.ts rename to packages/implementations/discord/src/interaction-handlers/admin/quota/AdminQuotaSnowflakeHandler.ts diff --git a/packages/discord/src/interaction-handlers/admin/quota/AdminQuotaUserHandler.ts b/packages/implementations/discord/src/interaction-handlers/admin/quota/AdminQuotaUserHandler.ts similarity index 100% rename from packages/discord/src/interaction-handlers/admin/quota/AdminQuotaUserHandler.ts rename to packages/implementations/discord/src/interaction-handlers/admin/quota/AdminQuotaUserHandler.ts diff --git a/packages/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetAllHandler.ts b/packages/implementations/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetAllHandler.ts similarity index 100% rename from packages/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetAllHandler.ts rename to packages/implementations/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetAllHandler.ts diff --git a/packages/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetMenuHandler.ts b/packages/implementations/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetMenuHandler.ts similarity index 100% rename from packages/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetMenuHandler.ts rename to packages/implementations/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetMenuHandler.ts diff --git a/packages/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetUserHandler.ts b/packages/implementations/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetUserHandler.ts similarity index 100% rename from packages/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetUserHandler.ts rename to packages/implementations/discord/src/interaction-handlers/admin/usage-reset/AdminUsageResetUserHandler.ts diff --git a/packages/discord/src/managers/AccessRuleManager.ts b/packages/implementations/discord/src/managers/AccessRuleManager.ts similarity index 100% rename from packages/discord/src/managers/AccessRuleManager.ts rename to packages/implementations/discord/src/managers/AccessRuleManager.ts diff --git a/packages/discord/src/managers/CommandManager.ts b/packages/implementations/discord/src/managers/CommandManager.ts similarity index 100% rename from packages/discord/src/managers/CommandManager.ts rename to packages/implementations/discord/src/managers/CommandManager.ts diff --git a/packages/discord/src/managers/ConversationManager.ts b/packages/implementations/discord/src/managers/ConversationManager.ts similarity index 82% rename from packages/discord/src/managers/ConversationManager.ts rename to packages/implementations/discord/src/managers/ConversationManager.ts index d5d0ba1..1c78d6a 100644 --- a/packages/discord/src/managers/ConversationManager.ts +++ b/packages/implementations/discord/src/managers/ConversationManager.ts @@ -3,6 +3,7 @@ import getConversationConfig from "../utils/getConversationConfig.js"; import BotException from "../exceptions/BotException.js"; import QuotaManager from "./QuotaManager.js"; import { ConversationUser } from "../utils/types.js"; +import { statsPluginName } from "gpt-turbo-plugin-stats"; export default class ConversationManager { constructor(private readonly quotaManager: QuotaManager) {} @@ -12,12 +13,14 @@ export default class ConversationManager { userId: string ) { const user: ConversationUser = `discord-${userId}`; - const conversation = await Conversation.fromMessages( - this.getAlternatedMessages(messages), - getConversationConfig({ + const conversation = new Conversation({ + history: { + messages: this.getAlternatedMessages(messages), + }, + config: getConversationConfig({ user, - }) - ); + }), + }); if (!(await this.quotaManager.isConversationAllowed(conversation))) { throw new BotException( @@ -26,7 +29,8 @@ export default class ConversationManager { } const quota = await this.quotaManager.getQuota(user); const usage = await this.quotaManager.getUsage(user); - const minUsage = usage + conversation.getSize(); + const stats = conversation.plugins.getPluginOutput(statsPluginName); + const minUsage = usage + stats.size; const maxTokens = Math.min(quota - minUsage, 1000); if (maxTokens <= 0) { @@ -43,7 +47,7 @@ export default class ConversationManager { if (!response.isCompletion()) throw new Error("Not a completion"); try { - await conversation.addAssistantMessage(response.content); + conversation.history.addAssistantMessage(response.content); } finally { await this.quotaManager.logUsage(conversation); } diff --git a/packages/discord/src/managers/EventManager.ts b/packages/implementations/discord/src/managers/EventManager.ts similarity index 100% rename from packages/discord/src/managers/EventManager.ts rename to packages/implementations/discord/src/managers/EventManager.ts diff --git a/packages/discord/src/managers/QuotaManager.ts b/packages/implementations/discord/src/managers/QuotaManager.ts similarity index 96% rename from packages/discord/src/managers/QuotaManager.ts rename to packages/implementations/discord/src/managers/QuotaManager.ts index ed1c8a3..ef9e352 100644 --- a/packages/discord/src/managers/QuotaManager.ts +++ b/packages/implementations/discord/src/managers/QuotaManager.ts @@ -12,6 +12,7 @@ import isValidSnowflake from "../utils/isValidSnowflake.js"; import BotException from "../exceptions/BotException.js"; import GPTTurboClient from "../GPTTurboClient.js"; import { Role } from "discord.js"; +import { statsPluginName } from "gpt-turbo-plugin-stats"; export type DbType = "mongodb" | "mysql" | "postgres"; export default class QuotaManager< @@ -210,25 +211,27 @@ export default class QuotaManager< conversation: Conversation ): Promise { if (!this.isEnabled()) return true; - const { user } = conversation.getConfig(); + const { user } = conversation.config.getConfig(); if (!user) throw new Error("No user found in conversation config"); const userId = this.parseSnowflake(user); const quota = await this.getQuota(userId); const usage = await this.getUsage(userId); + const stats = conversation.plugins.getPluginOutput(statsPluginName); - return usage + conversation.getSize() < quota; + return usage + stats.size < quota; } public async logUsage(conversation: Conversation) { if (!this.isEnabled()) return; - const { user } = conversation.getConfig(); + const { user } = conversation.config.getConfig(); if (!user) throw new Error("No user found in conversation config"); const userId = this.parseSnowflake(user); const usage = await this.getUsage(userId); + const stats = conversation.plugins.getPluginOutput(statsPluginName); - await this.usages.set(userId, usage + conversation.getSize()); + await this.usages.set(userId, usage + stats.size); } private parseSnowflake(snowflake: string) { diff --git a/packages/discord/src/message-handlers/DMReplyHandler.ts b/packages/implementations/discord/src/message-handlers/DMReplyHandler.ts similarity index 100% rename from packages/discord/src/message-handlers/DMReplyHandler.ts rename to packages/implementations/discord/src/message-handlers/DMReplyHandler.ts diff --git a/packages/discord/src/message-handlers/EmptyPromptHandler.ts b/packages/implementations/discord/src/message-handlers/EmptyPromptHandler.ts similarity index 100% rename from packages/discord/src/message-handlers/EmptyPromptHandler.ts rename to packages/implementations/discord/src/message-handlers/EmptyPromptHandler.ts diff --git a/packages/discord/src/message-handlers/GuildReplyHandler.ts b/packages/implementations/discord/src/message-handlers/GuildReplyHandler.ts similarity index 100% rename from packages/discord/src/message-handlers/GuildReplyHandler.ts rename to packages/implementations/discord/src/message-handlers/GuildReplyHandler.ts diff --git a/packages/discord/src/message-handlers/MessageHandler.ts b/packages/implementations/discord/src/message-handlers/MessageHandler.ts similarity index 100% rename from packages/discord/src/message-handlers/MessageHandler.ts rename to packages/implementations/discord/src/message-handlers/MessageHandler.ts diff --git a/packages/discord/src/message-handlers/NewConversationHandler.ts b/packages/implementations/discord/src/message-handlers/NewConversationHandler.ts similarity index 100% rename from packages/discord/src/message-handlers/NewConversationHandler.ts rename to packages/implementations/discord/src/message-handlers/NewConversationHandler.ts diff --git a/packages/discord/src/message-handlers/ThreadMessageHandler.ts b/packages/implementations/discord/src/message-handlers/ThreadMessageHandler.ts similarity index 100% rename from packages/discord/src/message-handlers/ThreadMessageHandler.ts rename to packages/implementations/discord/src/message-handlers/ThreadMessageHandler.ts diff --git a/packages/discord/src/scripts/register.ts b/packages/implementations/discord/src/scripts/register.ts similarity index 100% rename from packages/discord/src/scripts/register.ts rename to packages/implementations/discord/src/scripts/register.ts diff --git a/packages/discord/src/utils/createAccessRule.ts b/packages/implementations/discord/src/utils/createAccessRule.ts similarity index 100% rename from packages/discord/src/utils/createAccessRule.ts rename to packages/implementations/discord/src/utils/createAccessRule.ts diff --git a/packages/discord/src/utils/createDiscordEvent.ts b/packages/implementations/discord/src/utils/createDiscordEvent.ts similarity index 100% rename from packages/discord/src/utils/createDiscordEvent.ts rename to packages/implementations/discord/src/utils/createDiscordEvent.ts diff --git a/packages/discord/src/utils/getChannelById.ts b/packages/implementations/discord/src/utils/getChannelById.ts similarity index 100% rename from packages/discord/src/utils/getChannelById.ts rename to packages/implementations/discord/src/utils/getChannelById.ts diff --git a/packages/discord/src/utils/getCleanContent.ts b/packages/implementations/discord/src/utils/getCleanContent.ts similarity index 100% rename from packages/discord/src/utils/getCleanContent.ts rename to packages/implementations/discord/src/utils/getCleanContent.ts diff --git a/packages/discord/src/utils/getClientDisplayName.ts b/packages/implementations/discord/src/utils/getClientDisplayName.ts similarity index 100% rename from packages/discord/src/utils/getClientDisplayName.ts rename to packages/implementations/discord/src/utils/getClientDisplayName.ts diff --git a/packages/discord/src/utils/getConversationConfig.ts b/packages/implementations/discord/src/utils/getConversationConfig.ts similarity index 68% rename from packages/discord/src/utils/getConversationConfig.ts rename to packages/implementations/discord/src/utils/getConversationConfig.ts index 98c8fbb..6f8be60 100644 --- a/packages/discord/src/utils/getConversationConfig.ts +++ b/packages/implementations/discord/src/utils/getConversationConfig.ts @@ -1,4 +1,4 @@ -import { ConversationConfigParameters } from "gpt-turbo"; +import { ConversationConfigModel } from "gpt-turbo"; import { GPTTURBO_APIKEY, GPTTURBO_MODEL, @@ -7,8 +7,8 @@ import { } from "../config/env.js"; export default ( - config: ConversationConfigParameters = {} -): ConversationConfigParameters => ({ + config: ConversationConfigModel = {} +): ConversationConfigModel => ({ apiKey: GPTTURBO_APIKEY, model: GPTTURBO_MODEL, dry: !GPTTURBO_APIKEY || GPTTURBO_DRY, diff --git a/packages/discord/src/utils/getGuildById.ts b/packages/implementations/discord/src/utils/getGuildById.ts similarity index 100% rename from packages/discord/src/utils/getGuildById.ts rename to packages/implementations/discord/src/utils/getGuildById.ts diff --git a/packages/discord/src/utils/getHandlerId.ts b/packages/implementations/discord/src/utils/getHandlerId.ts similarity index 100% rename from packages/discord/src/utils/getHandlerId.ts rename to packages/implementations/discord/src/utils/getHandlerId.ts diff --git a/packages/discord/src/utils/getMessageById.ts b/packages/implementations/discord/src/utils/getMessageById.ts similarity index 100% rename from packages/discord/src/utils/getMessageById.ts rename to packages/implementations/discord/src/utils/getMessageById.ts diff --git a/packages/discord/src/utils/getPromptAndReplyMessages.ts b/packages/implementations/discord/src/utils/getPromptAndReplyMessages.ts similarity index 100% rename from packages/discord/src/utils/getPromptAndReplyMessages.ts rename to packages/implementations/discord/src/utils/getPromptAndReplyMessages.ts diff --git a/packages/discord/src/utils/getReferencedMessage.ts b/packages/implementations/discord/src/utils/getReferencedMessage.ts similarity index 100% rename from packages/discord/src/utils/getReferencedMessage.ts rename to packages/implementations/discord/src/utils/getReferencedMessage.ts diff --git a/packages/discord/src/utils/isBotAdmin.ts b/packages/implementations/discord/src/utils/isBotAdmin.ts similarity index 100% rename from packages/discord/src/utils/isBotAdmin.ts rename to packages/implementations/discord/src/utils/isBotAdmin.ts diff --git a/packages/discord/src/utils/isValidSnowflake.ts b/packages/implementations/discord/src/utils/isValidSnowflake.ts similarity index 100% rename from packages/discord/src/utils/isValidSnowflake.ts rename to packages/implementations/discord/src/utils/isValidSnowflake.ts diff --git a/packages/discord/src/utils/loadResource.ts b/packages/implementations/discord/src/utils/loadResource.ts similarity index 100% rename from packages/discord/src/utils/loadResource.ts rename to packages/implementations/discord/src/utils/loadResource.ts diff --git a/packages/discord/src/utils/makeIsEvent.ts b/packages/implementations/discord/src/utils/makeIsEvent.ts similarity index 100% rename from packages/discord/src/utils/makeIsEvent.ts rename to packages/implementations/discord/src/utils/makeIsEvent.ts diff --git a/packages/discord/src/utils/reply.ts b/packages/implementations/discord/src/utils/reply.ts similarity index 100% rename from packages/discord/src/utils/reply.ts rename to packages/implementations/discord/src/utils/reply.ts diff --git a/packages/discord/src/utils/setupInteractionCleanup.ts b/packages/implementations/discord/src/utils/setupInteractionCleanup.ts similarity index 100% rename from packages/discord/src/utils/setupInteractionCleanup.ts rename to packages/implementations/discord/src/utils/setupInteractionCleanup.ts diff --git a/packages/discord/src/utils/types.ts b/packages/implementations/discord/src/utils/types.ts similarity index 100% rename from packages/discord/src/utils/types.ts rename to packages/implementations/discord/src/utils/types.ts diff --git a/packages/discord/tsconfig.build.json b/packages/implementations/discord/tsconfig.build.json similarity index 100% rename from packages/discord/tsconfig.build.json rename to packages/implementations/discord/tsconfig.build.json diff --git a/packages/discord/tsconfig.json b/packages/implementations/discord/tsconfig.json similarity index 100% rename from packages/discord/tsconfig.json rename to packages/implementations/discord/tsconfig.json diff --git a/packages/nest/.env.example b/packages/implementations/nest/.env.example similarity index 100% rename from packages/nest/.env.example rename to packages/implementations/nest/.env.example diff --git a/packages/nest/.eslintrc.cjs b/packages/implementations/nest/.eslintrc.cjs similarity index 97% rename from packages/nest/.eslintrc.cjs rename to packages/implementations/nest/.eslintrc.cjs index d9a048f..15aae98 100644 --- a/packages/nest/.eslintrc.cjs +++ b/packages/implementations/nest/.eslintrc.cjs @@ -29,6 +29,7 @@ module.exports = { "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/await-thenable": "warn", "max-classes-per-file": "off", "no-useless-constructor": "off", "class-methods-use-this": "off", diff --git a/packages/nest/.gitignore b/packages/implementations/nest/.gitignore similarity index 100% rename from packages/nest/.gitignore rename to packages/implementations/nest/.gitignore diff --git a/packages/nest/.prettierrc b/packages/implementations/nest/.prettierrc similarity index 100% rename from packages/nest/.prettierrc rename to packages/implementations/nest/.prettierrc diff --git a/packages/nest/GPT Turbo - Nest.postman_collection.json b/packages/implementations/nest/GPT Turbo - Nest.postman_collection.json similarity index 99% rename from packages/nest/GPT Turbo - Nest.postman_collection.json rename to packages/implementations/nest/GPT Turbo - Nest.postman_collection.json index 43cd2d0..07d1529 100644 --- a/packages/nest/GPT Turbo - Nest.postman_collection.json +++ b/packages/implementations/nest/GPT Turbo - Nest.postman_collection.json @@ -347,7 +347,7 @@ "variable": [ { "key": "gpt-turbo-nest", - "value": "", + "value": "http://localhost:3000", "type": "string" }, { @@ -359,11 +359,6 @@ "key": "assistantMessageId", "value": "", "type": "string" - }, - { - "key": "apiKey", - "value": "", - "type": "string" } ] } \ No newline at end of file diff --git a/packages/implementations/nest/GPT Turbo - Nest.postman_environment.json b/packages/implementations/nest/GPT Turbo - Nest.postman_environment.json new file mode 100644 index 0000000..8630e12 --- /dev/null +++ b/packages/implementations/nest/GPT Turbo - Nest.postman_environment.json @@ -0,0 +1,15 @@ +{ + "id": "8ed39bed-32ca-4fa7-b4ca-440b63335bf0", + "name": "GPT Turbo - Nest", + "values": [ + { + "key": "apiKey", + "value": "", + "type": "secret", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2023-07-29T04:46:31.274Z", + "_postman_exported_using": "Postman/10.16.3" +} \ No newline at end of file diff --git a/packages/nest/LICENSE.md b/packages/implementations/nest/LICENSE.md similarity index 100% rename from packages/nest/LICENSE.md rename to packages/implementations/nest/LICENSE.md diff --git a/packages/nest/README.md b/packages/implementations/nest/README.md similarity index 77% rename from packages/nest/README.md rename to packages/implementations/nest/README.md index 6a13a79..1d4efd9 100644 --- a/packages/nest/README.md +++ b/packages/implementations/nest/README.md @@ -1,11 +1,19 @@ -# GPT Turbo - Nest +# GPT Turbo - Implementation - Nest
- [![GPT Turbo - Nest](https://img.shields.io/github/package-json/v/maxijonson/gpt-turbo?color=brightgreen&filename=packages%2Fnest%2Fpackage.json&label=gpt-turbo-nest&logo=nestjs)](https://github.com/maxijonson/gpt-turbo/tree/develop/packages/nest) + [![GPT Turbo - Nest](https://img.shields.io/github/package-json/v/maxijonson/gpt-turbo?color=brightgreen&filename=packages%2Fnest%2Fpackage.json&label=gpt-turbo-nest&logo=nestjs)](https://github.com/maxijonson/gpt-turbo/tree/develop/packages/implementations/nest) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
+> ⚠⚠⚠ Since v5, this implementation is only maintained to make the build pass. Some cases may not work as expected. ⚠⚠⚠ +> +> The Nest implementation was more of a proof of concept when GPT Turbo started, rather than an actual useable project like the other implementations. +> For this reason, not much effort will be put into maintaining it. It's kept here for historical purposes, and may be reworked in the future or removed entirely. +> You're welcome to contribute to it if you want to keep it alive! +> +> *Note: this implementation has been tested thoroughly for the last time on v5.0.0 and seemed to work fine, apart from not using new features beyond v1.4, such as callable functions and plugins* + A NestJS app that interacts with the gpt-turbo library. ## Disclaimer @@ -79,10 +87,12 @@ For streamed conversation prompts (`POST /conversations/{id}`), Swagger will onl ## Postman Collection -While Swagger is the most up-to-date way of testing the API, since it is generated at runtime, you can also use the Postman collection included this directory: `GPT Turbo - Nest.postman_collection.json`. Bear in mind that this collection is not automatically updated, so it may be out of date. To use it, simply import it into Postman. +While Swagger is the most up-to-date way of testing the API, since it is generated at runtime, you can also use the Postman collection/environment included this directory: +- `GPT Turbo - Nest.postman_collection.json` +- `GPT Turbo - Nest.postman_environment.json` + +Bear in mind that this collection is not automatically updated, so it may be out of date. To use it, simply import it into Postman. The Postman collection includes automated scripts to assign variables so testing is relatively easier than Swagger. For example, after creating a conversation in Postman, the `conversationId` variable will be automatically assigned to the ID of the conversation. This means that you can then use the `conversationId` variable in subsequent requests, such as sending a prompt to the conversation. Postman is also a great way to test streamed conversation prompts, since Swagger will only show the data stream after the stream has ended. - -**Note: If you want to use your API key with these requests, set them in the collection's variables instead of directly in the body. This has already been setup for you to prevent accidental leaks if you open a PR with this file changed! (as I did when the Nest implementation was first released!)** \ No newline at end of file diff --git a/packages/nest/nest-cli.json b/packages/implementations/nest/nest-cli.json similarity index 100% rename from packages/nest/nest-cli.json rename to packages/implementations/nest/nest-cli.json diff --git a/packages/nest/package.json b/packages/implementations/nest/package.json similarity index 96% rename from packages/nest/package.json rename to packages/implementations/nest/package.json index 2d9d913..1c6e254 100644 --- a/packages/nest/package.json +++ b/packages/implementations/nest/package.json @@ -40,7 +40,7 @@ "nestjs" ], "author": "Tristan Chin ", - "homepage": "https://github.com/maxijonson/gpt-turbo/tree/develop/packages/nest#readme", + "homepage": "https://github.com/maxijonson/gpt-turbo/tree/develop/packages/implementations/nest#readme", "repository": { "type": "git", "url": "git+https://github.com/maxijonson/gpt-turbo.git" @@ -59,6 +59,7 @@ "@nestjs/swagger": "^6.3.0", "dotenv": "^16.0.3", "gpt-turbo": "^4.5.0", + "gpt-turbo-plugin-stats": "^4.5.0", "lowdb": "^5.1.0", "nestjs-zod": "^2.0.3", "reflect-metadata": "^0.1.13", diff --git a/packages/nest/src/app.controller.ts b/packages/implementations/nest/src/app.controller.ts similarity index 57% rename from packages/nest/src/app.controller.ts rename to packages/implementations/nest/src/app.controller.ts index 313b136..fe78376 100644 --- a/packages/nest/src/app.controller.ts +++ b/packages/implementations/nest/src/app.controller.ts @@ -1,7 +1,12 @@ -import { Controller } from "@nestjs/common"; +import { Controller, Get } from "@nestjs/common"; import { AppService } from "./app.service.js"; @Controller() export class AppController { constructor(private readonly appService: AppService) {} + + @Get() + getOk() { + return { status: "OK" }; + } } diff --git a/packages/nest/src/app.module.ts b/packages/implementations/nest/src/app.module.ts similarity index 100% rename from packages/nest/src/app.module.ts rename to packages/implementations/nest/src/app.module.ts diff --git a/packages/nest/src/app.service.ts b/packages/implementations/nest/src/app.service.ts similarity index 100% rename from packages/nest/src/app.service.ts rename to packages/implementations/nest/src/app.service.ts diff --git a/packages/nest/src/config/env.ts b/packages/implementations/nest/src/config/env.ts similarity index 100% rename from packages/nest/src/config/env.ts rename to packages/implementations/nest/src/config/env.ts diff --git a/packages/implementations/nest/src/config/gpt-turbo.ts b/packages/implementations/nest/src/config/gpt-turbo.ts new file mode 100644 index 0000000..60d1755 --- /dev/null +++ b/packages/implementations/nest/src/config/gpt-turbo.ts @@ -0,0 +1,10 @@ +import { Conversation } from "gpt-turbo"; +import statsPlugin from "gpt-turbo-plugin-stats"; + +const globalPlugins = [statsPlugin]; +Conversation.globalPlugins = [statsPlugin]; +declare module "gpt-turbo" { + export interface ConversationGlobalPluginsOverride { + globalPlugins: typeof globalPlugins; + } +} diff --git a/packages/nest/src/conversations/conversations.controller.ts b/packages/implementations/nest/src/conversations/conversations.controller.ts similarity index 94% rename from packages/nest/src/conversations/conversations.controller.ts rename to packages/implementations/nest/src/conversations/conversations.controller.ts index e7d2af3..6897bf6 100644 --- a/packages/nest/src/conversations/conversations.controller.ts +++ b/packages/implementations/nest/src/conversations/conversations.controller.ts @@ -20,7 +20,6 @@ import { ZodValidationPipe } from "nestjs-zod"; import { uuidSchema } from "../schemas/uuidSchema.js"; import { UseZodApiOperation } from "../decorators/zod-api-operation.decorator.js"; import { getConversationsResponseDtoSchema } from "./dtos/getConversations.dto.js"; -import messageToJson from "../utils/messageToJson.js"; import { Response } from "express"; import { z } from "nestjs-zod/z"; import { conversationDtoSchema } from "./dtos/conversation.dto.js"; @@ -180,13 +179,13 @@ export class ConversationsController { throw new NotFoundException("Conversation not found"); } - return conversation.getMessages().map(messageToJson); + return conversation.history.getMessages().map((m) => m.toJSON()); } private handlePromptResponse(message: Message, res: Response) { // Non-streaming message if (!message.isStreaming && message.content) { - res.json(messageToJson(message)); + res.json(message.toJSON()); return; } @@ -198,14 +197,12 @@ export class ConversationsController { }); res.status(200); - message.onMessageUpdate((_, m) => { - const data = JSON.stringify( - messageDtoSchema.parse(messageToJson(m)) - ); + message.onUpdate((_, m) => { + const data = JSON.stringify(messageDtoSchema.parse(m.toJSON())); res.write(`data: ${data}\n\n`); }); - message.onMessageStreamingStop(() => { + message.onStreamingStop(() => { res.end(); }); } diff --git a/packages/nest/src/conversations/conversations.module.ts b/packages/implementations/nest/src/conversations/conversations.module.ts similarity index 100% rename from packages/nest/src/conversations/conversations.module.ts rename to packages/implementations/nest/src/conversations/conversations.module.ts diff --git a/packages/nest/src/conversations/conversations.service.ts b/packages/implementations/nest/src/conversations/conversations.service.ts similarity index 85% rename from packages/nest/src/conversations/conversations.service.ts rename to packages/implementations/nest/src/conversations/conversations.service.ts index ec6af1a..8f5124a 100644 --- a/packages/nest/src/conversations/conversations.service.ts +++ b/packages/implementations/nest/src/conversations/conversations.service.ts @@ -1,12 +1,12 @@ import { Injectable, NotFoundException } from "@nestjs/common"; -import { Conversation, ConversationConfigParameters } from "gpt-turbo"; +import { Conversation, ConversationConfigModel } from "gpt-turbo"; @Injectable() export class ConversationsService { private conversations: Conversation[] = []; - createConversation(config: ConversationConfigParameters) { - const conversation = new Conversation(config); + createConversation(config: ConversationConfigModel) { + const conversation = new Conversation({ config }); this.addConversation(conversation); return conversation; } @@ -41,7 +41,7 @@ export class ConversationsService { throw new NotFoundException("Conversation not found"); } - const message = conversation + const message = conversation.history .getMessages() .find((m) => m.id === messageId); diff --git a/packages/implementations/nest/src/conversations/dtos/conversation.dto.ts b/packages/implementations/nest/src/conversations/dtos/conversation.dto.ts new file mode 100644 index 0000000..baf28e7 --- /dev/null +++ b/packages/implementations/nest/src/conversations/dtos/conversation.dto.ts @@ -0,0 +1,11 @@ +import { z } from "nestjs-zod/z"; +import { createZodDto } from "nestjs-zod"; +import { conversationSchema } from "gpt-turbo"; + +export const conversationDtoSchema = conversationSchema; + +export type ConversationDto = z.infer; + +export class ConversationDtoEntity extends createZodDto( + conversationDtoSchema +) {} diff --git a/packages/implementations/nest/src/conversations/dtos/conversationConfig.dto.ts b/packages/implementations/nest/src/conversations/dtos/conversationConfig.dto.ts new file mode 100644 index 0000000..eb866cb --- /dev/null +++ b/packages/implementations/nest/src/conversations/dtos/conversationConfig.dto.ts @@ -0,0 +1,11 @@ +import { conversationConfigSchema } from "gpt-turbo"; +import { createZodDto } from "nestjs-zod"; +import { z } from "nestjs-zod/z"; + +export const conversationConfigDtoSchema = conversationConfigSchema; + +export type ConversationConfigDto = z.infer; + +export class ConversationConfigDtoEntity extends createZodDto( + conversationConfigDtoSchema +) {} diff --git a/packages/nest/src/conversations/dtos/createConversation.dto.ts b/packages/implementations/nest/src/conversations/dtos/createConversation.dto.ts similarity index 100% rename from packages/nest/src/conversations/dtos/createConversation.dto.ts rename to packages/implementations/nest/src/conversations/dtos/createConversation.dto.ts diff --git a/packages/nest/src/conversations/dtos/getConversations.dto.ts b/packages/implementations/nest/src/conversations/dtos/getConversations.dto.ts similarity index 100% rename from packages/nest/src/conversations/dtos/getConversations.dto.ts rename to packages/implementations/nest/src/conversations/dtos/getConversations.dto.ts diff --git a/packages/implementations/nest/src/conversations/dtos/message.dto.ts b/packages/implementations/nest/src/conversations/dtos/message.dto.ts new file mode 100644 index 0000000..9a11afd --- /dev/null +++ b/packages/implementations/nest/src/conversations/dtos/message.dto.ts @@ -0,0 +1,9 @@ +import { z } from "nestjs-zod/z"; +import { createZodDto } from "nestjs-zod"; +import { messageSchema } from "gpt-turbo"; + +export const messageDtoSchema = messageSchema; + +export type MessageDto = z.infer; + +export class MessageDtoEntity extends createZodDto(messageDtoSchema) {} diff --git a/packages/nest/src/conversations/dtos/prompt.dto.ts b/packages/implementations/nest/src/conversations/dtos/prompt.dto.ts similarity index 100% rename from packages/nest/src/conversations/dtos/prompt.dto.ts rename to packages/implementations/nest/src/conversations/dtos/prompt.dto.ts diff --git a/packages/nest/src/conversations/dtos/repromptMessage.dto.ts b/packages/implementations/nest/src/conversations/dtos/repromptMessage.dto.ts similarity index 100% rename from packages/nest/src/conversations/dtos/repromptMessage.dto.ts rename to packages/implementations/nest/src/conversations/dtos/repromptMessage.dto.ts diff --git a/packages/nest/src/db/db.controller.ts b/packages/implementations/nest/src/db/db.controller.ts similarity index 100% rename from packages/nest/src/db/db.controller.ts rename to packages/implementations/nest/src/db/db.controller.ts diff --git a/packages/nest/src/db/db.module.ts b/packages/implementations/nest/src/db/db.module.ts similarity index 100% rename from packages/nest/src/db/db.module.ts rename to packages/implementations/nest/src/db/db.module.ts diff --git a/packages/nest/src/db/db.service.ts b/packages/implementations/nest/src/db/db.service.ts similarity index 100% rename from packages/nest/src/db/db.service.ts rename to packages/implementations/nest/src/db/db.service.ts diff --git a/packages/nest/src/decorators/zod-api-operation.decorator.ts b/packages/implementations/nest/src/decorators/zod-api-operation.decorator.ts similarity index 100% rename from packages/nest/src/decorators/zod-api-operation.decorator.ts rename to packages/implementations/nest/src/decorators/zod-api-operation.decorator.ts diff --git a/packages/nest/src/decorators/zod-response-validation.decorator.ts b/packages/implementations/nest/src/decorators/zod-response-validation.decorator.ts similarity index 100% rename from packages/nest/src/decorators/zod-response-validation.decorator.ts rename to packages/implementations/nest/src/decorators/zod-response-validation.decorator.ts diff --git a/packages/nest/src/filters/zod-validation-exception.filter.ts b/packages/implementations/nest/src/filters/zod-validation-exception.filter.ts similarity index 100% rename from packages/nest/src/filters/zod-validation-exception.filter.ts rename to packages/implementations/nest/src/filters/zod-validation-exception.filter.ts diff --git a/packages/nest/src/index.ts b/packages/implementations/nest/src/index.ts similarity index 96% rename from packages/nest/src/index.ts rename to packages/implementations/nest/src/index.ts index 08cd6a1..4c52537 100644 --- a/packages/nest/src/index.ts +++ b/packages/implementations/nest/src/index.ts @@ -12,6 +12,7 @@ import { PORT, } from "./config/env.js"; import { ZodValidationExceptionFilter } from "./filters/zod-validation-exception.filter.js"; +import "./config/gpt-turbo.js"; patchNestJsSwagger(); @@ -67,6 +68,7 @@ const bootstrap = async () => { app.useGlobalFilters(new ZodValidationExceptionFilter()); + console.info(`🚀 Listening on port ${PORT}`); await app.listen(PORT); }; diff --git a/packages/nest/src/interceptors/class-transform.interceptor.ts b/packages/implementations/nest/src/interceptors/class-transform.interceptor.ts similarity index 80% rename from packages/nest/src/interceptors/class-transform.interceptor.ts rename to packages/implementations/nest/src/interceptors/class-transform.interceptor.ts index 024dc0d..c18a69b 100644 --- a/packages/nest/src/interceptors/class-transform.interceptor.ts +++ b/packages/implementations/nest/src/interceptors/class-transform.interceptor.ts @@ -5,9 +5,9 @@ import { NestInterceptor, } from "@nestjs/common"; import { Conversation, Message } from "gpt-turbo"; +import { statsPluginName } from "gpt-turbo-plugin-stats"; import { Observable } from "rxjs"; import { map } from "rxjs/operators"; -import messageToJson from "../utils/messageToJson.js"; @Injectable() export class ClassTransformInterceptor implements NestInterceptor { @@ -45,22 +45,23 @@ export class ClassTransformInterceptor implements NestInterceptor { } private handleConversationInstance(instance: Conversation) { - const { apiKey, ...config } = instance.getConfig(); + const { apiKey, ...config } = instance.config.getConfig(); + const stats = instance.plugins.getPluginOutput(statsPluginName); return { id: instance.id, config, - messages: instance + messages: instance.history .getMessages() .map((message) => this.handleMessageInstance(message)), - cost: instance.getCost(), - cumulativeCost: instance.getCumulativeCost(), - size: instance.getSize(), - cumulativeSize: instance.getCumulativeSize(), + cost: stats.cost, + cumulativeCost: stats.cumulativeCost, + size: stats.size, + cumulativeSize: stats.cumulativeSize, }; } private handleMessageInstance(instance: Message) { - return messageToJson(instance); + return instance.toJSON(); } } diff --git a/packages/nest/src/interceptors/zod-validation.interceptor.ts b/packages/implementations/nest/src/interceptors/zod-validation.interceptor.ts similarity index 100% rename from packages/nest/src/interceptors/zod-validation.interceptor.ts rename to packages/implementations/nest/src/interceptors/zod-validation.interceptor.ts diff --git a/packages/nest/src/schemas/uuidSchema.ts b/packages/implementations/nest/src/schemas/uuidSchema.ts similarity index 100% rename from packages/nest/src/schemas/uuidSchema.ts rename to packages/implementations/nest/src/schemas/uuidSchema.ts diff --git a/packages/nest/src/utils/getOpenAPIRequestBody.ts b/packages/implementations/nest/src/utils/getOpenAPIRequestBody.ts similarity index 100% rename from packages/nest/src/utils/getOpenAPIRequestBody.ts rename to packages/implementations/nest/src/utils/getOpenAPIRequestBody.ts diff --git a/packages/nest/tsconfig.build.json b/packages/implementations/nest/tsconfig.build.json similarity index 100% rename from packages/nest/tsconfig.build.json rename to packages/implementations/nest/tsconfig.build.json diff --git a/packages/nest/tsconfig.json b/packages/implementations/nest/tsconfig.json similarity index 100% rename from packages/nest/tsconfig.json rename to packages/implementations/nest/tsconfig.json diff --git a/packages/web/.eslintrc.cjs b/packages/implementations/web/.eslintrc.cjs similarity index 97% rename from packages/web/.eslintrc.cjs rename to packages/implementations/web/.eslintrc.cjs index b88703d..2320ba9 100644 --- a/packages/web/.eslintrc.cjs +++ b/packages/implementations/web/.eslintrc.cjs @@ -33,6 +33,7 @@ module.exports = { ], "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/await-thenable": "warn", "max-classes-per-file": "off", "no-useless-constructor": "off", "class-methods-use-this": "off", diff --git a/packages/web/.gitignore b/packages/implementations/web/.gitignore similarity index 100% rename from packages/web/.gitignore rename to packages/implementations/web/.gitignore diff --git a/packages/web/.prettierrc b/packages/implementations/web/.prettierrc similarity index 100% rename from packages/web/.prettierrc rename to packages/implementations/web/.prettierrc diff --git a/packages/web/LICENSE.md b/packages/implementations/web/LICENSE.md similarity index 100% rename from packages/web/LICENSE.md rename to packages/implementations/web/LICENSE.md diff --git a/packages/web/README.md b/packages/implementations/web/README.md similarity index 97% rename from packages/web/README.md rename to packages/implementations/web/README.md index 23f8f86..26d3c66 100644 --- a/packages/web/README.md +++ b/packages/implementations/web/README.md @@ -1,4 +1,4 @@ -# GPT Turbo - Web +# GPT Turbo - Implementation - Web
@@ -52,7 +52,7 @@ The following instructions are for deploying the web app to [Render](https://ren 4. Select the `master` branch as the branch to deploy. 5. Leave the root directory blank. 6. Set the build command to `npm run build:web`. -7. Set the publish directory to `packages/web/dist`. +7. Set the publish directory to `packages/implementations/web/dist`. 8. Add an environment variable `NODE_VERSION` with `lts` as the value. 9. (Optional) If you chose to link this repository (option 2), you may want to disable the "Auto-Deploy" option under the "Advanced" tab. This will prevent Render from automatically deploying the web app every time a change is made to it. You can then manually deploy the web app later. 10. Click "Create Static Site". diff --git a/packages/web/index.html b/packages/implementations/web/index.html similarity index 100% rename from packages/web/index.html rename to packages/implementations/web/index.html diff --git a/packages/web/package.json b/packages/implementations/web/package.json similarity index 86% rename from packages/web/package.json rename to packages/implementations/web/package.json index 28a6d5f..55b2c0f 100644 --- a/packages/web/package.json +++ b/packages/implementations/web/package.json @@ -38,7 +38,7 @@ "react" ], "author": "Tristan Chin ", - "homepage": "https://github.com/maxijonson/gpt-turbo/tree/develop/packages/web#readme", + "homepage": "https://github.com/maxijonson/gpt-turbo/tree/develop/packages/implementations/web#readme", "repository": { "type": "git", "url": "git+https://github.com/maxijonson/gpt-turbo.git" @@ -52,14 +52,14 @@ ], "dependencies": { "@emotion/react": "^11.11.1", - "@mantine/core": "^6.0.16", - "@mantine/dropzone": "6.0.16", - "@mantine/form": "^6.0.16", - "@mantine/hooks": "^6.0.16", - "@mantine/modals": "^6.0.16", - "@mantine/notifications": "^6.0.16", - "@mantine/prism": "^6.0.16", - "@mantine/tiptap": "^6.0.16", + "@mantine/core": "^6.0.17", + "@mantine/dropzone": "6.0.17", + "@mantine/form": "^6.0.17", + "@mantine/hooks": "^6.0.17", + "@mantine/modals": "^6.0.17", + "@mantine/notifications": "^6.0.17", + "@mantine/prism": "^6.0.17", + "@mantine/tiptap": "^6.0.17", "@tabler/icons-react": "^2.25.0", "@tiptap/extension-code-block-lowlight": "^2.0.3", "@tiptap/extension-link": "^2.0.3", @@ -67,6 +67,7 @@ "@tiptap/react": "^2.0.3", "@tiptap/starter-kit": "^2.0.3", "gpt-turbo": "^4.5.0", + "gpt-turbo-plugin-stats": "^4.5.0", "lowlight": "^2.9.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/packages/web/src/changelog/index.ts b/packages/implementations/web/src/changelog/index.ts similarity index 82% rename from packages/web/src/changelog/index.ts rename to packages/implementations/web/src/changelog/index.ts index d55b9e4..b6073cb 100644 --- a/packages/web/src/changelog/index.ts +++ b/packages/implementations/web/src/changelog/index.ts @@ -2,6 +2,7 @@ import { ReactNode } from "react"; import v4_4_0 from "./v4-4-0"; import v4_4_1 from "./v4-4-1"; import v4_5_0 from "./v4-5-0"; +import v5_0_0 from "./v5-0-0"; export type ChangelogEntrySection = { label: ReactNode; @@ -17,4 +18,4 @@ export type ChangelogEntry = { }; // First entry is the latest version -export const changelog = [v4_5_0, v4_4_1, v4_4_0]; +export const changelog = [v5_0_0, v4_5_0, v4_4_1, v4_4_0]; diff --git a/packages/web/src/changelog/v4-4-0.ts b/packages/implementations/web/src/changelog/v4-4-0.ts similarity index 100% rename from packages/web/src/changelog/v4-4-0.ts rename to packages/implementations/web/src/changelog/v4-4-0.ts diff --git a/packages/web/src/changelog/v4-4-1.ts b/packages/implementations/web/src/changelog/v4-4-1.ts similarity index 100% rename from packages/web/src/changelog/v4-4-1.ts rename to packages/implementations/web/src/changelog/v4-4-1.ts diff --git a/packages/web/src/changelog/v4-5-0.ts b/packages/implementations/web/src/changelog/v4-5-0.ts similarity index 100% rename from packages/web/src/changelog/v4-5-0.ts rename to packages/implementations/web/src/changelog/v4-5-0.ts diff --git a/packages/implementations/web/src/changelog/v5-0-0.ts b/packages/implementations/web/src/changelog/v5-0-0.ts new file mode 100644 index 0000000..56f22eb --- /dev/null +++ b/packages/implementations/web/src/changelog/v5-0-0.ts @@ -0,0 +1,26 @@ +import { ChangelogEntry } from "."; +import { CHANGELOG_SECTION } from "../config/constants"; + +const v5_0_0: ChangelogEntry = { + version: "5.0.0 - Library rewrite and plugin system", + date: new Date("july 30 2023"), + description: + "This new update is primarily focused on the library side of the project, so there shouldn't be any major noticeable changes here. However, under the hood, the library has been completely rewritten to be more modular and extensible with plugins. The first plugin to exist is actually the usage stats feature, which has been moved out from the underlying library and into a conversation plugin!", + sections: [ + { + label: CHANGELOG_SECTION.IMPROVEMENTS, + items: [ + "Integrated the stats plugin", + "Stats are now updated in real time", + "Improve the crash screen to show the error message and stack trace", + "Improve the crash screen to pre-fill the bug report on GitHub", + ], + }, + { + label: CHANGELOG_SECTION.FIXES, + items: ["Fixed the usage stats not updating correctly sometimes"], + }, + ], +}; + +export default v5_0_0; diff --git a/packages/web/src/components/About/About.tsx b/packages/implementations/web/src/components/About/About.tsx similarity index 100% rename from packages/web/src/components/About/About.tsx rename to packages/implementations/web/src/components/About/About.tsx diff --git a/packages/web/src/components/About/AboutButton.tsx b/packages/implementations/web/src/components/About/AboutButton.tsx similarity index 100% rename from packages/web/src/components/About/AboutButton.tsx rename to packages/implementations/web/src/components/About/AboutButton.tsx diff --git a/packages/web/src/components/AddConversation.tsx b/packages/implementations/web/src/components/AddConversation.tsx similarity index 76% rename from packages/web/src/components/AddConversation.tsx rename to packages/implementations/web/src/components/AddConversation.tsx index 2ceb4c4..39513c4 100644 --- a/packages/web/src/components/AddConversation.tsx +++ b/packages/implementations/web/src/components/AddConversation.tsx @@ -40,24 +40,35 @@ const AddConversation = () => { const { classes } = useStyles(); const dropzoneOpenRef = React.useRef<() => void>(null); - const onSubmit = React.useCallback( - ({ - save, - headers, - proxy, - functionIds, - ...values - }: ConversationFormValues) => { - const newConversation = addConversation( - values, - { headers, proxy }, - functionIds, - save - ); - setActiveConversation(newConversation.id, true); - }, - [] - ); + const onSubmit = React.useCallback((values: ConversationFormValues) => { + const newConversation = addConversation( + { + config: { + apiKey: values.apiKey, + model: values.model, + context: values.context, + dry: values.dry, + disableModeration: values.disableModeration, + stream: values.stream, + temperature: values.temperature, + top_p: values.top_p, + frequency_penalty: values.frequency_penalty, + presence_penalty: values.presence_penalty, + stop: values.stop, + max_tokens: values.max_tokens, + logit_bias: values.logit_bias, + user: values.user, + }, + requestOptions: { + headers: values.headers, + proxy: values.proxy, + }, + }, + values.functionIds, + values.save + ); + setActiveConversation(newConversation.id, true); + }, []); const onDrop = React.useCallback( async (importedConversations) => { diff --git a/packages/web/src/components/AppSettings/AppSettings.tsx b/packages/implementations/web/src/components/AppSettings/AppSettings.tsx similarity index 100% rename from packages/web/src/components/AppSettings/AppSettings.tsx rename to packages/implementations/web/src/components/AppSettings/AppSettings.tsx diff --git a/packages/web/src/components/AppSettings/AppSettingsDangerZone.tsx b/packages/implementations/web/src/components/AppSettings/AppSettingsDangerZone.tsx similarity index 100% rename from packages/web/src/components/AppSettings/AppSettingsDangerZone.tsx rename to packages/implementations/web/src/components/AppSettings/AppSettingsDangerZone.tsx diff --git a/packages/web/src/components/AppSettings/AppStorageUsage.tsx b/packages/implementations/web/src/components/AppSettings/AppStorageUsage.tsx similarity index 100% rename from packages/web/src/components/AppSettings/AppStorageUsage.tsx rename to packages/implementations/web/src/components/AppSettings/AppStorageUsage.tsx diff --git a/packages/web/src/components/AppSettings/DataSettings.tsx b/packages/implementations/web/src/components/AppSettings/DataSettings.tsx similarity index 100% rename from packages/web/src/components/AppSettings/DataSettings.tsx rename to packages/implementations/web/src/components/AppSettings/DataSettings.tsx diff --git a/packages/web/src/components/AppSettings/GeneralSettings.tsx b/packages/implementations/web/src/components/AppSettings/GeneralSettings.tsx similarity index 100% rename from packages/web/src/components/AppSettings/GeneralSettings.tsx rename to packages/implementations/web/src/components/AppSettings/GeneralSettings.tsx diff --git a/packages/web/src/components/CallableFunctionCard/CallableFunctionCard.tsx b/packages/implementations/web/src/components/CallableFunctionCard/CallableFunctionCard.tsx similarity index 100% rename from packages/web/src/components/CallableFunctionCard/CallableFunctionCard.tsx rename to packages/implementations/web/src/components/CallableFunctionCard/CallableFunctionCard.tsx diff --git a/packages/web/src/components/CallableFunctionCard/CallableFunctionCardMenu.tsx b/packages/implementations/web/src/components/CallableFunctionCard/CallableFunctionCardMenu.tsx similarity index 100% rename from packages/web/src/components/CallableFunctionCard/CallableFunctionCardMenu.tsx rename to packages/implementations/web/src/components/CallableFunctionCard/CallableFunctionCardMenu.tsx diff --git a/packages/web/src/components/CallableFunctionCreateButton.tsx b/packages/implementations/web/src/components/CallableFunctionCreateButton.tsx similarity index 100% rename from packages/web/src/components/CallableFunctionCreateButton.tsx rename to packages/implementations/web/src/components/CallableFunctionCreateButton.tsx diff --git a/packages/web/src/components/CallableFunctionImport/CallableFunctionImport.tsx b/packages/implementations/web/src/components/CallableFunctionImport/CallableFunctionImport.tsx similarity index 100% rename from packages/web/src/components/CallableFunctionImport/CallableFunctionImport.tsx rename to packages/implementations/web/src/components/CallableFunctionImport/CallableFunctionImport.tsx diff --git a/packages/web/src/components/CallableFunctionImport/CallableFunctionImportButton.tsx b/packages/implementations/web/src/components/CallableFunctionImport/CallableFunctionImportButton.tsx similarity index 100% rename from packages/web/src/components/CallableFunctionImport/CallableFunctionImportButton.tsx rename to packages/implementations/web/src/components/CallableFunctionImport/CallableFunctionImportButton.tsx diff --git a/packages/web/src/components/CallableFunctionImport/CallableFunctionImportDropzone.tsx b/packages/implementations/web/src/components/CallableFunctionImport/CallableFunctionImportDropzone.tsx similarity index 100% rename from packages/web/src/components/CallableFunctionImport/CallableFunctionImportDropzone.tsx rename to packages/implementations/web/src/components/CallableFunctionImport/CallableFunctionImportDropzone.tsx diff --git a/packages/web/src/components/Changelog/Changelog.tsx b/packages/implementations/web/src/components/Changelog/Changelog.tsx similarity index 100% rename from packages/web/src/components/Changelog/Changelog.tsx rename to packages/implementations/web/src/components/Changelog/Changelog.tsx diff --git a/packages/web/src/components/Changelog/ChangelogButton.tsx b/packages/implementations/web/src/components/Changelog/ChangelogButton.tsx similarity index 100% rename from packages/web/src/components/Changelog/ChangelogButton.tsx rename to packages/implementations/web/src/components/Changelog/ChangelogButton.tsx diff --git a/packages/web/src/components/ConversationNavbar/ConversationNavbar.tsx b/packages/implementations/web/src/components/ConversationNavbar/ConversationNavbar.tsx similarity index 100% rename from packages/web/src/components/ConversationNavbar/ConversationNavbar.tsx rename to packages/implementations/web/src/components/ConversationNavbar/ConversationNavbar.tsx diff --git a/packages/web/src/components/ConversationNavbar/ConversationNavbarBurger.tsx b/packages/implementations/web/src/components/ConversationNavbar/ConversationNavbarBurger.tsx similarity index 100% rename from packages/web/src/components/ConversationNavbar/ConversationNavbarBurger.tsx rename to packages/implementations/web/src/components/ConversationNavbar/ConversationNavbarBurger.tsx diff --git a/packages/web/src/components/ConversationNavbar/ConversationNavbarFooter/ConversationNavbarFooter.tsx b/packages/implementations/web/src/components/ConversationNavbar/ConversationNavbarFooter/ConversationNavbarFooter.tsx similarity index 97% rename from packages/web/src/components/ConversationNavbar/ConversationNavbarFooter/ConversationNavbarFooter.tsx rename to packages/implementations/web/src/components/ConversationNavbar/ConversationNavbarFooter/ConversationNavbarFooter.tsx index 06b8532..bf01c32 100644 --- a/packages/web/src/components/ConversationNavbar/ConversationNavbarFooter/ConversationNavbarFooter.tsx +++ b/packages/implementations/web/src/components/ConversationNavbar/ConversationNavbarFooter/ConversationNavbarFooter.tsx @@ -12,7 +12,7 @@ const ConversationNavbarFooter = () => { diff --git a/packages/web/src/components/ConversationNavbar/ConversationNavbarHeader/ConversationNavbarHeader.tsx b/packages/implementations/web/src/components/ConversationNavbar/ConversationNavbarHeader/ConversationNavbarHeader.tsx similarity index 100% rename from packages/web/src/components/ConversationNavbar/ConversationNavbarHeader/ConversationNavbarHeader.tsx rename to packages/implementations/web/src/components/ConversationNavbar/ConversationNavbarHeader/ConversationNavbarHeader.tsx diff --git a/packages/web/src/components/ConversationNavbar/ConversationNavbarHeader/SettingsButton.tsx b/packages/implementations/web/src/components/ConversationNavbar/ConversationNavbarHeader/SettingsButton.tsx similarity index 100% rename from packages/web/src/components/ConversationNavbar/ConversationNavbarHeader/SettingsButton.tsx rename to packages/implementations/web/src/components/ConversationNavbar/ConversationNavbarHeader/SettingsButton.tsx diff --git a/packages/web/src/components/ConversationNavbar/NavbarConversations/NavbarConverationInfoIcon.tsx b/packages/implementations/web/src/components/ConversationNavbar/NavbarConversations/NavbarConverationInfoIcon.tsx similarity index 100% rename from packages/web/src/components/ConversationNavbar/NavbarConversations/NavbarConverationInfoIcon.tsx rename to packages/implementations/web/src/components/ConversationNavbar/NavbarConversations/NavbarConverationInfoIcon.tsx diff --git a/packages/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversation/NavbarConversation.tsx b/packages/implementations/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversation/NavbarConversation.tsx similarity index 100% rename from packages/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversation/NavbarConversation.tsx rename to packages/implementations/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversation/NavbarConversation.tsx diff --git a/packages/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversation/NavbarConversationMenu.tsx b/packages/implementations/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversation/NavbarConversationMenu.tsx similarity index 100% rename from packages/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversation/NavbarConversationMenu.tsx rename to packages/implementations/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversation/NavbarConversationMenu.tsx diff --git a/packages/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversationInfo.tsx b/packages/implementations/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversationInfo.tsx similarity index 96% rename from packages/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversationInfo.tsx rename to packages/implementations/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversationInfo.tsx index 673d2fd..b791d42 100644 --- a/packages/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversationInfo.tsx +++ b/packages/implementations/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversationInfo.tsx @@ -28,7 +28,8 @@ const SIZE = 14; const NavbarConversationInfo = ({ conversation, }: NavbarConversationInfoProps) => { - const { model, dry, disableModeration, stream } = conversation.getConfig(); + const { model, dry, disableModeration, stream } = + conversation.config.getConfig(); const persistedConversationIds = useAppStore( (state) => state.persistedConversationIds ); diff --git a/packages/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversations.tsx b/packages/implementations/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversations.tsx similarity index 100% rename from packages/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversations.tsx rename to packages/implementations/web/src/components/ConversationNavbar/NavbarConversations/NavbarConversations.tsx diff --git a/packages/web/src/components/ConversationPageShell.tsx b/packages/implementations/web/src/components/ConversationPageShell.tsx similarity index 100% rename from packages/web/src/components/ConversationPageShell.tsx rename to packages/implementations/web/src/components/ConversationPageShell.tsx diff --git a/packages/web/src/components/Messages/CodeBlock.tsx b/packages/implementations/web/src/components/Messages/CodeBlock.tsx similarity index 100% rename from packages/web/src/components/Messages/CodeBlock.tsx rename to packages/implementations/web/src/components/Messages/CodeBlock.tsx diff --git a/packages/web/src/components/Messages/Message.tsx b/packages/implementations/web/src/components/Messages/Message.tsx similarity index 100% rename from packages/web/src/components/Messages/Message.tsx rename to packages/implementations/web/src/components/Messages/Message.tsx diff --git a/packages/web/src/components/Messages/Messages.tsx b/packages/implementations/web/src/components/Messages/Messages.tsx similarity index 84% rename from packages/web/src/components/Messages/Messages.tsx rename to packages/implementations/web/src/components/Messages/Messages.tsx index f6941b3..f0c5c9f 100644 --- a/packages/web/src/components/Messages/Messages.tsx +++ b/packages/implementations/web/src/components/Messages/Messages.tsx @@ -23,7 +23,7 @@ const useStyles = createStyles(() => ({ const Messages = () => { const conversation = useActiveConversation(); const [messages, setMessages] = React.useState( - conversation?.getMessages() ?? [] + conversation?.history.getMessages() ?? [] ); const callFunction = useCallFunction(); const viewport = React.useRef(null); @@ -73,7 +73,7 @@ const Messages = () => { React.useEffect(() => { if (!conversation) return; const unsubscribes: (() => void)[] = []; - const unsubscribeMessageAdded = conversation.onMessageAdded( + const unsubscribeMessageAdded = conversation.history.onMessageAdded( (message) => { if (message.role === "system") return; setMessages((messages) => [...messages, message]); @@ -83,26 +83,30 @@ const Messages = () => { if (message.role !== "assistant") return; unsubscribes.push( - message.onMessageUpdate(() => { + message.onUpdate(() => { setMessages((messages) => [...messages]); // Force re-render by creating a new array if (isSticky) scrollToBottom(); }) ); - const isStreaming = conversation.getConfig().stream; + const isStreaming = conversation.config.getConfig().stream; if (isStreaming) { - const unsubscribeStreamingStop = - message.onMessageStreamingStop((message) => { + const unsubscribeStreamingStop = message.onStreamingStop( + (message) => { unsubscribeStreamingStop(); if (!message.isFunctionCall()) return; handleFunctionCall( message, - conversation.getFunctions() + conversation.callableFunctions.getFunctions() ); - }); + } + ); unsubscribes.push(unsubscribeStreamingStop); } else if (message.isFunctionCall()) { - handleFunctionCall(message, conversation.getFunctions()); + handleFunctionCall( + message, + conversation.callableFunctions.getFunctions() + ); } } ); @@ -115,7 +119,7 @@ const Messages = () => { React.useEffect(() => { if (!conversation) return; - return conversation.onMessageRemoved((message) => { + return conversation.history.onMessageRemoved((message) => { setMessages((messages) => messages.filter((m) => m.id !== message.id) ); @@ -123,7 +127,7 @@ const Messages = () => { }, [conversation]); React.useEffect(() => { - setMessages(conversation?.getMessages() ?? []); + setMessages(conversation?.history.getMessages() ?? []); }, [conversation]); return ( diff --git a/packages/web/src/components/Usage/Usage.tsx b/packages/implementations/web/src/components/Usage/Usage.tsx similarity index 77% rename from packages/web/src/components/Usage/Usage.tsx rename to packages/implementations/web/src/components/Usage/Usage.tsx index a0db6b8..db1aca8 100644 --- a/packages/web/src/components/Usage/Usage.tsx +++ b/packages/implementations/web/src/components/Usage/Usage.tsx @@ -4,6 +4,9 @@ import UsageMetric from "./UsageMetric"; import getPriceString from "../../utils/getPriceString"; import { useGetConversationName } from "../../store/hooks/conversations/useGetConversationName"; import { DEFAULT_CONVERSATION_NAME } from "../../config/constants"; +import { statsPluginName } from "gpt-turbo-plugin-stats"; +import React from "react"; +import { useForceUpdate } from "@mantine/hooks"; interface UsageProps { conversation: Conversation; @@ -11,6 +14,8 @@ interface UsageProps { const Usage = ({ conversation }: UsageProps) => { const getConversationName = useGetConversationName(); + const forceUpdate = useForceUpdate(); + const stats = conversation.plugins.getPluginOutput(statsPluginName); const metrics: { label: React.ReactNode; @@ -19,26 +24,30 @@ const Usage = ({ conversation }: UsageProps) => { }[] = [ { label: "Cumulative Size", - value: `${conversation.getCumulativeSize()} tkns`, + value: `${stats.cumulativeSize} tkns`, description: "Cumulative number of tokens sent to OpenAI", }, { label: "Cumulative Cost", - value: getPriceString(conversation.getCumulativeCost()), + value: getPriceString(stats.cumulativeCost), description: "Cumulative cost of tokens sent to OpenAI", }, { label: "Conversation Size", - value: `${conversation.getSize()} tkns`, + value: `${stats.size} tkns`, description: "Current number of tokens in this conversation", }, { label: "Conversation Cost", - value: getPriceString(conversation.getCost()), + value: getPriceString(stats.cost), description: "Current cost of tokens in this conversation", }, ]; + React.useEffect(() => { + stats.onStatsUpdate(() => forceUpdate()); + }, [forceUpdate, stats]); + return ( diff --git a/packages/web/src/components/Usage/UsageMetric.tsx b/packages/implementations/web/src/components/Usage/UsageMetric.tsx similarity index 100% rename from packages/web/src/components/Usage/UsageMetric.tsx rename to packages/implementations/web/src/components/Usage/UsageMetric.tsx diff --git a/packages/web/src/components/common/ContentLoader.tsx b/packages/implementations/web/src/components/common/ContentLoader.tsx similarity index 100% rename from packages/web/src/components/common/ContentLoader.tsx rename to packages/implementations/web/src/components/common/ContentLoader.tsx diff --git a/packages/web/src/components/common/InlineConfirmButton.tsx b/packages/implementations/web/src/components/common/InlineConfirmButton.tsx similarity index 100% rename from packages/web/src/components/common/InlineConfirmButton.tsx rename to packages/implementations/web/src/components/common/InlineConfirmButton.tsx diff --git a/packages/web/src/components/common/TippedActionIcon.tsx b/packages/implementations/web/src/components/common/TippedActionIcon.tsx similarity index 100% rename from packages/web/src/components/common/TippedActionIcon.tsx rename to packages/implementations/web/src/components/common/TippedActionIcon.tsx diff --git a/packages/implementations/web/src/components/error-handling/AppCatcher.tsx b/packages/implementations/web/src/components/error-handling/AppCatcher.tsx new file mode 100644 index 0000000..91867fc --- /dev/null +++ b/packages/implementations/web/src/components/error-handling/AppCatcher.tsx @@ -0,0 +1,38 @@ +import React, { ErrorInfo } from "react"; +import AppErrorModal from "./AppErrorModal"; + +export interface AppCatcherProps { + children?: React.ReactNode; +} + +export interface AppCatcherState { + error: Error | null; +} + +class AppCatcher extends React.Component { + constructor(props: AppCatcherProps) { + super(props); + this.state = { error: null }; + } + + static getDerivedStateFromError(error: Error) { + return { error }; + } + + componentDidCatch(error: Error, errorInfo: ErrorInfo) { + console.error(error, errorInfo); + } + + render() { + const { error } = this.state; + const { children } = this.props; + + if (!error) { + return children; + } + + return ; + } +} + +export default AppCatcher; diff --git a/packages/implementations/web/src/components/error-handling/AppErrorModal.tsx b/packages/implementations/web/src/components/error-handling/AppErrorModal.tsx new file mode 100644 index 0000000..b4ecf1b --- /dev/null +++ b/packages/implementations/web/src/components/error-handling/AppErrorModal.tsx @@ -0,0 +1,162 @@ +import { + Modal, + Title, + ScrollArea, + Stack, + Container, + List, + Group, + Button, + Text, + Collapse, + Box, + Divider, + Textarea, +} from "@mantine/core"; +import { useDisclosure } from "@mantine/hooks"; +import React from "react"; +import { BiBug, BiTrash, BiRefresh, BiLogoGithub } from "react-icons/bi"; +import TippedActionIcon from "../common/TippedActionIcon"; +import getErrorInfo from "../../utils/getErrorInfo"; +import { storeVersion } from "../../store/persist/migrations"; +import getIssueLink, { blockTicks } from "../../utils/getIssueLink"; + +interface AppErrorModalProps { + error: Error; +} + +const AppErrorModal = ({ error }: AppErrorModalProps) => { + const [showError, { toggle: toggleShowError }] = useDisclosure(); + + const reportLink = React.useMemo(() => { + const title = "[Bug]: Web Fatal Error"; + + const info = getErrorInfo(error); + const content = { + "App Version": APP_VERSION, + "Store Version": storeVersion, + "Error Info": `${blockTicks}\n${info.title}\n${info.message}\n${blockTicks}`, + "Stack Trace": `${blockTicks}\n${error.stack}\n${blockTicks}`, + }; + return getIssueLink(title, content); + }, [error]); + + return ( + {}} + centered + title={ + + Fatal error + + } + color="red" + size="xl" + scrollAreaComponent={ScrollArea.Autosize} + > + + + + The application encountered a fatal error. Try to reload + the page. If the issue persists, try opening the app in + a private tab: + + + If the app now works in a private tab, you might + have invalid or outdated local storage data in + your browser. Consider clearing your local + storage data{" "} + + which will clear all your settings and + conversations + + + + If the app still does not work in a private tab, + you might have encountered a bug. You may report + it on the project's project's GitHub issues + page. In order to help us resolve this issue, + please include the error information below by + clicking on the{" "} + + + {" "} + icon or the "Report issue on GitHub" button to + pre-fill this information! + + + + + + + + + } + labelPosition="center" + mb="xs" + /> + +