├── .gitignore ├── LICENSE.md ├── client ├── .env.example ├── .gitignore ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── components │ │ ├── App │ │ │ ├── App.css │ │ │ ├── App.test.tsx │ │ │ └── App.tsx │ │ ├── PromptInput │ │ │ ├── PromptInput.css │ │ │ └── PromptInput.tsx │ │ └── PromptResponseList │ │ │ ├── PromptResponseList.css │ │ │ ├── PromptResponseList.tsx │ │ │ └── response-interface.ts │ ├── img │ │ ├── chatgpt.png │ │ ├── demo2.gif │ │ └── me.png │ ├── index.tsx │ ├── react-app-env.d.ts │ ├── reportWebVitals.ts │ └── setupTests.ts └── tsconfig.json ├── readme.md └── server ├── .env.sample ├── .gitignore ├── index.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 Ioan Moldovan 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /client/.env.example: -------------------------------------------------------------------------------- 1 | REACT_APP_BACKEND_URL=http://localhost:3001/ -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chatgpt-client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "@types/jest": "^27.5.2", 10 | "@types/node": "^16.18.12", 11 | "@types/react": "^18.0.27", 12 | "@types/react-dom": "^18.0.10", 13 | "axios": "^1.3.2", 14 | "highlight.js": "^11.7.0", 15 | "react": "^18.2.0", 16 | "react-contenteditable": "^3.3.6", 17 | "react-dom": "^18.2.0", 18 | "react-markdown": "^8.0.5", 19 | "react-scripts": "5.0.1", 20 | "typescript": "^4.9.5", 21 | "web-vitals": "^2.1.4" 22 | }, 23 | "scripts": { 24 | "start": "react-scripts start", 25 | "build": "react-scripts build", 26 | "test": "react-scripts test", 27 | "eject": "react-scripts eject" 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "react-app", 32 | "react-app/jest" 33 | ] 34 | }, 35 | "browserslist": { 36 | "production": [ 37 | ">0.2%", 38 | "not dead", 39 | "not op_mini all" 40 | ], 41 | "development": [ 42 | "last 1 chrome version", 43 | "last 1 firefox version", 44 | "last 1 safari version" 45 | ] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ioanmo226/chatgpt-react-application/422a93d52df5d8b194923d7e515f74ba3e7bd630/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | ChatGPT Web Application 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /client/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ioanmo226/chatgpt-react-application/422a93d52df5d8b194923d7e515f74ba3e7bd630/client/public/logo192.png -------------------------------------------------------------------------------- /client/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ioanmo226/chatgpt-react-application/422a93d52df5d8b194923d7e515f74ba3e7bd630/client/public/logo512.png -------------------------------------------------------------------------------- /client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /client/src/components/App/App.css: -------------------------------------------------------------------------------- 1 | html, body, #root, .App { 2 | height: 100%; 3 | } 4 | .App { 5 | display: flex; 6 | flex-direction: column; 7 | } 8 | /* Add background color to the body */ 9 | body { 10 | background-color: rgba(68, 70, 84, 1.0); 11 | display: flex; 12 | flex-direction: column; 13 | justify-content: space-between; 14 | margin: 0; 15 | } 16 | 17 | /* Remove border color from the response list container */ 18 | #response-list { 19 | border: none; 20 | overflow-y: auto; 21 | flex: 1; 22 | } 23 | 24 | .chatgpt-response { 25 | background-color: rgba(68, 70, 84, 1); 26 | } 27 | 28 | .my-question { 29 | background-color: rgba(52, 53, 65, 1); 30 | } 31 | /* Change background color of the input container */ 32 | #input-container { 33 | display: flex; 34 | align-items: center; 35 | justify-content: space-between; 36 | padding: 10px; 37 | background-color: rgba(64, 65, 79, 1); 38 | border-color: rgba(32,33,35,.5); 39 | border-radius: 5px; 40 | margin: 10px 200px; 41 | } 42 | 43 | 44 | /* Remove background color and add an SVG background for the submit button */ 45 | #submit-button { 46 | background: transparent url("data:image/svg+xml,") no-repeat center center; 47 | color: white; 48 | width: 40px; 49 | height: 40px; 50 | border: none; 51 | border-radius: 5px; 52 | cursor: pointer; 53 | } 54 | 55 | #regenerate-button-container { 56 | display: flex; 57 | flex-direction: row; 58 | justify-content: center; 59 | margin-bottom: 10px; 60 | } 61 | 62 | #regenerate-response-button { 63 | color: white; 64 | border: none; 65 | background: #10A37F; 66 | border-radius: 4px; 67 | padding: 10px 20px; 68 | cursor: pointer; 69 | } 70 | 71 | .loading { 72 | opacity: 0.5; 73 | cursor: not-allowed; 74 | pointer-events: none; 75 | } 76 | 77 | #model-select-container { 78 | margin: 10px 200px; 79 | color: white; 80 | } 81 | 82 | #model-select-container select { 83 | background: transparent; 84 | border: none; 85 | outline: none; 86 | color: white; 87 | } 88 | 89 | #model-select-container select option:not(:checked) { 90 | background: rgba(32,33,35,.8); 91 | } 92 | 93 | #model-select-container select option { 94 | background: rgba(32,33,35,.5); 95 | } 96 | -------------------------------------------------------------------------------- /client/src/components/App/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /client/src/components/App/App.tsx: -------------------------------------------------------------------------------- 1 | import {useState} from 'react'; 2 | import axios from "axios"; 3 | import PromptInput from "../PromptInput/PromptInput"; 4 | import './App.css'; 5 | import {ResponseInterface} from "../PromptResponseList/response-interface"; 6 | import PromptResponseList from "../PromptResponseList/PromptResponseList"; 7 | 8 | type ModelValueType = 'gpt' | 'codex' | 'image'; 9 | const App = () => { 10 | 11 | const [responseList, setResponseList] = useState([]); 12 | const [prompt, setPrompt] = useState(''); 13 | const [promptToRetry, setPromptToRetry] = useState(null); 14 | const [uniqueIdToRetry, setUniqueIdToRetry] = useState(null); 15 | const [modelValue, setModelValue] = useState('gpt'); 16 | const [isLoading, setIsLoading] = useState(false); 17 | let loadInterval: number | undefined; 18 | 19 | const generateUniqueId = () => { 20 | const timestamp = Date.now(); 21 | const randomNumber = Math.random(); 22 | const hexadecimalString = randomNumber.toString(16); 23 | 24 | return `id-${timestamp}-${hexadecimalString}`; 25 | } 26 | 27 | const htmlToText = (html: string) => { 28 | const temp = document.createElement('div'); 29 | temp.innerHTML = html; 30 | return temp.textContent; 31 | } 32 | 33 | const delay = (ms: number) => { 34 | return new Promise( resolve => setTimeout(resolve, ms) ); 35 | } 36 | 37 | const addLoader = (uid: string) => { 38 | const element = document.getElementById(uid) as HTMLElement; 39 | element.textContent = '' 40 | 41 | // @ts-ignore 42 | loadInterval = setInterval(() => { 43 | // Update the text content of the loading indicator 44 | element.textContent += '.'; 45 | 46 | // If the loading indicator has reached three dots, reset it 47 | if (element.textContent === '....') { 48 | element.textContent = ''; 49 | } 50 | }, 300); 51 | } 52 | 53 | 54 | const addResponse = (selfFlag: boolean, response?: string) => { 55 | const uid = generateUniqueId() 56 | setResponseList(prevResponses => [ 57 | ...prevResponses, 58 | { 59 | id: uid, 60 | response, 61 | selfFlag 62 | }, 63 | ]); 64 | return uid; 65 | } 66 | 67 | const updateResponse = (uid: string, updatedObject: Record) => { 68 | setResponseList(prevResponses => { 69 | const updatedList = [...prevResponses] 70 | const index = prevResponses.findIndex((response) => response.id === uid); 71 | if (index > -1) { 72 | updatedList[index] = { 73 | ...updatedList[index], 74 | ...updatedObject 75 | } 76 | } 77 | return updatedList; 78 | }); 79 | } 80 | 81 | const regenerateResponse = async () => { 82 | await getGPTResult(promptToRetry, uniqueIdToRetry); 83 | } 84 | 85 | const getGPTResult = async (_promptToRetry?: string | null, _uniqueIdToRetry?: string | null) => { 86 | // Get the prompt input 87 | const _prompt = _promptToRetry ?? htmlToText(prompt); 88 | 89 | // If a response is already being generated or the prompt is empty, return 90 | if (isLoading || !_prompt) { 91 | return; 92 | } 93 | 94 | setIsLoading(true); 95 | 96 | // Clear the prompt input 97 | setPrompt(''); 98 | 99 | let uniqueId: string; 100 | if (_uniqueIdToRetry) { 101 | uniqueId = _uniqueIdToRetry; 102 | } else { 103 | // Add the self prompt to the response list 104 | addResponse(true, _prompt); 105 | uniqueId = addResponse(false); 106 | await delay(50); 107 | addLoader(uniqueId); 108 | } 109 | 110 | try { 111 | // Send a POST request to the API with the prompt in the request body 112 | const response = await axios.post('get-prompt-result', { 113 | prompt: _prompt, 114 | model: modelValue 115 | }); 116 | if (modelValue === 'image') { 117 | // Show image for `Create image` model 118 | updateResponse(uniqueId, { 119 | image: response.data, 120 | }); 121 | } else { 122 | updateResponse(uniqueId, { 123 | response: response.data.trim(), 124 | }); 125 | } 126 | 127 | setPromptToRetry(null); 128 | setUniqueIdToRetry(null); 129 | } catch (err) { 130 | setPromptToRetry(_prompt); 131 | setUniqueIdToRetry(uniqueId); 132 | updateResponse(uniqueId, { 133 | // @ts-ignore 134 | response: `Error: ${err.message}`, 135 | error: true 136 | }); 137 | } finally { 138 | // Clear the loader interval 139 | clearInterval(loadInterval); 140 | setIsLoading(false); 141 | } 142 | } 143 | 144 | return ( 145 |
146 |
147 | 148 |
149 | { uniqueIdToRetry && 150 | (
151 | 154 |
155 | ) 156 | } 157 |
158 | 159 | 165 |
166 |
167 | getGPTResult()} 170 | key="prompt-input" 171 | updatePrompt={(prompt) => setPrompt(prompt)} 172 | /> 173 | 174 |
175 |
176 | ); 177 | } 178 | 179 | export default App; 180 | -------------------------------------------------------------------------------- /client/src/components/PromptInput/PromptInput.css: -------------------------------------------------------------------------------- 1 | /* Style for the prompt input */ 2 | #prompt-input { 3 | flex-grow: 1; 4 | padding: 10px; 5 | border-radius: 5px; 6 | min-height: 20px; 7 | color: white; 8 | overflow: auto; 9 | } 10 | 11 | #prompt-input:focus { 12 | outline: none !important; 13 | } -------------------------------------------------------------------------------- /client/src/components/PromptInput/PromptInput.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef, useCallback } from 'react'; 2 | import ContentEditable from 'react-contenteditable'; 3 | import './PromptInput.css'; 4 | 5 | interface PromptInputProps { 6 | prompt: string; 7 | onSubmit: () => void; 8 | updatePrompt: (prompt: string) => void; 9 | } 10 | 11 | const PromptInput: React.FC = ({ prompt, onSubmit, updatePrompt }) => { 12 | const checkKeyPress = useCallback((e: KeyboardEvent) => { 13 | if (e.key === 'Enter') { 14 | e.preventDefault(); 15 | if (e.ctrlKey || e.shiftKey) { 16 | document.execCommand('insertHTML', false, '

'); 17 | } else { 18 | onSubmit(); 19 | } 20 | } 21 | // eslint-disable-next-line react-hooks/exhaustive-deps 22 | }, [prompt]); 23 | 24 | const contentEditableRef = useRef(null); 25 | 26 | useEffect(() => { 27 | window.addEventListener("keydown", checkKeyPress); 28 | return () => { 29 | window.removeEventListener("keydown", checkKeyPress); 30 | }; 31 | }, [checkKeyPress]); 32 | 33 | return ( 34 | updatePrompt(event.target.value)} 41 | /> 42 | ); 43 | }; 44 | 45 | export default PromptInput; 46 | -------------------------------------------------------------------------------- /client/src/components/PromptResponseList/PromptResponseList.css: -------------------------------------------------------------------------------- 1 | /* Style for each response element in the list */ 2 | .response-container { 3 | margin-bottom: 10px; 4 | color: white; 5 | padding: 15px 200px; 6 | font-size: 1rem; 7 | display: flex; 8 | } 9 | 10 | .response-container .avatar-image { 11 | width: 30px; 12 | height: 30px; 13 | margin-right: 15px; 14 | } 15 | 16 | .response-container .response-content { 17 | display: flex; 18 | flex-direction: column; 19 | } 20 | 21 | .response-container pre { 22 | max-width: 100%; 23 | margin: 0 !important; 24 | white-space: break-spaces; 25 | } 26 | 27 | .response-container .prompt-content { 28 | background: transparent !important; 29 | color: white; 30 | padding: 0 !important; 31 | margin-top: 5px; 32 | } 33 | 34 | .response-container .prompt-content p:first-child { 35 | margin-top: 0; 36 | } 37 | 38 | .ai-image { 39 | width: 500px; 40 | height: auto; 41 | } 42 | 43 | .error-response { 44 | color: rgb(220, 0, 0) !important; 45 | } 46 | 47 | /* Override hljs to match for chatgpt */ 48 | .hljs { 49 | background: rgb(0,0,0) !important; 50 | color: white !important; 51 | display: block; 52 | padding: 10px; 53 | border-radius: 6px; 54 | } 55 | 56 | .hljs-section, .hljs-title { 57 | color: #f22c3d !important; 58 | } 59 | 60 | .hljs-deletion, .hljs-number, .hljs-quote, .hljs-selector-class, .hljs-selector-id, .hljs-string, .hljs-template-tag, .hljs-type { 61 | color: #df3079 !important; 62 | } 63 | 64 | .hljs-addition, .hljs-built_in, .hljs-bullet, .hljs-code { 65 | color: #e9950c !important; 66 | } 67 | 68 | .hljs-link, .hljs-operator, .hljs-regexp, .hljs-selector-attr, .hljs-selector-pseudo, .hljs-symbol, .hljs-template-variable, .hljs-variable { 69 | color: white !important; 70 | } -------------------------------------------------------------------------------- /client/src/components/PromptResponseList/PromptResponseList.tsx: -------------------------------------------------------------------------------- 1 | import React, {FC, useEffect, useRef} from 'react'; 2 | import ChatGptImg from '../../img/chatgpt.png'; 3 | import MyImg from '../../img/me.png'; 4 | import ReactMarkdown from 'react-markdown'; 5 | import {ResponseInterface} from "./response-interface"; 6 | import hljs from 'highlight.js'; 7 | import './PromptResponseList.css'; 8 | 9 | interface PromptResponseListProps { 10 | responseList: ResponseInterface[]; 11 | } 12 | 13 | const PromptResponseList: FC = ({ responseList }) => { 14 | const responseListRef = useRef(null); 15 | 16 | useEffect(() => { 17 | hljs.highlightAll(); 18 | }) 19 | 20 | useEffect(() => { 21 | hljs.highlightAll(); 22 | }, [responseList]); 23 | 24 | return ( 25 |
26 | {responseList.map((responseData) => ( 27 |
28 | avatar 29 |
30 | { responseData.image && 31 | generated ai 32 | } 33 | { responseData.response && 34 | 40 | {children} 41 | 42 | ) 43 | } 44 | }} 45 | /> 46 | } 47 |
48 |
49 | ))} 50 |
51 | ); 52 | }; 53 | 54 | export default PromptResponseList; 55 | -------------------------------------------------------------------------------- /client/src/components/PromptResponseList/response-interface.ts: -------------------------------------------------------------------------------- 1 | export interface ResponseInterface { 2 | id: string; 3 | response?: string; 4 | selfFlag: boolean; 5 | error?: boolean; 6 | image?: string; 7 | } 8 | -------------------------------------------------------------------------------- /client/src/img/chatgpt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ioanmo226/chatgpt-react-application/422a93d52df5d8b194923d7e515f74ba3e7bd630/client/src/img/chatgpt.png -------------------------------------------------------------------------------- /client/src/img/demo2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ioanmo226/chatgpt-react-application/422a93d52df5d8b194923d7e515f74ba3e7bd630/client/src/img/demo2.gif -------------------------------------------------------------------------------- /client/src/img/me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ioanmo226/chatgpt-react-application/422a93d52df5d8b194923d7e515f74ba3e7bd630/client/src/img/me.png -------------------------------------------------------------------------------- /client/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './components/App/App'; 4 | import reportWebVitals from './reportWebVitals'; 5 | import axios from "axios"; 6 | 7 | axios.defaults.baseURL = process.env.REACT_APP_BACKEND_URL; 8 | 9 | const root = ReactDOM.createRoot( 10 | document.getElementById('root') as HTMLElement 11 | ); 12 | root.render( 13 | 14 | 15 | 16 | ); 17 | 18 | // If you want to start measuring performance in your app, pass a function 19 | // to log results (for example: reportWebVitals(console.log)) 20 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 21 | reportWebVitals(); 22 | -------------------------------------------------------------------------------- /client/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /client/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /client/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ChatGPT Web Application 2 | 3 | A web application that allows users to interact with OpenAI's GPT-3 language model through a simple and user-friendly interface. 4 | This app is for demo purpose to test OpenAI API and may contain issues/bugs. 5 | 6 | If you are looking for a simple HTML/vanilla JavaScript version, check [here](https://github.com/ioanmo226/chatgpt-web-application) 7 | 8 | ![Demo Gif](/client/src/img/demo2.gif) 9 | 10 | Buy Me A Coffee 11 | 12 | 13 | ## Features 14 | - User-friendly interface for making requests to the OpenAI API 15 | - Responses are displayed in a chat-like format 16 | - Select Models (Davinci, Codex, Create Image) based on your needs 17 | - Highlight code syntax 18 | 19 | ## Technologies Used 20 | - For client, I used React.js. 21 | - For server, I used express. 22 | 23 | ## Setup Introduction 24 | This guide will help you set up the repository on your local machine. Please follow these steps carefully to ensure a smooth setup process. 25 | 26 | ### Cloning the repository 27 | Use the following command to clone the repository: 28 | ```sh 29 | git clone https://github.com/ioanmo226/chatgpt-web-application 30 | ``` 31 | 32 | ### Backend Setup 33 | 34 | - Navigate to server directory 35 | ```sh 36 | cd server # Navigate to the server directory: 37 | ``` 38 | - Install dependencies 39 | ```sh 40 | npm install #install the backend dependencies 41 | ``` 42 | - Set the OPENAI_API_KEY in the .env file: 43 | ```sh 44 | OPENAI_API_KEY=YOUR_OPENAI_API_KEY 45 | ``` 46 | 47 | - Start the backend server by running the following command: 48 | ```sh 49 | node index.js 50 | ``` 51 | 52 | ### Frontend Setup 53 | 54 | - Navigate to the client directory: 55 | ```sh 56 | cd client 57 | ``` 58 | 59 | - Run the following command to install the frontend dependencies: 60 | ```sh 61 | npm install 62 | ``` 63 | 64 | - Set the `REACT_APP_BACKEND_URL` in the `.env` file to the URL of your backend server. For local development, use the following URL: 65 | ```sh 66 | REACT_APP_BACKEND_URL=http://localhost:3001/ 67 | ``` 68 | 69 | - Start the frontend app by running the following command: 70 | ```sh 71 | npm start 72 | ``` 73 | 74 | ### Hosting Backend and Frontend in Same Port/URL 75 | 76 | If you wish to host both the backend and frontend on the same port/URL, follow these steps: 77 | 78 | - Build the frontend by running the following command in the `client` directory: 79 | ```sh 80 | npm run build 81 | ``` 82 | - Copy the `build` directory to the `server` directory and rename it to `frontend`. 83 | 84 | - Start the backend server using the instructions in the "Backend Setup" section. 85 | 86 | - Once the setup process is complete, the frontend will be accessible at the URL of your backend server. 87 | 88 | ## Usage 89 | - Type in the input field and press enter or click on the send button to make a request to the OpenAI API 90 | - Use control+enter to add line breaks in the input field 91 | - Responses are displayed in the chat-like format on top of the page 92 | - Generate code, including translating natural language to code 93 | - You can also create AI images using DALL·E models 94 | 95 | ## Contributing 96 | 97 | This project welcomes contributions and suggestions for improvements. If you have any ideas, please feel free to open an issue or create a pull request. 98 | 99 | Thank you for your consideration. 100 | 101 | 102 | -------------------------------------------------------------------------------- /server/.env.sample: -------------------------------------------------------------------------------- 1 | OPENAI_API_KEY= -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .env -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const {Configuration, OpenAIApi} = require("openai"); 3 | const app = express(); 4 | const cors = require('cors'); 5 | require("dotenv").config(); 6 | const configuration = new Configuration({ 7 | apiKey: process.env.OPENAI_API_KEY, 8 | }); 9 | const openai = new OpenAIApi(configuration); 10 | 11 | app.use(cors()); 12 | app.use(express.json()); 13 | app.use('/', express.static(__dirname + '/frontend')); // Serves resources from client folder 14 | 15 | app.post('/get-prompt-result', async (req, res) => { 16 | // Get the prompt from the request body 17 | const {prompt, model = 'gpt'} = req.body; 18 | 19 | // Check if prompt is present in the request 20 | if (!prompt) { 21 | // Send a 400 status code and a message indicating that the prompt is missing 22 | return res.status(400).send({error: 'Prompt is missing in the request'}); 23 | } 24 | 25 | try { 26 | // Use the OpenAI SDK to create a completion 27 | // with the given prompt, model and maximum tokens 28 | if (model === 'image') { 29 | const result = await openai.createImage({ 30 | prompt, 31 | response_format: 'url', 32 | size: '512x512' 33 | }); 34 | return res.send(result.data.data[0].url); 35 | } 36 | const completion = await openai.createCompletion({ 37 | model: model === 'gpt' ? "text-davinci-003" : 'code-davinci-002', // model name 38 | prompt: `Please reply below question in markdown format.\n ${prompt}`, // input prompt 39 | max_tokens: model === 'gpt' ? 4000 : 8000 // Use max 8000 tokens for codex model 40 | }); 41 | // Send the generated text as the response 42 | return res.send(completion.data.choices[0].text); 43 | } catch (error) { 44 | const errorMsg = error.response ? error.response.data.error : `${error}`; 45 | console.error(errorMsg); 46 | // Send a 500 status code and the error message as the response 47 | return res.status(500).send(errorMsg); 48 | } 49 | }); 50 | 51 | const port = process.env.PORT || 3001; 52 | app.listen(port, () => console.log(`Listening on port ${port}`)); 53 | -------------------------------------------------------------------------------- /server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chatgpt-server", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "chatgpt-server", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cors": "^2.8.5", 13 | "dotenv": "^16.0.3", 14 | "express": "^4.18.2", 15 | "openai": "^3.1.0" 16 | } 17 | }, 18 | "node_modules/accepts": { 19 | "version": "1.3.8", 20 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 21 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 22 | "dependencies": { 23 | "mime-types": "~2.1.34", 24 | "negotiator": "0.6.3" 25 | }, 26 | "engines": { 27 | "node": ">= 0.6" 28 | } 29 | }, 30 | "node_modules/array-flatten": { 31 | "version": "1.1.1", 32 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 33 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 34 | }, 35 | "node_modules/asynckit": { 36 | "version": "0.4.0", 37 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 38 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 39 | }, 40 | "node_modules/axios": { 41 | "version": "0.26.1", 42 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", 43 | "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", 44 | "dependencies": { 45 | "follow-redirects": "^1.14.8" 46 | } 47 | }, 48 | "node_modules/body-parser": { 49 | "version": "1.20.1", 50 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 51 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 52 | "dependencies": { 53 | "bytes": "3.1.2", 54 | "content-type": "~1.0.4", 55 | "debug": "2.6.9", 56 | "depd": "2.0.0", 57 | "destroy": "1.2.0", 58 | "http-errors": "2.0.0", 59 | "iconv-lite": "0.4.24", 60 | "on-finished": "2.4.1", 61 | "qs": "6.11.0", 62 | "raw-body": "2.5.1", 63 | "type-is": "~1.6.18", 64 | "unpipe": "1.0.0" 65 | }, 66 | "engines": { 67 | "node": ">= 0.8", 68 | "npm": "1.2.8000 || >= 1.4.16" 69 | } 70 | }, 71 | "node_modules/bytes": { 72 | "version": "3.1.2", 73 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 74 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 75 | "engines": { 76 | "node": ">= 0.8" 77 | } 78 | }, 79 | "node_modules/call-bind": { 80 | "version": "1.0.2", 81 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 82 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 83 | "dependencies": { 84 | "function-bind": "^1.1.1", 85 | "get-intrinsic": "^1.0.2" 86 | }, 87 | "funding": { 88 | "url": "https://github.com/sponsors/ljharb" 89 | } 90 | }, 91 | "node_modules/combined-stream": { 92 | "version": "1.0.8", 93 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 94 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 95 | "dependencies": { 96 | "delayed-stream": "~1.0.0" 97 | }, 98 | "engines": { 99 | "node": ">= 0.8" 100 | } 101 | }, 102 | "node_modules/content-disposition": { 103 | "version": "0.5.4", 104 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 105 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 106 | "dependencies": { 107 | "safe-buffer": "5.2.1" 108 | }, 109 | "engines": { 110 | "node": ">= 0.6" 111 | } 112 | }, 113 | "node_modules/content-type": { 114 | "version": "1.0.4", 115 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 116 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 117 | "engines": { 118 | "node": ">= 0.6" 119 | } 120 | }, 121 | "node_modules/cookie": { 122 | "version": "0.5.0", 123 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 124 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 125 | "engines": { 126 | "node": ">= 0.6" 127 | } 128 | }, 129 | "node_modules/cookie-signature": { 130 | "version": "1.0.6", 131 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 132 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 133 | }, 134 | "node_modules/cors": { 135 | "version": "2.8.5", 136 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 137 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 138 | "dependencies": { 139 | "object-assign": "^4", 140 | "vary": "^1" 141 | }, 142 | "engines": { 143 | "node": ">= 0.10" 144 | } 145 | }, 146 | "node_modules/debug": { 147 | "version": "2.6.9", 148 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 149 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 150 | "dependencies": { 151 | "ms": "2.0.0" 152 | } 153 | }, 154 | "node_modules/delayed-stream": { 155 | "version": "1.0.0", 156 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 157 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 158 | "engines": { 159 | "node": ">=0.4.0" 160 | } 161 | }, 162 | "node_modules/depd": { 163 | "version": "2.0.0", 164 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 165 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 166 | "engines": { 167 | "node": ">= 0.8" 168 | } 169 | }, 170 | "node_modules/destroy": { 171 | "version": "1.2.0", 172 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 173 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 174 | "engines": { 175 | "node": ">= 0.8", 176 | "npm": "1.2.8000 || >= 1.4.16" 177 | } 178 | }, 179 | "node_modules/dotenv": { 180 | "version": "16.0.3", 181 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", 182 | "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", 183 | "engines": { 184 | "node": ">=12" 185 | } 186 | }, 187 | "node_modules/ee-first": { 188 | "version": "1.1.1", 189 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 190 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 191 | }, 192 | "node_modules/encodeurl": { 193 | "version": "1.0.2", 194 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 195 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 196 | "engines": { 197 | "node": ">= 0.8" 198 | } 199 | }, 200 | "node_modules/escape-html": { 201 | "version": "1.0.3", 202 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 203 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 204 | }, 205 | "node_modules/etag": { 206 | "version": "1.8.1", 207 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 208 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 209 | "engines": { 210 | "node": ">= 0.6" 211 | } 212 | }, 213 | "node_modules/express": { 214 | "version": "4.18.2", 215 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 216 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 217 | "dependencies": { 218 | "accepts": "~1.3.8", 219 | "array-flatten": "1.1.1", 220 | "body-parser": "1.20.1", 221 | "content-disposition": "0.5.4", 222 | "content-type": "~1.0.4", 223 | "cookie": "0.5.0", 224 | "cookie-signature": "1.0.6", 225 | "debug": "2.6.9", 226 | "depd": "2.0.0", 227 | "encodeurl": "~1.0.2", 228 | "escape-html": "~1.0.3", 229 | "etag": "~1.8.1", 230 | "finalhandler": "1.2.0", 231 | "fresh": "0.5.2", 232 | "http-errors": "2.0.0", 233 | "merge-descriptors": "1.0.1", 234 | "methods": "~1.1.2", 235 | "on-finished": "2.4.1", 236 | "parseurl": "~1.3.3", 237 | "path-to-regexp": "0.1.7", 238 | "proxy-addr": "~2.0.7", 239 | "qs": "6.11.0", 240 | "range-parser": "~1.2.1", 241 | "safe-buffer": "5.2.1", 242 | "send": "0.18.0", 243 | "serve-static": "1.15.0", 244 | "setprototypeof": "1.2.0", 245 | "statuses": "2.0.1", 246 | "type-is": "~1.6.18", 247 | "utils-merge": "1.0.1", 248 | "vary": "~1.1.2" 249 | }, 250 | "engines": { 251 | "node": ">= 0.10.0" 252 | } 253 | }, 254 | "node_modules/finalhandler": { 255 | "version": "1.2.0", 256 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 257 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 258 | "dependencies": { 259 | "debug": "2.6.9", 260 | "encodeurl": "~1.0.2", 261 | "escape-html": "~1.0.3", 262 | "on-finished": "2.4.1", 263 | "parseurl": "~1.3.3", 264 | "statuses": "2.0.1", 265 | "unpipe": "~1.0.0" 266 | }, 267 | "engines": { 268 | "node": ">= 0.8" 269 | } 270 | }, 271 | "node_modules/follow-redirects": { 272 | "version": "1.15.2", 273 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", 274 | "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", 275 | "funding": [ 276 | { 277 | "type": "individual", 278 | "url": "https://github.com/sponsors/RubenVerborgh" 279 | } 280 | ], 281 | "engines": { 282 | "node": ">=4.0" 283 | }, 284 | "peerDependenciesMeta": { 285 | "debug": { 286 | "optional": true 287 | } 288 | } 289 | }, 290 | "node_modules/form-data": { 291 | "version": "4.0.0", 292 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 293 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 294 | "dependencies": { 295 | "asynckit": "^0.4.0", 296 | "combined-stream": "^1.0.8", 297 | "mime-types": "^2.1.12" 298 | }, 299 | "engines": { 300 | "node": ">= 6" 301 | } 302 | }, 303 | "node_modules/forwarded": { 304 | "version": "0.2.0", 305 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 306 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 307 | "engines": { 308 | "node": ">= 0.6" 309 | } 310 | }, 311 | "node_modules/fresh": { 312 | "version": "0.5.2", 313 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 314 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 315 | "engines": { 316 | "node": ">= 0.6" 317 | } 318 | }, 319 | "node_modules/function-bind": { 320 | "version": "1.1.1", 321 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 322 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 323 | }, 324 | "node_modules/get-intrinsic": { 325 | "version": "1.2.0", 326 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 327 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 328 | "dependencies": { 329 | "function-bind": "^1.1.1", 330 | "has": "^1.0.3", 331 | "has-symbols": "^1.0.3" 332 | }, 333 | "funding": { 334 | "url": "https://github.com/sponsors/ljharb" 335 | } 336 | }, 337 | "node_modules/has": { 338 | "version": "1.0.3", 339 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 340 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 341 | "dependencies": { 342 | "function-bind": "^1.1.1" 343 | }, 344 | "engines": { 345 | "node": ">= 0.4.0" 346 | } 347 | }, 348 | "node_modules/has-symbols": { 349 | "version": "1.0.3", 350 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 351 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 352 | "engines": { 353 | "node": ">= 0.4" 354 | }, 355 | "funding": { 356 | "url": "https://github.com/sponsors/ljharb" 357 | } 358 | }, 359 | "node_modules/http-errors": { 360 | "version": "2.0.0", 361 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 362 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 363 | "dependencies": { 364 | "depd": "2.0.0", 365 | "inherits": "2.0.4", 366 | "setprototypeof": "1.2.0", 367 | "statuses": "2.0.1", 368 | "toidentifier": "1.0.1" 369 | }, 370 | "engines": { 371 | "node": ">= 0.8" 372 | } 373 | }, 374 | "node_modules/iconv-lite": { 375 | "version": "0.4.24", 376 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 377 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 378 | "dependencies": { 379 | "safer-buffer": ">= 2.1.2 < 3" 380 | }, 381 | "engines": { 382 | "node": ">=0.10.0" 383 | } 384 | }, 385 | "node_modules/inherits": { 386 | "version": "2.0.4", 387 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 388 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 389 | }, 390 | "node_modules/ipaddr.js": { 391 | "version": "1.9.1", 392 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 393 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 394 | "engines": { 395 | "node": ">= 0.10" 396 | } 397 | }, 398 | "node_modules/media-typer": { 399 | "version": "0.3.0", 400 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 401 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 402 | "engines": { 403 | "node": ">= 0.6" 404 | } 405 | }, 406 | "node_modules/merge-descriptors": { 407 | "version": "1.0.1", 408 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 409 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 410 | }, 411 | "node_modules/methods": { 412 | "version": "1.1.2", 413 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 414 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 415 | "engines": { 416 | "node": ">= 0.6" 417 | } 418 | }, 419 | "node_modules/mime": { 420 | "version": "1.6.0", 421 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 422 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 423 | "bin": { 424 | "mime": "cli.js" 425 | }, 426 | "engines": { 427 | "node": ">=4" 428 | } 429 | }, 430 | "node_modules/mime-db": { 431 | "version": "1.52.0", 432 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 433 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 434 | "engines": { 435 | "node": ">= 0.6" 436 | } 437 | }, 438 | "node_modules/mime-types": { 439 | "version": "2.1.35", 440 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 441 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 442 | "dependencies": { 443 | "mime-db": "1.52.0" 444 | }, 445 | "engines": { 446 | "node": ">= 0.6" 447 | } 448 | }, 449 | "node_modules/ms": { 450 | "version": "2.0.0", 451 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 452 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 453 | }, 454 | "node_modules/negotiator": { 455 | "version": "0.6.3", 456 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 457 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 458 | "engines": { 459 | "node": ">= 0.6" 460 | } 461 | }, 462 | "node_modules/object-assign": { 463 | "version": "4.1.1", 464 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 465 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 466 | "engines": { 467 | "node": ">=0.10.0" 468 | } 469 | }, 470 | "node_modules/object-inspect": { 471 | "version": "1.12.3", 472 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 473 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", 474 | "funding": { 475 | "url": "https://github.com/sponsors/ljharb" 476 | } 477 | }, 478 | "node_modules/on-finished": { 479 | "version": "2.4.1", 480 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 481 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 482 | "dependencies": { 483 | "ee-first": "1.1.1" 484 | }, 485 | "engines": { 486 | "node": ">= 0.8" 487 | } 488 | }, 489 | "node_modules/openai": { 490 | "version": "3.1.0", 491 | "resolved": "https://registry.npmjs.org/openai/-/openai-3.1.0.tgz", 492 | "integrity": "sha512-v5kKFH5o+8ld+t0arudj833Mgm3GcgBnbyN9946bj6u7bvel4Yg6YFz2A4HLIYDzmMjIo0s6vSG9x73kOwvdCg==", 493 | "dependencies": { 494 | "axios": "^0.26.0", 495 | "form-data": "^4.0.0" 496 | } 497 | }, 498 | "node_modules/parseurl": { 499 | "version": "1.3.3", 500 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 501 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 502 | "engines": { 503 | "node": ">= 0.8" 504 | } 505 | }, 506 | "node_modules/path-to-regexp": { 507 | "version": "0.1.7", 508 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 509 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 510 | }, 511 | "node_modules/proxy-addr": { 512 | "version": "2.0.7", 513 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 514 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 515 | "dependencies": { 516 | "forwarded": "0.2.0", 517 | "ipaddr.js": "1.9.1" 518 | }, 519 | "engines": { 520 | "node": ">= 0.10" 521 | } 522 | }, 523 | "node_modules/qs": { 524 | "version": "6.11.0", 525 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 526 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 527 | "dependencies": { 528 | "side-channel": "^1.0.4" 529 | }, 530 | "engines": { 531 | "node": ">=0.6" 532 | }, 533 | "funding": { 534 | "url": "https://github.com/sponsors/ljharb" 535 | } 536 | }, 537 | "node_modules/range-parser": { 538 | "version": "1.2.1", 539 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 540 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 541 | "engines": { 542 | "node": ">= 0.6" 543 | } 544 | }, 545 | "node_modules/raw-body": { 546 | "version": "2.5.1", 547 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 548 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 549 | "dependencies": { 550 | "bytes": "3.1.2", 551 | "http-errors": "2.0.0", 552 | "iconv-lite": "0.4.24", 553 | "unpipe": "1.0.0" 554 | }, 555 | "engines": { 556 | "node": ">= 0.8" 557 | } 558 | }, 559 | "node_modules/safe-buffer": { 560 | "version": "5.2.1", 561 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 562 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 563 | "funding": [ 564 | { 565 | "type": "github", 566 | "url": "https://github.com/sponsors/feross" 567 | }, 568 | { 569 | "type": "patreon", 570 | "url": "https://www.patreon.com/feross" 571 | }, 572 | { 573 | "type": "consulting", 574 | "url": "https://feross.org/support" 575 | } 576 | ] 577 | }, 578 | "node_modules/safer-buffer": { 579 | "version": "2.1.2", 580 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 581 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 582 | }, 583 | "node_modules/send": { 584 | "version": "0.18.0", 585 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 586 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 587 | "dependencies": { 588 | "debug": "2.6.9", 589 | "depd": "2.0.0", 590 | "destroy": "1.2.0", 591 | "encodeurl": "~1.0.2", 592 | "escape-html": "~1.0.3", 593 | "etag": "~1.8.1", 594 | "fresh": "0.5.2", 595 | "http-errors": "2.0.0", 596 | "mime": "1.6.0", 597 | "ms": "2.1.3", 598 | "on-finished": "2.4.1", 599 | "range-parser": "~1.2.1", 600 | "statuses": "2.0.1" 601 | }, 602 | "engines": { 603 | "node": ">= 0.8.0" 604 | } 605 | }, 606 | "node_modules/send/node_modules/ms": { 607 | "version": "2.1.3", 608 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 609 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 610 | }, 611 | "node_modules/serve-static": { 612 | "version": "1.15.0", 613 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 614 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 615 | "dependencies": { 616 | "encodeurl": "~1.0.2", 617 | "escape-html": "~1.0.3", 618 | "parseurl": "~1.3.3", 619 | "send": "0.18.0" 620 | }, 621 | "engines": { 622 | "node": ">= 0.8.0" 623 | } 624 | }, 625 | "node_modules/setprototypeof": { 626 | "version": "1.2.0", 627 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 628 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 629 | }, 630 | "node_modules/side-channel": { 631 | "version": "1.0.4", 632 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 633 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 634 | "dependencies": { 635 | "call-bind": "^1.0.0", 636 | "get-intrinsic": "^1.0.2", 637 | "object-inspect": "^1.9.0" 638 | }, 639 | "funding": { 640 | "url": "https://github.com/sponsors/ljharb" 641 | } 642 | }, 643 | "node_modules/statuses": { 644 | "version": "2.0.1", 645 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 646 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 647 | "engines": { 648 | "node": ">= 0.8" 649 | } 650 | }, 651 | "node_modules/toidentifier": { 652 | "version": "1.0.1", 653 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 654 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 655 | "engines": { 656 | "node": ">=0.6" 657 | } 658 | }, 659 | "node_modules/type-is": { 660 | "version": "1.6.18", 661 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 662 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 663 | "dependencies": { 664 | "media-typer": "0.3.0", 665 | "mime-types": "~2.1.24" 666 | }, 667 | "engines": { 668 | "node": ">= 0.6" 669 | } 670 | }, 671 | "node_modules/unpipe": { 672 | "version": "1.0.0", 673 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 674 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 675 | "engines": { 676 | "node": ">= 0.8" 677 | } 678 | }, 679 | "node_modules/utils-merge": { 680 | "version": "1.0.1", 681 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 682 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 683 | "engines": { 684 | "node": ">= 0.4.0" 685 | } 686 | }, 687 | "node_modules/vary": { 688 | "version": "1.1.2", 689 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 690 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 691 | "engines": { 692 | "node": ">= 0.8" 693 | } 694 | } 695 | }, 696 | "dependencies": { 697 | "accepts": { 698 | "version": "1.3.8", 699 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 700 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 701 | "requires": { 702 | "mime-types": "~2.1.34", 703 | "negotiator": "0.6.3" 704 | } 705 | }, 706 | "array-flatten": { 707 | "version": "1.1.1", 708 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 709 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 710 | }, 711 | "asynckit": { 712 | "version": "0.4.0", 713 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 714 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 715 | }, 716 | "axios": { 717 | "version": "0.26.1", 718 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", 719 | "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", 720 | "requires": { 721 | "follow-redirects": "^1.14.8" 722 | } 723 | }, 724 | "body-parser": { 725 | "version": "1.20.1", 726 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 727 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 728 | "requires": { 729 | "bytes": "3.1.2", 730 | "content-type": "~1.0.4", 731 | "debug": "2.6.9", 732 | "depd": "2.0.0", 733 | "destroy": "1.2.0", 734 | "http-errors": "2.0.0", 735 | "iconv-lite": "0.4.24", 736 | "on-finished": "2.4.1", 737 | "qs": "6.11.0", 738 | "raw-body": "2.5.1", 739 | "type-is": "~1.6.18", 740 | "unpipe": "1.0.0" 741 | } 742 | }, 743 | "bytes": { 744 | "version": "3.1.2", 745 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 746 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 747 | }, 748 | "call-bind": { 749 | "version": "1.0.2", 750 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 751 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 752 | "requires": { 753 | "function-bind": "^1.1.1", 754 | "get-intrinsic": "^1.0.2" 755 | } 756 | }, 757 | "combined-stream": { 758 | "version": "1.0.8", 759 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 760 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 761 | "requires": { 762 | "delayed-stream": "~1.0.0" 763 | } 764 | }, 765 | "content-disposition": { 766 | "version": "0.5.4", 767 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 768 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 769 | "requires": { 770 | "safe-buffer": "5.2.1" 771 | } 772 | }, 773 | "content-type": { 774 | "version": "1.0.4", 775 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 776 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 777 | }, 778 | "cookie": { 779 | "version": "0.5.0", 780 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 781 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" 782 | }, 783 | "cookie-signature": { 784 | "version": "1.0.6", 785 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 786 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 787 | }, 788 | "cors": { 789 | "version": "2.8.5", 790 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 791 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 792 | "requires": { 793 | "object-assign": "^4", 794 | "vary": "^1" 795 | } 796 | }, 797 | "debug": { 798 | "version": "2.6.9", 799 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 800 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 801 | "requires": { 802 | "ms": "2.0.0" 803 | } 804 | }, 805 | "delayed-stream": { 806 | "version": "1.0.0", 807 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 808 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" 809 | }, 810 | "depd": { 811 | "version": "2.0.0", 812 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 813 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 814 | }, 815 | "destroy": { 816 | "version": "1.2.0", 817 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 818 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 819 | }, 820 | "dotenv": { 821 | "version": "16.0.3", 822 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", 823 | "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" 824 | }, 825 | "ee-first": { 826 | "version": "1.1.1", 827 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 828 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 829 | }, 830 | "encodeurl": { 831 | "version": "1.0.2", 832 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 833 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 834 | }, 835 | "escape-html": { 836 | "version": "1.0.3", 837 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 838 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 839 | }, 840 | "etag": { 841 | "version": "1.8.1", 842 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 843 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 844 | }, 845 | "express": { 846 | "version": "4.18.2", 847 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 848 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 849 | "requires": { 850 | "accepts": "~1.3.8", 851 | "array-flatten": "1.1.1", 852 | "body-parser": "1.20.1", 853 | "content-disposition": "0.5.4", 854 | "content-type": "~1.0.4", 855 | "cookie": "0.5.0", 856 | "cookie-signature": "1.0.6", 857 | "debug": "2.6.9", 858 | "depd": "2.0.0", 859 | "encodeurl": "~1.0.2", 860 | "escape-html": "~1.0.3", 861 | "etag": "~1.8.1", 862 | "finalhandler": "1.2.0", 863 | "fresh": "0.5.2", 864 | "http-errors": "2.0.0", 865 | "merge-descriptors": "1.0.1", 866 | "methods": "~1.1.2", 867 | "on-finished": "2.4.1", 868 | "parseurl": "~1.3.3", 869 | "path-to-regexp": "0.1.7", 870 | "proxy-addr": "~2.0.7", 871 | "qs": "6.11.0", 872 | "range-parser": "~1.2.1", 873 | "safe-buffer": "5.2.1", 874 | "send": "0.18.0", 875 | "serve-static": "1.15.0", 876 | "setprototypeof": "1.2.0", 877 | "statuses": "2.0.1", 878 | "type-is": "~1.6.18", 879 | "utils-merge": "1.0.1", 880 | "vary": "~1.1.2" 881 | } 882 | }, 883 | "finalhandler": { 884 | "version": "1.2.0", 885 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 886 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 887 | "requires": { 888 | "debug": "2.6.9", 889 | "encodeurl": "~1.0.2", 890 | "escape-html": "~1.0.3", 891 | "on-finished": "2.4.1", 892 | "parseurl": "~1.3.3", 893 | "statuses": "2.0.1", 894 | "unpipe": "~1.0.0" 895 | } 896 | }, 897 | "follow-redirects": { 898 | "version": "1.15.2", 899 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", 900 | "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" 901 | }, 902 | "form-data": { 903 | "version": "4.0.0", 904 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 905 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 906 | "requires": { 907 | "asynckit": "^0.4.0", 908 | "combined-stream": "^1.0.8", 909 | "mime-types": "^2.1.12" 910 | } 911 | }, 912 | "forwarded": { 913 | "version": "0.2.0", 914 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 915 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 916 | }, 917 | "fresh": { 918 | "version": "0.5.2", 919 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 920 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 921 | }, 922 | "function-bind": { 923 | "version": "1.1.1", 924 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 925 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 926 | }, 927 | "get-intrinsic": { 928 | "version": "1.2.0", 929 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 930 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 931 | "requires": { 932 | "function-bind": "^1.1.1", 933 | "has": "^1.0.3", 934 | "has-symbols": "^1.0.3" 935 | } 936 | }, 937 | "has": { 938 | "version": "1.0.3", 939 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 940 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 941 | "requires": { 942 | "function-bind": "^1.1.1" 943 | } 944 | }, 945 | "has-symbols": { 946 | "version": "1.0.3", 947 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 948 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 949 | }, 950 | "http-errors": { 951 | "version": "2.0.0", 952 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 953 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 954 | "requires": { 955 | "depd": "2.0.0", 956 | "inherits": "2.0.4", 957 | "setprototypeof": "1.2.0", 958 | "statuses": "2.0.1", 959 | "toidentifier": "1.0.1" 960 | } 961 | }, 962 | "iconv-lite": { 963 | "version": "0.4.24", 964 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 965 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 966 | "requires": { 967 | "safer-buffer": ">= 2.1.2 < 3" 968 | } 969 | }, 970 | "inherits": { 971 | "version": "2.0.4", 972 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 973 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 974 | }, 975 | "ipaddr.js": { 976 | "version": "1.9.1", 977 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 978 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 979 | }, 980 | "media-typer": { 981 | "version": "0.3.0", 982 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 983 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" 984 | }, 985 | "merge-descriptors": { 986 | "version": "1.0.1", 987 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 988 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 989 | }, 990 | "methods": { 991 | "version": "1.1.2", 992 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 993 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" 994 | }, 995 | "mime": { 996 | "version": "1.6.0", 997 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 998 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 999 | }, 1000 | "mime-db": { 1001 | "version": "1.52.0", 1002 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1003 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 1004 | }, 1005 | "mime-types": { 1006 | "version": "2.1.35", 1007 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1008 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1009 | "requires": { 1010 | "mime-db": "1.52.0" 1011 | } 1012 | }, 1013 | "ms": { 1014 | "version": "2.0.0", 1015 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1016 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 1017 | }, 1018 | "negotiator": { 1019 | "version": "0.6.3", 1020 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1021 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 1022 | }, 1023 | "object-assign": { 1024 | "version": "4.1.1", 1025 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1026 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" 1027 | }, 1028 | "object-inspect": { 1029 | "version": "1.12.3", 1030 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 1031 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" 1032 | }, 1033 | "on-finished": { 1034 | "version": "2.4.1", 1035 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1036 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1037 | "requires": { 1038 | "ee-first": "1.1.1" 1039 | } 1040 | }, 1041 | "openai": { 1042 | "version": "3.1.0", 1043 | "resolved": "https://registry.npmjs.org/openai/-/openai-3.1.0.tgz", 1044 | "integrity": "sha512-v5kKFH5o+8ld+t0arudj833Mgm3GcgBnbyN9946bj6u7bvel4Yg6YFz2A4HLIYDzmMjIo0s6vSG9x73kOwvdCg==", 1045 | "requires": { 1046 | "axios": "^0.26.0", 1047 | "form-data": "^4.0.0" 1048 | } 1049 | }, 1050 | "parseurl": { 1051 | "version": "1.3.3", 1052 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1053 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1054 | }, 1055 | "path-to-regexp": { 1056 | "version": "0.1.7", 1057 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1058 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 1059 | }, 1060 | "proxy-addr": { 1061 | "version": "2.0.7", 1062 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1063 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1064 | "requires": { 1065 | "forwarded": "0.2.0", 1066 | "ipaddr.js": "1.9.1" 1067 | } 1068 | }, 1069 | "qs": { 1070 | "version": "6.11.0", 1071 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 1072 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 1073 | "requires": { 1074 | "side-channel": "^1.0.4" 1075 | } 1076 | }, 1077 | "range-parser": { 1078 | "version": "1.2.1", 1079 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1080 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1081 | }, 1082 | "raw-body": { 1083 | "version": "2.5.1", 1084 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 1085 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 1086 | "requires": { 1087 | "bytes": "3.1.2", 1088 | "http-errors": "2.0.0", 1089 | "iconv-lite": "0.4.24", 1090 | "unpipe": "1.0.0" 1091 | } 1092 | }, 1093 | "safe-buffer": { 1094 | "version": "5.2.1", 1095 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1096 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1097 | }, 1098 | "safer-buffer": { 1099 | "version": "2.1.2", 1100 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1101 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1102 | }, 1103 | "send": { 1104 | "version": "0.18.0", 1105 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 1106 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 1107 | "requires": { 1108 | "debug": "2.6.9", 1109 | "depd": "2.0.0", 1110 | "destroy": "1.2.0", 1111 | "encodeurl": "~1.0.2", 1112 | "escape-html": "~1.0.3", 1113 | "etag": "~1.8.1", 1114 | "fresh": "0.5.2", 1115 | "http-errors": "2.0.0", 1116 | "mime": "1.6.0", 1117 | "ms": "2.1.3", 1118 | "on-finished": "2.4.1", 1119 | "range-parser": "~1.2.1", 1120 | "statuses": "2.0.1" 1121 | }, 1122 | "dependencies": { 1123 | "ms": { 1124 | "version": "2.1.3", 1125 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1126 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1127 | } 1128 | } 1129 | }, 1130 | "serve-static": { 1131 | "version": "1.15.0", 1132 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 1133 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 1134 | "requires": { 1135 | "encodeurl": "~1.0.2", 1136 | "escape-html": "~1.0.3", 1137 | "parseurl": "~1.3.3", 1138 | "send": "0.18.0" 1139 | } 1140 | }, 1141 | "setprototypeof": { 1142 | "version": "1.2.0", 1143 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1144 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1145 | }, 1146 | "side-channel": { 1147 | "version": "1.0.4", 1148 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1149 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1150 | "requires": { 1151 | "call-bind": "^1.0.0", 1152 | "get-intrinsic": "^1.0.2", 1153 | "object-inspect": "^1.9.0" 1154 | } 1155 | }, 1156 | "statuses": { 1157 | "version": "2.0.1", 1158 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1159 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 1160 | }, 1161 | "toidentifier": { 1162 | "version": "1.0.1", 1163 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1164 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 1165 | }, 1166 | "type-is": { 1167 | "version": "1.6.18", 1168 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1169 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1170 | "requires": { 1171 | "media-typer": "0.3.0", 1172 | "mime-types": "~2.1.24" 1173 | } 1174 | }, 1175 | "unpipe": { 1176 | "version": "1.0.0", 1177 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1178 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" 1179 | }, 1180 | "utils-merge": { 1181 | "version": "1.0.1", 1182 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1183 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" 1184 | }, 1185 | "vary": { 1186 | "version": "1.1.2", 1187 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1188 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" 1189 | } 1190 | } 1191 | } 1192 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chatgpt-server", 3 | "version": "1.0.0", 4 | "description": "ChatGpt Server", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "chatgpt" 11 | ], 12 | "author": "Super", 13 | "license": "ISC", 14 | "dependencies": { 15 | "cors": "^2.8.5", 16 | "dotenv": "^16.0.3", 17 | "express": "^4.18.2", 18 | "openai": "^3.1.0" 19 | } 20 | } 21 | --------------------------------------------------------------------------------