diff --git a/package.json b/package.json index 77d0f5c..955aa91 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@untemps/react-vocal": "^1.7.16", "ajv": "^8.12.0", "lodash": "^4.17.21", - "openai": "^3.2.1", + "openai": "^4.55.7", "react": "^18.2.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", @@ -37,7 +37,9 @@ "react-redux": "^8.0.5", "react-router-dom": "^6.9.0", "react-scripts": "5.0.1", + "redux-persist": "^6.0.0", "typescript": "^4.9.5", + "uuidv4": "^6.2.13", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/src/app/store.ts b/src/app/store.ts index 4a4f24c..cf67fe1 100644 --- a/src/app/store.ts +++ b/src/app/store.ts @@ -1,15 +1,31 @@ import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit' +import { persistStore, persistReducer } from 'redux-persist' import counterReducer from '../features/counter/counterSlice' import jsonFormsEditReducer from '../features/wizard/WizardSlice' import templateSlice from '../features/wizard/TemplateSlice' - +import storage from 'redux-persist/lib/storage' +import { formsDataReducer } from '../features/wizard/FormDataSlice' // defaults to localStorage for web export const store = configureStore({ reducer: { counter: counterReducer, jsonFormsEdit: jsonFormsEditReducer, - template: templateSlice, + template: persistReducer( + { + key: 'template', + storage, + }, + templateSlice + ), + formsData: persistReducer( + { + key: 'formsData', + storage, + }, + formsDataReducer + ), }, }) +export const persistor = persistStore(store) export type AppDispatch = typeof store.dispatch export type RootState = ReturnType diff --git a/src/features/home/ClickBox.tsx b/src/features/home/ClickBox.tsx new file mode 100644 index 0000000..d157586 --- /dev/null +++ b/src/features/home/ClickBox.tsx @@ -0,0 +1,34 @@ +import { Avatar, Button, Card, CardActionArea, CardContent, CardHeader, CardMedia, Typography } from '@mui/material' +import React, { useCallback } from 'react' +import { useAppDispatch } from '../../app/hooks/reduxHooks' +import { loadForm } from '../wizard/FormDataSlice' +import { red } from '@mui/material/colors' + +type ClickBoxProps = { + id: string + title: string + avatar?: string +} +export const ClickBox = ({ id, title, avatar }: ClickBoxProps) => { + const dispatch = useAppDispatch() + const handleLoad = useCallback(() => { + dispatch(loadForm({ id })) + }, [id]) + + return ( + + + {title[0]} + + } + title={title} + > + {avatar && } + + + + + ) +} diff --git a/src/features/home/DragBox.tsx b/src/features/home/DragBox.tsx index 4689327..d4ad390 100644 --- a/src/features/home/DragBox.tsx +++ b/src/features/home/DragBox.tsx @@ -1,7 +1,8 @@ -import React, { useEffect, useLayoutEffect, useState } from 'react' +import React, { useCallback, useEffect, useLayoutEffect, useState } from 'react' import { useDrag } from 'react-dnd' import { Button, Card, CardActionArea, CardActions, CardContent, Typography } from '@mui/material' -import { DraggableComponent } from '../wizard/WizardSlice' +import { DraggableComponent, replaceSchema } from '../wizard/WizardSlice' +import { useAppDispatch } from '../../app/hooks/reduxHooks' type DragBoxProps = { name: string @@ -9,6 +10,7 @@ type DragBoxProps = { componentMeta: DraggableComponent } const DragBox = ({ name = 'Eingabefeld', img = '', componentMeta }: DragBoxProps) => { + const dispatch = useAppDispatch() const [, dragRef] = useDrag( () => ({ type: 'DRAGBOX', @@ -25,6 +27,10 @@ const DragBox = ({ name = 'Eingabefeld', img = '', componentMeta }: DragBoxProps [] ) + const handleReplace = useCallback(() => { + dispatch(replaceSchema(componentMeta.jsonSchemaElement)) + }, [dispatch, componentMeta]) + return ( @@ -33,6 +39,9 @@ const DragBox = ({ name = 'Eingabefeld', img = '', componentMeta }: DragBoxProps {name} + + + ) diff --git a/src/features/home/LeftDrawer.tsx b/src/features/home/LeftDrawer.tsx index a2b8d8c..f9f3406 100644 --- a/src/features/home/LeftDrawer.tsx +++ b/src/features/home/LeftDrawer.tsx @@ -5,14 +5,17 @@ import Drawer from '@mui/material/Drawer' import Toolbar from '@mui/material/Toolbar' import DragBox from './DragBox' -import { DraggableComponent } from '../wizard/WizardSlice' +import { DraggableComponent, selectJsonSchema, selectUiSchema } from '../wizard/WizardSlice' import { TabContext, TabList, TabPanel } from '@mui/lab' -import { Tab } from '@mui/material' +import { Button, Tab } from '@mui/material' import { useCallback } from 'react' import { updateScopeOfUISchemaElement } from '../../utils/uiSchemaHelpers' import { ConfirmButton } from '../modals/ChatGptModal' -import { useSelector } from 'react-redux' import { selectTemplates } from '../wizard/TemplateSlice' +import { useAppDispatch, useAppSelector } from '../../app/hooks/reduxHooks' +import { ClickBox } from './ClickBox' +import { listFormData, newForm } from '../wizard/FormDataSlice' +import { CreateRounded } from '@mui/icons-material' const drawerWidth = 240 @@ -116,9 +119,24 @@ export const advancedDraggableComponents: DraggableComponent[] = [ }, ] +export const NewEntryButton = () => { + const dispatch = useAppDispatch() + const jsonSchema = useAppSelector(selectJsonSchema) + const uiSchema = useAppSelector(selectUiSchema) + const handleNewEntry = useCallback(() => { + dispatch(newForm({ jsonSchema, uiSchema })) + }, [dispatch, jsonSchema, uiSchema]) + return ( + + ) +} + export default function LeftDrawer() { const [activeTab, setActiveTab] = React.useState('1') - const templates = useSelector(selectTemplates) + const templates = useAppSelector(selectTemplates) + const formDataList = useAppSelector(listFormData) const handleChange = useCallback( (event, newValue) => { setActiveTab(newValue) @@ -145,6 +163,7 @@ export default function LeftDrawer() { + @@ -162,14 +181,20 @@ export default function LeftDrawer() { + KI gestützte Formulargenerierung {advancedDraggableComponents.map((component, index) => { return })} - Chat GPT {templates.map((component, index) => { return })} + + + {formDataList.map(({ id, title, avatar }) => { + return + })} + ) diff --git a/src/features/input/UploadAnalyzeGPT.tsx b/src/features/input/UploadAnalyzeGPT.tsx new file mode 100644 index 0000000..93a0750 --- /dev/null +++ b/src/features/input/UploadAnalyzeGPT.tsx @@ -0,0 +1,88 @@ +import { useState } from 'react' +import openAIInstance, { model } from '../../utils/openai' +import { threadId } from 'worker_threads' + +export const UploadAnalyzeGPT = () => { + const [summary, setSummary] = useState('') + const [loading, setLoading] = useState(false) + + const handleFileUpload = async (event) => { + const file = event.target.files[0] + + if (!file) { + return + } + + setLoading(true) + + try { + const client = openAIInstance + + // Upload the file to OpenAI + /*const response = await client.files.create({ + file: new File([file], file.name), + purpose: 'assistants', // Change the purpose according to your need + });*/ + + const vectorStore = await client.beta.vectorStores.create({ name: 'File Upload' }) + console.log('Vector Store ID:', vectorStore.id) + + const batch = await client.beta.vectorStores.fileBatches.uploadAndPoll(vectorStore.id, { + files: [new File([file], file.name)], + }) + console.log({ batch }) + + const assistant = await client.beta.assistants.create({ + model: model, + instructions: 'You are a knowledgeable assistant that uses the provided files to answer questions.', + tools: [{ type: 'file_search' }], + tool_resources: { + file_search: { + vector_store_ids: [vectorStore.id], // Attach vector store containing your files + }, + }, + }) + + console.log('Assistant ID:', assistant.id) + console.log({ assistant }) + + const thread = await client.beta.threads.create() + console.log('Thread ID:', thread.id) + + const message = await client.beta.threads.messages.create(thread.id, { + role: 'user', + content: 'Summarize what can be seen at the image', + }) + + const run = await client.beta.threads.runs.create(thread.id, { + assistant_id: assistant.id, + }) + + console.log({ run }) + + let interval = setInterval(async () => { + const status = await client.beta.threads.runs.retrieve(thread.id, run.id) + if (status.status === 'completed') { + clearInterval(interval) + const messages = await client.beta.threads.messages.list(thread.id) + console.log({ messages }) + } + }, 1000) + + //setSummary(run.choices[0].message.content.trim()); + } catch (error) { + console.error('Error uploading file:', error) + setSummary('An error occurred while summarizing the file.') + } finally { + setLoading(false) + } + } + + return ( +
+ + {loading &&

Uploading and summarizing the file...

} + {summary &&

Summary: {summary}

} +
+ ) +} diff --git a/src/features/modals/ChatGptModal.tsx b/src/features/modals/ChatGptModal.tsx index 47e0625..409d9d3 100644 --- a/src/features/modals/ChatGptModal.tsx +++ b/src/features/modals/ChatGptModal.tsx @@ -21,6 +21,7 @@ import Box from '@mui/material/Box' import { LoadingButton, TabContext, TabList, TabPanel } from '@mui/lab' import DropTargetFormsPreview from '../dragAndDrop/DropTargetFormsPreview' import Vocal from '@untemps/react-vocal' +import { AndroidRounded } from '@mui/icons-material' interface ConfirmModalProps { onConfirm?: () => void @@ -76,20 +77,41 @@ const ChatGptModal = NiceModal.create(({ onConfirm = () => nu const talkToAI = useCallback( async (text) => { // Insert message at first element. - const response = await openaiInstance.createCompletion({ + const response = await openaiInstance.chat.completions.create({ model: model, - prompt: `For a form generate a JSONSchema that meets the following requirements: ${text}`, - max_tokens: 600, + messages: [ + { + role: 'user', + content: `For a form generate a JSONSchema that meets the following requirements: ${text} \n Only output the parsable JSON Schema - even without the typical markdown code block. Keys und properties should always be in english but labels/titles should be in the language of the requirements text. Add additional fields, that can be derived from your domain knowledge, even if not explicitly asked for.`, + }, + ], + max_tokens: 4000, }) - console.log(response.data) + console.log(response) // Append AI message. - setResponse(response.data.choices[0].text) - const titleResponse = await openaiInstance.createCompletion({ - model: model, - prompt: `The headline or title that summarizes the following form: ${text}`, - max_tokens: 50, - }) - setFormTitle(titleResponse.data.choices[0].text) + const res = response.choices[0].message.content + setResponse(res) + let formTitle: string | null = null + try { + const schema = JSON.parse(res) + if (typeof schema.title === 'string') { + formTitle = schema.title + } + } catch (e) { + console.warn(e.message) + } + if (!formTitle) { + const titleResponse = await openaiInstance.chat.completions.create({ + model: model, + messages: [ + { role: 'user', content: `A short headline or title that summarizes the following form: ${text}` }, + ], + max_tokens: 50, + }) + formTitle = titleResponse.choices[0].message.content + } + + setFormTitle(formTitle) setLoading(false) }, [setResponse, setFormTitle, setLoading] @@ -143,7 +165,11 @@ const ChatGptModal = NiceModal.create(({ onConfirm = () => nu setMessage(e.target.value)} /> - + Submit @@ -171,6 +197,9 @@ const ChatGptModal = NiceModal.create(({ onConfirm = () => nu + @@ -187,6 +216,8 @@ export function ConfirmButton({ }: ConfirmModalProps & { children: React.ReactNode }) { return ( + + ) diff --git a/src/features/wizard/WizardSlice.ts b/src/features/wizard/WizardSlice.ts index d2a7493..2782341 100644 --- a/src/features/wizard/WizardSlice.ts +++ b/src/features/wizard/WizardSlice.ts @@ -32,45 +32,6 @@ const initialState: JsonFormsEditState = { name: { type: 'string', }, - description: { - type: 'string', - }, - done: { - type: 'boolean', - }, - rating: { - type: 'integer', - }, - customerSatisfaction: { - type: 'integer', - }, - category: { - type: 'object', - properties: { - name: { - type: 'string', - }, - description: { - type: 'string', - }, - }, - }, - meta: { - type: 'object', - properties: { - created: { - type: 'string', - format: 'date-time', - }, - lastModified: { - type: 'string', - format: 'date-time', - }, - version: { - type: 'integer', - }, - }, - }, }, required: ['name'], }, @@ -81,58 +42,6 @@ const initialState: JsonFormsEditState = { type: 'Control', scope: '#/properties/name', }, - { - type: 'HorizontalLayout', - elements: [ - { - type: 'Control', - scope: '#/properties/rating', - }, - { - type: 'Control', - scope: '#/properties/customerSatisfaction', - }, - ], - }, - { - type: 'Control', - scope: '#/properties/category/properties/name', - }, - { - type: 'Control', - scope: '#/properties/category/properties/description', - }, - { - type: 'Control', - scope: '#/properties/description', - }, - { - type: 'Control', - scope: '#/properties/done', - }, - { - type: 'Group', - label: 'Metadata', - elements: [ - { - type: 'VerticalLayout', - elements: [ - { - type: 'Control', - scope: '#/properties/meta/properties/created', - }, - { - type: 'Control', - scope: '#/properties/meta/properties/lastModified', - }, - { - type: 'Control', - scope: '#/properties/meta/properties/version', - }, - ], - }, - ], - }, ], }, } @@ -237,6 +146,11 @@ export const jsonFormsEditSlice = createSlice({ const { scope, uiSchema } = action.payload state.uiSchema = updateUISchemaElement(scope, uiSchema, state.uiSchema) }, + replaceSchema: (state: JsonFormsEditState, action: PayloadAction) => { + const schema = action.payload + state.jsonSchema = schema + state.uiSchema = undefined + }, insertControl: ( state: JsonFormsEditState, action: PayloadAction<{ @@ -303,7 +217,14 @@ export const jsonFormsEditSlice = createSlice({ }, }) -export const { insertControl, selectElement, renameField, removeField, updateUISchemaByScope, toggleEditMode } = - jsonFormsEditSlice.actions +export const { + insertControl, + selectElement, + renameField, + removeField, + updateUISchemaByScope, + toggleEditMode, + replaceSchema, +} = jsonFormsEditSlice.actions export default jsonFormsEditSlice.reducer diff --git a/src/index.tsx b/src/index.tsx index a56a252..dc9cf3c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,7 +1,7 @@ import React from 'react' import { createRoot } from 'react-dom/client' import { Provider } from 'react-redux' -import { store } from './app/store' +import { persistor, store } from './app/store' import App from './App' import { HashRouter } from 'react-router-dom' import './index.css' @@ -13,6 +13,7 @@ import NiceModal from '@ebay/nice-modal-react' import { IntlProvider } from 'react-intl' import { TouchBackend } from 'react-dnd-touch-backend' import reportWebVitals from './reportWebVitals' +import { PersistGate } from 'redux-persist/integration/react' const container = document.getElementById('root')! const root = createRoot(container) console.log('APP running in touch mode: ' + isTouchDevice()) @@ -20,17 +21,19 @@ const backend = isTouchDevice() ? TouchBackend : HTML5Backend root.render( - - - - - - - - - - - + + + + + + + + + + + + + ) diff --git a/src/utils/openai.ts b/src/utils/openai.ts index 4cb6596..99a0d6f 100644 --- a/src/utils/openai.ts +++ b/src/utils/openai.ts @@ -1,11 +1,11 @@ -import { Configuration, OpenAIApi } from 'openai' +import { OpenAI } from 'openai' console.log(process.env) -const configuration = new Configuration({ +const openAIInstance = new OpenAI({ + dangerouslyAllowBrowser: true, organization: process.env.REACT_APP_OPENAI_ORGANIZATION, apiKey: process.env.REACT_APP_OPENAI_API_KEY, }) -const openaiInstance = new OpenAIApi(configuration) -export default openaiInstance +export default openAIInstance -export const model = 'text-davinci-003' +export const model = 'gpt-4o' diff --git a/yarn.lock b/yarn.lock index 60ec376..6b05f7c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3814,6 +3814,14 @@ "@types/node" "*" form-data "^3.0.0" +"@types/node-fetch@^2.6.4": + version "2.6.11" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24" + integrity sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g== + dependencies: + "@types/node" "*" + form-data "^4.0.0" + "@types/node@*": version "18.15.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.5.tgz#3af577099a99c61479149b716183e70b5239324a" @@ -3829,6 +3837,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== +"@types/node@^18.11.18": + version "18.19.44" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.44.tgz#875a8322d17ff12bf82b3af8c07b9310a00e72f8" + integrity sha512-ZsbGerYg72WMXUIE9fYxtvfzLEuq6q8mKERdWFnqTmOvudMxnz+CBNRoOwJ2kNpFOncrKjT1hZwxjlFgQ9qvQA== + dependencies: + undici-types "~5.26.4" + "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" @@ -3993,6 +4008,11 @@ resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43" integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== +"@types/uuid@8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" + integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== + "@types/ws@^8.5.1": version "8.5.4" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" @@ -4273,6 +4293,13 @@ abab@^2.0.3, abab@^2.0.5: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -4348,6 +4375,13 @@ agent-base@6: dependencies: debug "4" +agentkeepalive@^4.2.1: + version "4.5.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" + integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== + dependencies: + humanize-ms "^1.2.1" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -4652,13 +4686,6 @@ axe-core@^4.6.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.6.3.tgz#fc0db6fdb65cc7a80ccf85286d91d64ababa3ece" integrity sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg== -axios@^0.26.0: - version "0.26.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" - integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== - dependencies: - follow-redirects "^1.14.8" - axobject-query@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" @@ -6633,6 +6660,11 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + eventemitter3@^4.0.0: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -6919,7 +6951,7 @@ flow-parser@0.*: resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.204.0.tgz#48515c3d289557d465b409c60ebdf4e783af491e" integrity sha512-cQhNPLOk5NFyDXBC8WE8dy2Gls+YqKI3FNqQbJ7UrbFyd30IdEX3t27u3VsnoVK22I872+PWeb1KhHxDgu7kAg== -follow-redirects@^1.0.0, follow-redirects@^1.14.8: +follow-redirects@^1.0.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== @@ -6976,6 +7008,11 @@ fork-ts-checker-webpack-plugin@^7.2.8: semver "^7.3.5" tapable "^2.2.1" +form-data-encoder@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040" + integrity sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A== + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -6994,6 +7031,14 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +formdata-node@^4.3.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2" + integrity sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ== + dependencies: + node-domexception "1.0.0" + web-streams-polyfill "4.0.0-beta.3" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -7548,6 +7593,13 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" + hyphenate-style-name@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" @@ -9252,7 +9304,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -9315,6 +9367,11 @@ node-dir@^0.1.10, node-dir@^0.1.17: dependencies: minimatch "^3.0.2" +node-domexception@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + node-fetch-native@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.1.0.tgz#a530f5c4cadb49b382dcf81d8f5f19ed0f457fbe" @@ -9539,13 +9596,18 @@ open@^8.0.9, open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" -openai@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/openai/-/openai-3.2.1.tgz#1fa35bdf979cbde8453b43f2dd3a7d401ee40866" - integrity sha512-762C9BNlJPbjjlWZi4WYK9iM2tAVAv0uUp1UmI34vb0CN5T2mjB/qM6RYBmNKMh/dN9fC+bxqPwWJZUTWW052A== - dependencies: - axios "^0.26.0" - form-data "^4.0.0" +openai@^4.55.7: + version "4.55.7" + resolved "https://registry.yarnpkg.com/openai/-/openai-4.55.7.tgz#2bba4ae9224ad205c0d087d1412fe95421397dff" + integrity sha512-I2dpHTINt0Zk+Wlns6KzkKu77MmNW3VfIIQf5qYziEUI6t7WciG1zTobfKqdPzBmZi3TTM+3DtjPumxQdcvzwA== + dependencies: + "@types/node" "^18.11.18" + "@types/node-fetch" "^2.6.4" + abort-controller "^3.0.0" + agentkeepalive "^4.2.1" + form-data-encoder "1.7.2" + formdata-node "^4.3.2" + node-fetch "^2.6.7" optionator@^0.8.1: version "0.8.3" @@ -10958,6 +11020,11 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +redux-persist@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8" + integrity sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ== + redux-thunk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.2.tgz#b9d05d11994b99f7a91ea223e8b04cf0afa5ef3b" @@ -12267,6 +12334,11 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + unfetch@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" @@ -12440,11 +12512,19 @@ uuid-browser@^3.1.0: resolved "https://registry.yarnpkg.com/uuid-browser/-/uuid-browser-3.1.0.tgz#0f05a40aef74f9e5951e20efbf44b11871e56410" integrity sha512-dsNgbLaTrd6l3MMxTtouOCFw4CBFc/3a+GgYA2YyrJvyQ1u6q4pcu3ktLoUZ/VN/Aw9WsauazbgsgdfVWgAKQg== -uuid@^8.3.2: +uuid@8.3.2, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuidv4@^6.2.13: + version "6.2.13" + resolved "https://registry.yarnpkg.com/uuidv4/-/uuidv4-6.2.13.tgz#8f95ec5ef22d1f92c8e5d4c70b735d1c89572cb7" + integrity sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ== + dependencies: + "@types/uuid" "8.3.4" + uuid "8.3.2" + v8-to-istanbul@^8.1.0: version "8.1.1" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" @@ -12512,6 +12592,11 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" +web-streams-polyfill@4.0.0-beta.3: + version "4.0.0-beta.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38" + integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug== + web-vitals@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-2.1.4.tgz#76563175a475a5e835264d373704f9dde718290c"