From 2c07e71349eea62e201b7c58ea0e9c251cb0d133 Mon Sep 17 00:00:00 2001 From: Artemy Date: Tue, 4 Apr 2023 16:50:11 +0300 Subject: [PATCH] feat: openai completion support --- package-lock.json | 59 +++++++++++++++++++++++++++++++ package.json | 1 + src/App.jsx | 2 ++ src/components/button.jsx | 11 ++++-- src/components/openai.js | 31 ++++++++++++++++ src/components/settingsInputs.jsx | 15 +++++++- src/components/styles.js | 2 +- src/localisation/en.js | 2 ++ src/localisation/ru.js | 2 ++ src/pages/chat.jsx | 3 ++ src/pages/create.jsx | 28 +++++++++++++-- src/pages/settings.jsx | 16 ++++----- 12 files changed, 155 insertions(+), 17 deletions(-) create mode 100644 src/components/openai.js create mode 100644 src/pages/chat.jsx diff --git a/package-lock.json b/package-lock.json index b4d672a..ac5e50d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "dotenv": "^16.0.3", "express": "^4.18.2", "js-sha3": "^0.8.0", + "openai": "^3.2.1", "react": "^18.2.0", "react-contenteditable": "^3.3.7", "react-dom": "^18.2.0", @@ -889,6 +890,14 @@ "postcss": "^8.1.0" } }, + "node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -2202,6 +2211,25 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -3913,6 +3941,15 @@ "node": ">= 0.8" } }, + "node_modules/openai": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/openai/-/openai-3.2.1.tgz", + "integrity": "sha512-762C9BNlJPbjjlWZi4WYK9iM2tAVAv0uUp1UmI34vb0CN5T2mjB/qM6RYBmNKMh/dN9fC+bxqPwWJZUTWW052A==", + "dependencies": { + "axios": "^0.26.0", + "form-data": "^4.0.0" + } + }, "node_modules/optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", @@ -6269,6 +6306,14 @@ "postcss-value-parser": "^4.2.0" } }, + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } + }, "bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -7138,6 +7183,11 @@ } } }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, "form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -8256,6 +8306,15 @@ "ee-first": "1.1.1" } }, + "openai": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/openai/-/openai-3.2.1.tgz", + "integrity": "sha512-762C9BNlJPbjjlWZi4WYK9iM2tAVAv0uUp1UmI34vb0CN5T2mjB/qM6RYBmNKMh/dN9fC+bxqPwWJZUTWW052A==", + "requires": { + "axios": "^0.26.0", + "form-data": "^4.0.0" + } + }, "optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", diff --git a/package.json b/package.json index a805f60..871dbb9 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "dotenv": "^16.0.3", "express": "^4.18.2", "js-sha3": "^0.8.0", + "openai": "^3.2.1", "react": "^18.2.0", "react-contenteditable": "^3.3.7", "react-dom": "^18.2.0", diff --git a/src/App.jsx b/src/App.jsx index f1e7888..1385f63 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -12,6 +12,7 @@ import PubNoteSafe from "./pages/pubNoteSafe"; import RenderMarkdown from "./components/markdown"; import socket from "./components/socket"; import Settings from "./pages/settings"; +import Chat from "./pages/chat"; import Locales from "./localisation/main"; import { useState } from "react"; @@ -52,6 +53,7 @@ function App() { } /> } /> } /> + } />
{props.children}
@@ -23,9 +27,9 @@ function IconWithText(props) { ); } return ( -
+
{props.icon}
-
{props.children}
+
{props.children}
); } @@ -36,6 +40,7 @@ function ButtonWithIcon(props) { href={props.href} className={props.className} onClick={props.onClick} + w={props.w} > + {text} + + ); +} + +export { + SettingsCheckBox, + SettingsTextInput, + SettingsSelectInput, + SettingsPlaceholder, +}; diff --git a/src/components/styles.js b/src/components/styles.js index a1cbf46..746104f 100644 --- a/src/components/styles.js +++ b/src/components/styles.js @@ -1,4 +1,4 @@ let inputStyle = - "form-control block px-3 py-1.5 text-base font-normal text-gray-700 dark:text-white bg-white dark:bg-zinc-900 bg-clip-padding border border-solid border-gray-300 rounded-lg transition ease-in-out focus:border-blue-600 focus:outline-none"; + "w-full form-control block px-3 py-1.5 text-base font-normal text-gray-700 dark:text-white bg-white dark:bg-zinc-900 bg-clip-padding border border-solid border-gray-300 rounded-lg transition ease-in-out focus:border-blue-600 focus:outline-none"; export { inputStyle }; diff --git a/src/localisation/en.js b/src/localisation/en.js index bff5fc3..f09f431 100644 --- a/src/localisation/en.js +++ b/src/localisation/en.js @@ -41,6 +41,8 @@ let en = { Delete: "Delete", Open: "Open", NoNotesYet: "No notes yet", + AIComplete: "Continue Note (AI)", + AdditionalFeatures: "Additional features", }; export default en; diff --git a/src/localisation/ru.js b/src/localisation/ru.js index 25a024a..ebf2f00 100644 --- a/src/localisation/ru.js +++ b/src/localisation/ru.js @@ -42,6 +42,8 @@ let ru = { Delete: "Удалить", Open: "Открыть", NoNotesYet: "Заметок пока нет", + AIComplete: "Продолжить заметку (ИИ)", + AdditionalFeatures: "Дополнительные функции", }; export default ru; diff --git a/src/pages/chat.jsx b/src/pages/chat.jsx new file mode 100644 index 0000000..2db24c4 --- /dev/null +++ b/src/pages/chat.jsx @@ -0,0 +1,3 @@ +function Chat() {} + +export default Chat; diff --git a/src/pages/create.jsx b/src/pages/create.jsx index 74e83a6..c5bcd2b 100644 --- a/src/pages/create.jsx +++ b/src/pages/create.jsx @@ -1,5 +1,8 @@ import { ButtonWithIcon } from "../components/button"; -import { ChevronDoubleRightIcon } from "@heroicons/react/24/outline"; +import { + ChevronDoubleRightIcon, + DocumentTextIcon, +} from "@heroicons/react/24/outline"; import { CheckBox } from "../components/checkbox"; import { useState } from "react"; import RenderMarkdown from "../components/markdown"; @@ -12,8 +15,12 @@ import rehypeParse from "rehype-parse"; import remarkStringify from "remark-stringify"; import remarkGfm from "remark-gfm"; import remarkMath from "remark-math"; -import { SettingsCheckBox } from "../components/settingsInputs"; +import { + SettingsCheckBox, + SettingsPlaceholder, +} from "../components/settingsInputs"; import { inputStyle } from "../components/styles"; +import { Complete } from "../components/openai"; function CreateNote() { const [preview, setPreview] = useState(false); @@ -126,6 +133,23 @@ function CreateNote() { className="m-1" />
+ + {settings.additionalFeatures && ( +
+ + {!!settings.openAiKey && ( + { + Complete(setText); + }} + /> + )} +
+ )} ); diff --git a/src/pages/settings.jsx b/src/pages/settings.jsx index f2eea8c..786516f 100644 --- a/src/pages/settings.jsx +++ b/src/pages/settings.jsx @@ -2,6 +2,7 @@ import { SettingsCheckBox, SettingsTextInput, SettingsSelectInput, + SettingsPlaceholder, } from "../components/settingsInputs"; import { reRenderPage } from "../components/utils"; import Locales from "../localisation/main"; @@ -38,17 +39,20 @@ function Settings() { + + - {text} - - ); -} - export default Settings;