├── .gitignore
├── README.md
├── server
├── .env.example
├── package.json
├── pnpm-lock.yaml
├── server.js
├── serverGPT3API.js
├── whitelist.js
└── whitelist.js.Example
└── ui
├── .eslintignore
├── .eslintrc.cjs
├── .gitignore
├── .npmrc
├── .prettierignore
├── .prettierrc
├── README.md
├── package.json
├── playwright.config.ts
├── pnpm-lock.yaml
├── postcss.config.cjs
├── src
├── DeclarationFile.d.ts
├── app.d.ts
├── app.html
├── app.postcss
├── index.test.ts
├── lib
│ ├── images
│ │ ├── banner1.jpg
│ │ ├── favicon.png
│ │ ├── github.svg
│ │ ├── svelte-logo.svg
│ │ ├── svelte-welcome.png
│ │ └── svelte-welcome.webp
│ └── styles
│ │ ├── chat.css
│ │ ├── prism-okaidia.css
│ │ └── prism-okaidiaOLD.css
└── routes
│ ├── +layout.svelte
│ ├── +page.svelte
│ ├── Header.svelte
│ ├── pageCopy1.svelte
│ ├── pageCopy2.svelte
│ ├── pageCopy3.svelte
│ ├── pageCopy4.svelte
│ ├── pageCopy5.svelte
│ └── pageCopy6.svelte
├── static
└── favicon.png
├── svelte.config.js
├── tailwind.config.cjs
├── tests
└── test.ts
├── tsconfig.json
└── vite.config.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 | # env
27 | .env
28 |
29 | # build
30 | build
31 |
32 | # test
33 | test
34 |
35 | # others:
36 | # whitelist.js
37 | servertest
38 | uitest
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # ✨ Build and Deploy Your Own ChatGPT AI Application That Will Help You
5 |
6 | 
7 |
8 | ## 📚 SETUP
9 |
10 | To Use this ChatGPT Clone AI Chatbot app built with SvelteKit (Frontend), Express.js (Backend) and Openai GPT-3 AI API, do the following:
11 |
12 | - `Star` this repo,
13 |
14 | - Then `Clone` this repo,
15 |
16 | - Finally, see the `Demo` to test the amazing `features` of the `ai chatbot app` and go through the `documentation` by enrolling for the `full course` to guide on how to set it up quickly, easily and successfully, which is `totally FREE` with support at:
17 |
18 | - [Build and Deploy AI chatbot Website Like chatGPT With Sveltekit, ExpressJs and Openai GPT-3 AI API](https://aihipuniversity.com/Svelte-SvelteKit-303-Advanced-Build-And-Deploy-Ai-Chatbot-Website?ref=AiHiPUniversity.com "FREE Full Course To get Started With AI Chatbot Development")
19 |
20 | ## 🎉 Launch your Full Stack and Web3 development career with Ai enhanced project-based courses and support
21 |
22 | [AiHiPUniversity.com](https://AiHiPUniversity.com?ref=AiHiPUniversity.com "Visit AiHiPUniversity Website")
23 |
24 | ## 📚 Star this Repository
25 |
26 | If you find this helpful,
27 |
28 | please remember to `star` the repo at the top and also share it on social media platforms.
29 |
--------------------------------------------------------------------------------
/server/.env.example:
--------------------------------------------------------------------------------
1 | # COPY AND PAST YOUR OPENAI's API KEY BELOW WITHIN THE QOUTAION MARKS.
2 | # WARNING: Your API Key is confidencial and must not be exposed on frontend or commited to public places like Github:
3 | # To avoid exposing your API key, kindly rename this file from .evn.example to .env to avoid any errors accessing it by the server,
4 | # and it will also ensure that .gitinore rules help prevent exposing your API KEY by removing it from your commit files to send to github.
5 | OPENAI_API_KEY= "COPY AND PASTE TO REPLACE THIS TEXT WITH YOUR OPENAI's API KEY"
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "foskaay-ai-server",
3 | "private": true,
4 | "version": "1.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "server": "nodemon server"
8 | },
9 | "dependencies": {
10 | "cors": "^2.8.5",
11 | "dotenv": "^16.0.3",
12 | "express": "^4.18.2",
13 | "nodemon": "^2.0.20",
14 | "openai": "^3.1.0"
15 | }
16 | }
--------------------------------------------------------------------------------
/server/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.4
2 |
3 | specifiers:
4 | cors: ^2.8.5
5 | dotenv: ^16.0.3
6 | express: ^4.18.2
7 | nodemon: ^2.0.20
8 | openai: ^3.1.0
9 |
10 | dependencies:
11 | cors: 2.8.5
12 | dotenv: 16.0.3
13 | express: 4.18.2
14 | nodemon: 2.0.20
15 | openai: 3.1.0
16 |
17 | packages:
18 |
19 | /abbrev/1.1.1:
20 | resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
21 | dev: false
22 |
23 | /accepts/1.3.8:
24 | resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
25 | engines: {node: '>= 0.6'}
26 | dependencies:
27 | mime-types: 2.1.35
28 | negotiator: 0.6.3
29 | dev: false
30 |
31 | /anymatch/3.1.3:
32 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
33 | engines: {node: '>= 8'}
34 | dependencies:
35 | normalize-path: 3.0.0
36 | picomatch: 2.3.1
37 | dev: false
38 |
39 | /array-flatten/1.1.1:
40 | resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
41 | dev: false
42 |
43 | /asynckit/0.4.0:
44 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
45 | dev: false
46 |
47 | /axios/0.26.1:
48 | resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==}
49 | dependencies:
50 | follow-redirects: 1.15.2
51 | transitivePeerDependencies:
52 | - debug
53 | dev: false
54 |
55 | /balanced-match/1.0.2:
56 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
57 | dev: false
58 |
59 | /binary-extensions/2.2.0:
60 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
61 | engines: {node: '>=8'}
62 | dev: false
63 |
64 | /body-parser/1.20.1:
65 | resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
66 | engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
67 | dependencies:
68 | bytes: 3.1.2
69 | content-type: 1.0.4
70 | debug: 2.6.9
71 | depd: 2.0.0
72 | destroy: 1.2.0
73 | http-errors: 2.0.0
74 | iconv-lite: 0.4.24
75 | on-finished: 2.4.1
76 | qs: 6.11.0
77 | raw-body: 2.5.1
78 | type-is: 1.6.18
79 | unpipe: 1.0.0
80 | transitivePeerDependencies:
81 | - supports-color
82 | dev: false
83 |
84 | /brace-expansion/1.1.11:
85 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
86 | dependencies:
87 | balanced-match: 1.0.2
88 | concat-map: 0.0.1
89 | dev: false
90 |
91 | /braces/3.0.2:
92 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
93 | engines: {node: '>=8'}
94 | dependencies:
95 | fill-range: 7.0.1
96 | dev: false
97 |
98 | /bytes/3.1.2:
99 | resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
100 | engines: {node: '>= 0.8'}
101 | dev: false
102 |
103 | /call-bind/1.0.2:
104 | resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
105 | dependencies:
106 | function-bind: 1.1.1
107 | get-intrinsic: 1.1.3
108 | dev: false
109 |
110 | /chokidar/3.5.3:
111 | resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
112 | engines: {node: '>= 8.10.0'}
113 | dependencies:
114 | anymatch: 3.1.3
115 | braces: 3.0.2
116 | glob-parent: 5.1.2
117 | is-binary-path: 2.1.0
118 | is-glob: 4.0.3
119 | normalize-path: 3.0.0
120 | readdirp: 3.6.0
121 | optionalDependencies:
122 | fsevents: 2.3.2
123 | dev: false
124 |
125 | /combined-stream/1.0.8:
126 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
127 | engines: {node: '>= 0.8'}
128 | dependencies:
129 | delayed-stream: 1.0.0
130 | dev: false
131 |
132 | /concat-map/0.0.1:
133 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
134 | dev: false
135 |
136 | /content-disposition/0.5.4:
137 | resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
138 | engines: {node: '>= 0.6'}
139 | dependencies:
140 | safe-buffer: 5.2.1
141 | dev: false
142 |
143 | /content-type/1.0.4:
144 | resolution: {integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==}
145 | engines: {node: '>= 0.6'}
146 | dev: false
147 |
148 | /cookie-signature/1.0.6:
149 | resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
150 | dev: false
151 |
152 | /cookie/0.5.0:
153 | resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
154 | engines: {node: '>= 0.6'}
155 | dev: false
156 |
157 | /cors/2.8.5:
158 | resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
159 | engines: {node: '>= 0.10'}
160 | dependencies:
161 | object-assign: 4.1.1
162 | vary: 1.1.2
163 | dev: false
164 |
165 | /debug/2.6.9:
166 | resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
167 | peerDependencies:
168 | supports-color: '*'
169 | peerDependenciesMeta:
170 | supports-color:
171 | optional: true
172 | dependencies:
173 | ms: 2.0.0
174 | dev: false
175 |
176 | /debug/3.2.7_supports-color@5.5.0:
177 | resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
178 | peerDependencies:
179 | supports-color: '*'
180 | peerDependenciesMeta:
181 | supports-color:
182 | optional: true
183 | dependencies:
184 | ms: 2.1.3
185 | supports-color: 5.5.0
186 | dev: false
187 |
188 | /delayed-stream/1.0.0:
189 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
190 | engines: {node: '>=0.4.0'}
191 | dev: false
192 |
193 | /depd/2.0.0:
194 | resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
195 | engines: {node: '>= 0.8'}
196 | dev: false
197 |
198 | /destroy/1.2.0:
199 | resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
200 | engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
201 | dev: false
202 |
203 | /dotenv/16.0.3:
204 | resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==}
205 | engines: {node: '>=12'}
206 | dev: false
207 |
208 | /ee-first/1.1.1:
209 | resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
210 | dev: false
211 |
212 | /encodeurl/1.0.2:
213 | resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
214 | engines: {node: '>= 0.8'}
215 | dev: false
216 |
217 | /escape-html/1.0.3:
218 | resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
219 | dev: false
220 |
221 | /etag/1.8.1:
222 | resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
223 | engines: {node: '>= 0.6'}
224 | dev: false
225 |
226 | /express/4.18.2:
227 | resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==}
228 | engines: {node: '>= 0.10.0'}
229 | dependencies:
230 | accepts: 1.3.8
231 | array-flatten: 1.1.1
232 | body-parser: 1.20.1
233 | content-disposition: 0.5.4
234 | content-type: 1.0.4
235 | cookie: 0.5.0
236 | cookie-signature: 1.0.6
237 | debug: 2.6.9
238 | depd: 2.0.0
239 | encodeurl: 1.0.2
240 | escape-html: 1.0.3
241 | etag: 1.8.1
242 | finalhandler: 1.2.0
243 | fresh: 0.5.2
244 | http-errors: 2.0.0
245 | merge-descriptors: 1.0.1
246 | methods: 1.1.2
247 | on-finished: 2.4.1
248 | parseurl: 1.3.3
249 | path-to-regexp: 0.1.7
250 | proxy-addr: 2.0.7
251 | qs: 6.11.0
252 | range-parser: 1.2.1
253 | safe-buffer: 5.2.1
254 | send: 0.18.0
255 | serve-static: 1.15.0
256 | setprototypeof: 1.2.0
257 | statuses: 2.0.1
258 | type-is: 1.6.18
259 | utils-merge: 1.0.1
260 | vary: 1.1.2
261 | transitivePeerDependencies:
262 | - supports-color
263 | dev: false
264 |
265 | /fill-range/7.0.1:
266 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
267 | engines: {node: '>=8'}
268 | dependencies:
269 | to-regex-range: 5.0.1
270 | dev: false
271 |
272 | /finalhandler/1.2.0:
273 | resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==}
274 | engines: {node: '>= 0.8'}
275 | dependencies:
276 | debug: 2.6.9
277 | encodeurl: 1.0.2
278 | escape-html: 1.0.3
279 | on-finished: 2.4.1
280 | parseurl: 1.3.3
281 | statuses: 2.0.1
282 | unpipe: 1.0.0
283 | transitivePeerDependencies:
284 | - supports-color
285 | dev: false
286 |
287 | /follow-redirects/1.15.2:
288 | resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
289 | engines: {node: '>=4.0'}
290 | peerDependencies:
291 | debug: '*'
292 | peerDependenciesMeta:
293 | debug:
294 | optional: true
295 | dev: false
296 |
297 | /form-data/4.0.0:
298 | resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
299 | engines: {node: '>= 6'}
300 | dependencies:
301 | asynckit: 0.4.0
302 | combined-stream: 1.0.8
303 | mime-types: 2.1.35
304 | dev: false
305 |
306 | /forwarded/0.2.0:
307 | resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
308 | engines: {node: '>= 0.6'}
309 | dev: false
310 |
311 | /fresh/0.5.2:
312 | resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
313 | engines: {node: '>= 0.6'}
314 | dev: false
315 |
316 | /fsevents/2.3.2:
317 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
318 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
319 | os: [darwin]
320 | requiresBuild: true
321 | dev: false
322 | optional: true
323 |
324 | /function-bind/1.1.1:
325 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
326 | dev: false
327 |
328 | /get-intrinsic/1.1.3:
329 | resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==}
330 | dependencies:
331 | function-bind: 1.1.1
332 | has: 1.0.3
333 | has-symbols: 1.0.3
334 | dev: false
335 |
336 | /glob-parent/5.1.2:
337 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
338 | engines: {node: '>= 6'}
339 | dependencies:
340 | is-glob: 4.0.3
341 | dev: false
342 |
343 | /has-flag/3.0.0:
344 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
345 | engines: {node: '>=4'}
346 | dev: false
347 |
348 | /has-symbols/1.0.3:
349 | resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
350 | engines: {node: '>= 0.4'}
351 | dev: false
352 |
353 | /has/1.0.3:
354 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
355 | engines: {node: '>= 0.4.0'}
356 | dependencies:
357 | function-bind: 1.1.1
358 | dev: false
359 |
360 | /http-errors/2.0.0:
361 | resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
362 | engines: {node: '>= 0.8'}
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 | dev: false
370 |
371 | /iconv-lite/0.4.24:
372 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
373 | engines: {node: '>=0.10.0'}
374 | dependencies:
375 | safer-buffer: 2.1.2
376 | dev: false
377 |
378 | /ignore-by-default/1.0.1:
379 | resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==}
380 | dev: false
381 |
382 | /inherits/2.0.4:
383 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
384 | dev: false
385 |
386 | /ipaddr.js/1.9.1:
387 | resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
388 | engines: {node: '>= 0.10'}
389 | dev: false
390 |
391 | /is-binary-path/2.1.0:
392 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
393 | engines: {node: '>=8'}
394 | dependencies:
395 | binary-extensions: 2.2.0
396 | dev: false
397 |
398 | /is-extglob/2.1.1:
399 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
400 | engines: {node: '>=0.10.0'}
401 | dev: false
402 |
403 | /is-glob/4.0.3:
404 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
405 | engines: {node: '>=0.10.0'}
406 | dependencies:
407 | is-extglob: 2.1.1
408 | dev: false
409 |
410 | /is-number/7.0.0:
411 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
412 | engines: {node: '>=0.12.0'}
413 | dev: false
414 |
415 | /media-typer/0.3.0:
416 | resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
417 | engines: {node: '>= 0.6'}
418 | dev: false
419 |
420 | /merge-descriptors/1.0.1:
421 | resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
422 | dev: false
423 |
424 | /methods/1.1.2:
425 | resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
426 | engines: {node: '>= 0.6'}
427 | dev: false
428 |
429 | /mime-db/1.52.0:
430 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
431 | engines: {node: '>= 0.6'}
432 | dev: false
433 |
434 | /mime-types/2.1.35:
435 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
436 | engines: {node: '>= 0.6'}
437 | dependencies:
438 | mime-db: 1.52.0
439 | dev: false
440 |
441 | /mime/1.6.0:
442 | resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
443 | engines: {node: '>=4'}
444 | hasBin: true
445 | dev: false
446 |
447 | /minimatch/3.1.2:
448 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
449 | dependencies:
450 | brace-expansion: 1.1.11
451 | dev: false
452 |
453 | /ms/2.0.0:
454 | resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
455 | dev: false
456 |
457 | /ms/2.1.3:
458 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
459 | dev: false
460 |
461 | /negotiator/0.6.3:
462 | resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
463 | engines: {node: '>= 0.6'}
464 | dev: false
465 |
466 | /nodemon/2.0.20:
467 | resolution: {integrity: sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==}
468 | engines: {node: '>=8.10.0'}
469 | hasBin: true
470 | dependencies:
471 | chokidar: 3.5.3
472 | debug: 3.2.7_supports-color@5.5.0
473 | ignore-by-default: 1.0.1
474 | minimatch: 3.1.2
475 | pstree.remy: 1.1.8
476 | semver: 5.7.1
477 | simple-update-notifier: 1.1.0
478 | supports-color: 5.5.0
479 | touch: 3.1.0
480 | undefsafe: 2.0.5
481 | dev: false
482 |
483 | /nopt/1.0.10:
484 | resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==}
485 | hasBin: true
486 | dependencies:
487 | abbrev: 1.1.1
488 | dev: false
489 |
490 | /normalize-path/3.0.0:
491 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
492 | engines: {node: '>=0.10.0'}
493 | dev: false
494 |
495 | /object-assign/4.1.1:
496 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
497 | engines: {node: '>=0.10.0'}
498 | dev: false
499 |
500 | /object-inspect/1.12.2:
501 | resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==}
502 | dev: false
503 |
504 | /on-finished/2.4.1:
505 | resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
506 | engines: {node: '>= 0.8'}
507 | dependencies:
508 | ee-first: 1.1.1
509 | dev: false
510 |
511 | /openai/3.1.0:
512 | resolution: {integrity: sha512-v5kKFH5o+8ld+t0arudj833Mgm3GcgBnbyN9946bj6u7bvel4Yg6YFz2A4HLIYDzmMjIo0s6vSG9x73kOwvdCg==}
513 | dependencies:
514 | axios: 0.26.1
515 | form-data: 4.0.0
516 | transitivePeerDependencies:
517 | - debug
518 | dev: false
519 |
520 | /parseurl/1.3.3:
521 | resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
522 | engines: {node: '>= 0.8'}
523 | dev: false
524 |
525 | /path-to-regexp/0.1.7:
526 | resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
527 | dev: false
528 |
529 | /picomatch/2.3.1:
530 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
531 | engines: {node: '>=8.6'}
532 | dev: false
533 |
534 | /proxy-addr/2.0.7:
535 | resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
536 | engines: {node: '>= 0.10'}
537 | dependencies:
538 | forwarded: 0.2.0
539 | ipaddr.js: 1.9.1
540 | dev: false
541 |
542 | /pstree.remy/1.1.8:
543 | resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==}
544 | dev: false
545 |
546 | /qs/6.11.0:
547 | resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
548 | engines: {node: '>=0.6'}
549 | dependencies:
550 | side-channel: 1.0.4
551 | dev: false
552 |
553 | /range-parser/1.2.1:
554 | resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
555 | engines: {node: '>= 0.6'}
556 | dev: false
557 |
558 | /raw-body/2.5.1:
559 | resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==}
560 | engines: {node: '>= 0.8'}
561 | dependencies:
562 | bytes: 3.1.2
563 | http-errors: 2.0.0
564 | iconv-lite: 0.4.24
565 | unpipe: 1.0.0
566 | dev: false
567 |
568 | /readdirp/3.6.0:
569 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
570 | engines: {node: '>=8.10.0'}
571 | dependencies:
572 | picomatch: 2.3.1
573 | dev: false
574 |
575 | /safe-buffer/5.2.1:
576 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
577 | dev: false
578 |
579 | /safer-buffer/2.1.2:
580 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
581 | dev: false
582 |
583 | /semver/5.7.1:
584 | resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
585 | hasBin: true
586 | dev: false
587 |
588 | /semver/7.0.0:
589 | resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==}
590 | hasBin: true
591 | dev: false
592 |
593 | /send/0.18.0:
594 | resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
595 | engines: {node: '>= 0.8.0'}
596 | dependencies:
597 | debug: 2.6.9
598 | depd: 2.0.0
599 | destroy: 1.2.0
600 | encodeurl: 1.0.2
601 | escape-html: 1.0.3
602 | etag: 1.8.1
603 | fresh: 0.5.2
604 | http-errors: 2.0.0
605 | mime: 1.6.0
606 | ms: 2.1.3
607 | on-finished: 2.4.1
608 | range-parser: 1.2.1
609 | statuses: 2.0.1
610 | transitivePeerDependencies:
611 | - supports-color
612 | dev: false
613 |
614 | /serve-static/1.15.0:
615 | resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==}
616 | engines: {node: '>= 0.8.0'}
617 | dependencies:
618 | encodeurl: 1.0.2
619 | escape-html: 1.0.3
620 | parseurl: 1.3.3
621 | send: 0.18.0
622 | transitivePeerDependencies:
623 | - supports-color
624 | dev: false
625 |
626 | /setprototypeof/1.2.0:
627 | resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
628 | dev: false
629 |
630 | /side-channel/1.0.4:
631 | resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
632 | dependencies:
633 | call-bind: 1.0.2
634 | get-intrinsic: 1.1.3
635 | object-inspect: 1.12.2
636 | dev: false
637 |
638 | /simple-update-notifier/1.1.0:
639 | resolution: {integrity: sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==}
640 | engines: {node: '>=8.10.0'}
641 | dependencies:
642 | semver: 7.0.0
643 | dev: false
644 |
645 | /statuses/2.0.1:
646 | resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
647 | engines: {node: '>= 0.8'}
648 | dev: false
649 |
650 | /supports-color/5.5.0:
651 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
652 | engines: {node: '>=4'}
653 | dependencies:
654 | has-flag: 3.0.0
655 | dev: false
656 |
657 | /to-regex-range/5.0.1:
658 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
659 | engines: {node: '>=8.0'}
660 | dependencies:
661 | is-number: 7.0.0
662 | dev: false
663 |
664 | /toidentifier/1.0.1:
665 | resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
666 | engines: {node: '>=0.6'}
667 | dev: false
668 |
669 | /touch/3.1.0:
670 | resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==}
671 | hasBin: true
672 | dependencies:
673 | nopt: 1.0.10
674 | dev: false
675 |
676 | /type-is/1.6.18:
677 | resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
678 | engines: {node: '>= 0.6'}
679 | dependencies:
680 | media-typer: 0.3.0
681 | mime-types: 2.1.35
682 | dev: false
683 |
684 | /undefsafe/2.0.5:
685 | resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==}
686 | dev: false
687 |
688 | /unpipe/1.0.0:
689 | resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
690 | engines: {node: '>= 0.8'}
691 | dev: false
692 |
693 | /utils-merge/1.0.1:
694 | resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
695 | engines: {node: '>= 0.4.0'}
696 | dev: false
697 |
698 | /vary/1.1.2:
699 | resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
700 | engines: {node: '>= 0.8'}
701 | dev: false
702 |
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | import express from 'express' //backend server framework
2 | import * as dotenv from 'dotenv' // access and use API KEY stored in .env file
3 | import cors from 'cors' //allow make cross origin API request to server from frontend
4 | import allowedOrigins from './whitelist.js'; //allowed domains only
5 | import { Configuration, OpenAIApi } from 'openai' //Openai API wrapper
6 | import { toChatML, get_message } from "gpt-to-chatgpt"; //using this as wrapper to make chatgpt api call work till official openai package is upgraded
7 |
8 |
9 | //call config function to give access to .env API KEY variable
10 | dotenv.config()
11 |
12 |
13 | //Openai API wrapper function which accepts API KEY as object parameter
14 | const configuration = new Configuration({
15 | apiKey: process.env.OPENAI_API_KEY,
16 | });
17 |
18 |
19 | // create instance of Openai and pass in the configuration object created above
20 | const openai = new OpenAIApi(configuration);
21 |
22 |
23 | // initialize expressjs server
24 | const app = express()
25 |
26 |
27 | // configure the cors middleware to allow accepting and processing request from allowed domains
28 | app.use(cors({
29 | origin: (origin, callback) => {
30 | // check if the origin is in the allowed origins array
31 | if (allowedOrigins.indexOf(origin) !== -1) {
32 | callback(null, true);
33 | } else {
34 | callback(new Error('Not allowed by CORS'));
35 | }
36 | }
37 | }));
38 |
39 |
40 | //middleware: allows the backend to recieve and acces request from frontend as a json object
41 | // rather than just a string.
42 | // This is necessary in the following POST request route code:
43 | // app.post('/', async (req, res) => {
44 | // try {const prompt = req.body.prompt;
45 | // where it uses req.body to get the prompt data/question sent in the post request
46 | // from our chatGPT Ai chatBot SvelteKit powered frontend
47 | app.use(express.json())
48 |
49 |
50 | // routes/endpoint to expose expressjs backend to frontend "GET" request
51 | // with a return statement of info to show user visiting the route
52 | // "started on http://localhost:5001" makes the port link clickable from terminal
53 | app.get('/', async (req, res) => {
54 | res.status(200).send({
55 | message: 'Hello Web3 AI World from Foskaay AI',
56 | })
57 | })
58 |
59 |
60 | //route/endpoint which allows Expressjs backend to recieve and process
61 | // the request sent from users of our chatGPT Ai chatBot SvelteKit powered frontend
62 | app.post('/', async (req, res) => {
63 |
64 | // check if the origin is in the allowed origins array/whitelist domains
65 | // before processing request
66 | if (!allowedOrigins.includes(req.headers.origin)) {
67 | return res.status(401).send({ message: 'Unauthorized: Origin not allowed' });
68 | }
69 |
70 | try {
71 | const prompt = req.body.prompt; //access user question submited as prompt
72 |
73 | //Initiate an API call to Openai's API to recieve response for user questions
74 | //from Openai's AI
75 | // But while making the call we bundle the user question/prompt and other
76 | // instructions to ensure we get the best response from the AI back to user
77 | openai.createChatCompletion({
78 | model: "gpt-3.5-turbo",
79 | messages: toChatML((prompt))
80 | }).then((data) => {
81 | const aiResponse = get_message(data.data);
82 | // console.log(aiResponse); // Log the response to the console for confirmation
83 | // console.log((get_message(data.data)));
84 |
85 | // Send the response back to the frontend
86 | res.status(200).send({
87 | ai: aiResponse,
88 | });
89 | });
90 |
91 |
92 | // logs error to the console and sends it back our chatGPT Ai chatBot SvelteKit powered frontend
93 | //with a status of 500 if there is any error caught in try block.
94 | } catch (error) {
95 | console.log(error);
96 | res.status(400).send({
97 | message: error.message,
98 | });
99 | }
100 | })
101 |
102 |
103 | // start the server on specified port on localhost
104 | // this get overriden when deployed to web server by the server url
105 | app.listen(5000, () => console.log('Foskaay Ai server started on http://localhost:5000'))
--------------------------------------------------------------------------------
/server/serverGPT3API.js:
--------------------------------------------------------------------------------
1 | import express from 'express' //backend server framework
2 | import * as dotenv from 'dotenv' // access and use API KEY stored in .env file
3 | import cors from 'cors' //allow make cross origin API request to server from frontend
4 | import allowedOrigins from './whitelist.js'; //allowed domains only
5 | import { Configuration, OpenAIApi } from 'openai' //Openai API wrapper
6 |
7 |
8 | //call config function to give access to .env API KEY variable
9 | dotenv.config()
10 |
11 |
12 | //Openai API wrapper function which accepts API KEY as object parameter
13 | const configuration = new Configuration({
14 | apiKey: process.env.OPENAI_API_KEY,
15 | });
16 |
17 |
18 | // create instance of Openai and pass in the configuration object created above
19 | const openai = new OpenAIApi(configuration);
20 |
21 |
22 | // initialize expressjs server
23 | const app = express()
24 |
25 |
26 | // configure the cors middleware to allow accepting and processing request from allowed domains
27 | app.use(cors({
28 | origin: (origin, callback) => {
29 | // check if the origin is in the allowed origins array
30 | if (allowedOrigins.indexOf(origin) !== -1) {
31 | callback(null, true);
32 | } else {
33 | callback(new Error('Not allowed by CORS'));
34 | }
35 | }
36 | }));
37 |
38 |
39 | //middleware: allows the backend to recieve and acces request from frontend as a json object
40 | // rather than just a string.
41 | // This is necessary in the following POST request route code:
42 | // app.post('/', async (req, res) => {
43 | // try {const prompt = req.body.prompt;
44 | // where it uses req.body to get the prompt data/question sent in the post request
45 | // from our chatGPT Ai chatBot SvelteKit powered frontend
46 | app.use(express.json())
47 |
48 |
49 | // routes/endpoint to expose expressjs backend to frontend "GET" request
50 | // with a return statement of info to show user visiting the route
51 | // "started on http://localhost:5001" makes the port link clickable from terminal
52 | app.get('/', async (req, res) => {
53 | res.status(200).send({
54 | message: 'Hello Web3 AI World from Foskaay AI',
55 | })
56 | })
57 |
58 |
59 | //route/endpoint which allows Expressjs backend to recieve and process
60 | // the request sent from users of our chatGPT Ai chatBot SvelteKit powered frontend
61 | app.post('/', async (req, res) => {
62 |
63 | // check if the origin is in the allowed origins array/whitelist domains
64 | // before processing request
65 | if (!allowedOrigins.includes(req.headers.origin)) {
66 | return res.status(401).send({ message: 'Unauthorized: Origin not allowed' });
67 | }
68 |
69 | try {
70 | const prompt = req.body.prompt; //access user question submited as prompt
71 |
72 | //Initiate an API call to Openai's API to recieve response for user questions
73 | //from Openai's AI
74 | // But while making the call we bundle the user question/prompt and other
75 | // instructions to ensure we get the best response from the AI back to user
76 | const response = await openai.createCompletion({
77 | model: "text-davinci-003", //most powerful openai large language Ai model for now
78 | prompt: `${prompt}`, //input text value of the form input box in sveltekit app ui
79 | temperature: 1, // Higher values means the model will take more risks and can change/modify response for same question when asked again.
80 | max_tokens: 3000, // If not specified, it auto limit reponses usually less than 50 character (thats about 50 words)The maximum number of tokens to generate in the completion. Most models have a context length of 2048 tokens (except for the newest models, which support over 8,000).
81 | top_p: 1, // alternative to sampling with temperature, called nucleus sampling
82 | frequency_penalty: 0.5, // Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.
83 | presence_penalty: 0, // Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.
84 | // user: "user123456", // optional but can be useful to detect user abusing your API request. You can use session ID or hash email/psw so each user is unique but still not individually identificable for openai
85 | });
86 |
87 | //Send the AI response back to user of
88 | // our chatGPT Ai chatBot SvelteKit powered frontend
89 | //in json format with a success status code of 200.
90 | res.status(200).send({
91 | ai: response.data.choices[0].text
92 | });
93 |
94 |
95 | // logs error to the console and sends it back our chatGPT Ai chatBot SvelteKit powered frontend
96 | //with a status of 500 if there is any error caught in try block.
97 | } catch (error) {
98 | console.error(error)
99 | res.status(500).send(error || 'Something went wrong communicating with Ai Foskaay');
100 | }
101 | })
102 |
103 |
104 | // start the server on specified port on localhost
105 | // this get overriden when deployed to web server by the server url
106 | app.listen(5000, () => console.log('Foskaay Ai server started on http://localhost:5000'))
--------------------------------------------------------------------------------
/server/whitelist.js:
--------------------------------------------------------------------------------
1 | // allowed origins is an array of allowed domains
2 | const allowedOrigins = ['https://foskaay.aihipuniversity.com'];
3 |
4 | export default allowedOrigins;
--------------------------------------------------------------------------------
/server/whitelist.js.Example:
--------------------------------------------------------------------------------
1 | // Rename this file from whitelist.js.Example to whitelist.js
2 | // Never allow localhost in your production server whitelist
3 | // because anyone can connect as whitelisted domain once they runing on local host
4 | //You can add as many whitelist domains as you want
5 |
6 | // allowed origins is an array of allowed domains
7 | const allowedOrigins = ['https://example.com','http://localhost:5173'];
8 |
9 | export default allowedOrigins;
10 |
--------------------------------------------------------------------------------
/ui/.eslintignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/ui/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: '@typescript-eslint/parser',
4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
5 | plugins: ['svelte3', '@typescript-eslint'],
6 | ignorePatterns: ['*.cjs'],
7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
8 | settings: {
9 | 'svelte3/typescript': () => require('typescript')
10 | },
11 | parserOptions: {
12 | sourceType: 'module',
13 | ecmaVersion: 2020
14 | },
15 | env: {
16 | browser: true,
17 | es2017: true,
18 | node: true
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/ui/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 | vite.config.js.timestamp-*
10 | vite.config.ts.timestamp-*
11 |
--------------------------------------------------------------------------------
/ui/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 |
--------------------------------------------------------------------------------
/ui/.prettierignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/ui/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": true,
3 | "singleQuote": true,
4 | "trailingComma": "none",
5 | "printWidth": 100,
6 | "plugins": ["prettier-plugin-svelte"],
7 | "pluginSearchDirs": ["."],
8 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
9 | }
10 |
--------------------------------------------------------------------------------
/ui/README.md:
--------------------------------------------------------------------------------
1 | # create-svelte
2 |
3 | Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
4 |
5 | ## Creating a project
6 |
7 | If you're seeing this, you've probably already done this step. Congrats!
8 |
9 | ```bash
10 | # create a new project in the current directory
11 | npm create svelte@latest
12 |
13 | # create a new project in my-app
14 | npm create svelte@latest my-app
15 | ```
16 |
17 | ## Developing
18 |
19 | Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
20 |
21 | ```bash
22 | npm run dev
23 |
24 | # or start the server and open the app in a new browser tab
25 | npm run dev -- --open
26 | ```
27 |
28 | ## Building
29 |
30 | To create a production version of your app:
31 |
32 | ```bash
33 | npm run build
34 | ```
35 |
36 | You can preview the production build with `npm run preview`.
37 |
38 | > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
39 |
--------------------------------------------------------------------------------
/ui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ui",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "dev": "vite dev",
7 | "build": "vite build",
8 | "preview": "vite preview",
9 | "test": "playwright test",
10 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
11 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
12 | "test:unit": "vitest",
13 | "lint": "prettier --plugin-search-dir . --check . && eslint .",
14 | "format": "prettier --plugin-search-dir . --write ."
15 | },
16 | "devDependencies": {
17 | "@playwright/test": "^1.28.1",
18 | "@sveltejs/adapter-auto": "^2.0.0",
19 | "@sveltejs/kit": "^1.5.0",
20 | "@typescript-eslint/eslint-plugin": "^5.45.0",
21 | "@typescript-eslint/parser": "^5.45.0",
22 | "eslint": "^8.28.0",
23 | "eslint-config-prettier": "^8.5.0",
24 | "eslint-plugin-svelte3": "^4.0.0",
25 | "prettier": "^2.8.0",
26 | "prettier-plugin-svelte": "^2.8.1",
27 | "svelte": "^3.54.0",
28 | "svelte-check": "^3.0.1",
29 | "svelte-prism": "^1.1.6",
30 | "tslib": "^2.4.1",
31 | "typescript": "^4.9.3",
32 | "vite": "^4.0.0",
33 | "vitest": "^0.25.3",
34 | "postcss": "^8.4.14",
35 | "postcss-load-config": "^4.0.1",
36 | "svelte-preprocess": "^4.10.7",
37 | "autoprefixer": "^10.4.7",
38 | "tailwindcss": "^3.1.5"
39 | },
40 | "type": "module",
41 | "dependencies": {
42 | "uuid": "^9.0.0"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ui/playwright.config.ts:
--------------------------------------------------------------------------------
1 | import type { PlaywrightTestConfig } from '@playwright/test';
2 |
3 | const config: PlaywrightTestConfig = {
4 | webServer: {
5 | command: 'npm run build && npm run preview',
6 | port: 4173
7 | },
8 | testDir: 'tests'
9 | };
10 |
11 | export default config;
12 |
--------------------------------------------------------------------------------
/ui/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | const tailwindcss = require('tailwindcss');
2 | const autoprefixer = require('autoprefixer');
3 |
4 | const config = {
5 | plugins: [
6 | //Some plugins, like tailwindcss/nesting, need to run before Tailwind,
7 | tailwindcss(),
8 | //But others, like autoprefixer, need to run after,
9 | autoprefixer
10 | ]
11 | };
12 |
13 | module.exports = config;
14 |
--------------------------------------------------------------------------------
/ui/src/DeclarationFile.d.ts:
--------------------------------------------------------------------------------
1 | //Declaration file to help resolve conflict between typescript and modules not identified after been properly installed.
2 | // this help resolve module not found error when importing packages modules
3 |
4 | //declare uuid package module
5 | declare module 'uuid';
6 |
7 |
--------------------------------------------------------------------------------
/ui/src/app.d.ts:
--------------------------------------------------------------------------------
1 | // See https://kit.svelte.dev/docs/types#app
2 | // for information about these interfaces
3 | declare global {
4 | namespace App {
5 | // interface Error {}
6 | // interface Locals {}
7 | // interface PageData {}
8 | // interface Platform {}
9 | }
10 | }
11 |
12 | export {};
13 |
--------------------------------------------------------------------------------
/ui/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | %sveltekit.head%
8 |
9 |
10 | %sveltekit.body%
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ui/src/app.postcss:
--------------------------------------------------------------------------------
1 | /* Write your global styles here, in PostCSS syntax */
2 | @tailwind base;
3 | @tailwind components;
4 | @tailwind utilities;
5 |
--------------------------------------------------------------------------------
/ui/src/index.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest';
2 |
3 | describe('sum test', () => {
4 | it('adds 1 + 2 to equal 3', () => {
5 | expect(1 + 2).toBe(3);
6 | });
7 | });
8 |
--------------------------------------------------------------------------------
/ui/src/lib/images/banner1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AiHiPUniversity/ai-chatbot-openai-sveltekit-boilerplate-1/abde58b12363206eae0af605ba920b67adf89c38/ui/src/lib/images/banner1.jpg
--------------------------------------------------------------------------------
/ui/src/lib/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AiHiPUniversity/ai-chatbot-openai-sveltekit-boilerplate-1/abde58b12363206eae0af605ba920b67adf89c38/ui/src/lib/images/favicon.png
--------------------------------------------------------------------------------
/ui/src/lib/images/github.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ui/src/lib/images/svelte-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ui/src/lib/images/svelte-welcome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AiHiPUniversity/ai-chatbot-openai-sveltekit-boilerplate-1/abde58b12363206eae0af605ba920b67adf89c38/ui/src/lib/images/svelte-welcome.png
--------------------------------------------------------------------------------
/ui/src/lib/images/svelte-welcome.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AiHiPUniversity/ai-chatbot-openai-sveltekit-boilerplate-1/abde58b12363206eae0af605ba920b67adf89c38/ui/src/lib/images/svelte-welcome.webp
--------------------------------------------------------------------------------
/ui/src/lib/styles/chat.css:
--------------------------------------------------------------------------------
1 | /* style the chat appearance */
2 |
3 | #new-chat {
4 | width: 100%;
5 | display: block;
6 | padding: 10px;
7 | font-size: 1.2em;
8 | background-color: #333;
9 | color: white;
10 | border: none;
11 | cursor: pointer;
12 | margin-bottom: 10px;
13 | }
14 |
15 | #prompts {
16 | display: flex;
17 | flex-wrap: wrap;
18 | }
19 |
20 | .prompts-section,
21 | .features-section {
22 | width: 50%;
23 | }
24 |
25 | .prompts-section {
26 | text-align: right;
27 | }
28 |
29 | .features-section {
30 | text-align: left;
31 | }
32 |
33 | h2 {
34 | margin: 0;
35 | }
36 |
37 | .prompt {
38 | display: block;
39 | margin: 0;
40 | padding: 5px 10px;
41 | font-size: 0.9em;
42 | background-color: #eee;
43 | color: #333;
44 | cursor: pointer;
45 | }
46 |
47 | .prompt:hover {
48 | background-color: #ddd;
49 | }
50 |
51 | ul {
52 | list-style: none;
53 | margin: 0;
54 | padding: 0;
55 | }
56 |
57 | li {
58 | margin: 5px 0;
59 | }
60 |
--------------------------------------------------------------------------------
/ui/src/lib/styles/prism-okaidia.css:
--------------------------------------------------------------------------------
1 | /*
2 | This is Prism theme used with svelte-prism
3 |
4 | Svelte-Prism: https://www.npmjs.com/package/svelte-prism
5 | --------------------------------
6 | Theme Name: prism-okaidia
7 |
8 | Css Code Link:
9 | https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/themes/prism-okaidia.min.css
10 |
11 | Css Code Link Source Map (download and copy the code to the end of this file):
12 | https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/themes/prism-okaidia.min.css
13 |
14 | */
15 |
16 | code[class*='language-'],
17 | pre[class*='language-'] {
18 | color: #f8f8f2;
19 | background: 0 0;
20 | text-shadow: 0 1px rgba(0, 0, 0, 0.3);
21 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
22 | font-size: 1em;
23 | text-align: left;
24 | white-space: pre;
25 | word-spacing: normal;
26 | word-break: normal;
27 | word-wrap: normal;
28 | line-height: 1.5;
29 | -moz-tab-size: 4;
30 | -o-tab-size: 4;
31 | tab-size: 4;
32 | -webkit-hyphens: none;
33 | -moz-hyphens: none;
34 | -ms-hyphens: none;
35 | hyphens: none;
36 | }
37 | pre[class*='language-'] {
38 | padding: 1em;
39 | margin: 0.5em 0;
40 | overflow: auto;
41 | border-radius: 0.3em;
42 | }
43 | :not(pre) > code[class*='language-'],
44 | pre[class*='language-'] {
45 | background: #272822;
46 | }
47 | :not(pre) > code[class*='language-'] {
48 | padding: 0.1em;
49 | border-radius: 0.3em;
50 | white-space: normal;
51 | }
52 | .token.cdata,
53 | .token.comment,
54 | .token.doctype,
55 | .token.prolog {
56 | color: #708090;
57 | }
58 | .token.punctuation {
59 | color: #f8f8f2;
60 | }
61 | .namespace {
62 | opacity: 0.7;
63 | }
64 | .token.constant,
65 | .token.deleted,
66 | .token.property,
67 | .token.symbol,
68 | .token.tag {
69 | color: #f92672;
70 | }
71 | .token.boolean,
72 | .token.number {
73 | color: #ae81ff;
74 | }
75 | .token.attr-name,
76 | .token.builtin,
77 | .token.char,
78 | .token.inserted,
79 | .token.selector,
80 | .token.string {
81 | color: #a6e22e;
82 | }
83 | .language-css .token.string,
84 | .style .token.string,
85 | .token.entity,
86 | .token.operator,
87 | .token.url,
88 | .token.variable {
89 | color: #f8f8f2;
90 | }
91 | .token.atrule,
92 | .token.attr-value,
93 | .token.class-name,
94 | .token.function {
95 | color: #e6db74;
96 | }
97 | .token.keyword {
98 | color: #66d9ef;
99 | }
100 | .token.important,
101 | .token.regex {
102 | color: #fd971f;
103 | }
104 | .token.bold,
105 | .token.important {
106 | font-weight: 700;
107 | }
108 | .token.italic {
109 | font-style: italic;
110 | }
111 | .token.entity {
112 | cursor: help;
113 | }
114 | /*# sourceMappingURL=prism-okaidia.min.css.map */
115 | {
116 | "version": 3,
117 | "sources": [
118 | "prism-okaidia.css"
119 | ];
120 | "names": [],
121 | "mappings": "AAMA,uBACA,sBACC,MAAO,QACP,WAAY,IACZ,YAAa,EAAE,IAAI,eACnB,YAAa,QAAQ,CAAE,MAAM,CAAE,aAAa,CAAE,aAAa,CAAE,UAC7D,UAAW,IACX,WAAY,KACZ,YAAa,IACb,aAAc,OACd,WAAY,OACZ,UAAW,OACX,YAAa,IAEb,cAAe,EACf,YAAa,EACb,SAAU,EAEV,gBAAiB,KACjB,aAAc,KACd,YAAa,KACb,QAAS,KAIV,sBACC,QAAS,IACT,OAAQ,KAAK,EACb,SAAU,KACV,cAAe,KAGhB,iCACA,sBACC,WAAY,QAIb,iCACC,QAAS,KACT,cAAe,KACf,YAAa,OAMd,aAHA,eAEA,eADA,cAGC,MAAO,QAGR,mBACC,MAAO,QAGR,WACC,QAAS,GAKV,gBAEA,eAJA,gBAGA,cAFA,WAIC,MAAO,QAGR,eACA,cACC,MAAO,QAIR,iBAGA,eADA,YAEA,gBALA,gBAEA,cAIC,MAAO,QAMR,4BACA,qBAHA,cADA,gBAEA,WAGA,gBACC,MAAO,QAGR,cACA,kBAEA,kBADA,gBAEC,MAAO,QAGR,eACC,MAAO,QAIR,iBADA,aAEC,MAAO,QAIR,YADA,iBAEC,YAAa,IAEd,cACC,WAAY,OAGb,cACC,OAAQ"
122 | }
123 |
124 | /* other custom styles not included in the default theme above */
125 |
126 | /* .code-block {
127 | Add styles for the code block here
128 | }
129 |
130 | .scrollable-code-block {
131 | Add a scrollbar to the code block
132 | overflow-y: scroll;
133 | Set a maximum height for the code block
134 | max-height: 500px;
135 | } */
--------------------------------------------------------------------------------
/ui/src/lib/styles/prism-okaidiaOLD.css:
--------------------------------------------------------------------------------
1 | /* This is Prism theme used with svelte-prism
2 | Svelte-Prism: https://www.npmjs.com/package/svelte-prism
3 | --------------------------------
4 | Theme Name: prism-okaidia
5 | Css Code Link: https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/themes/prism-okaidia.min.css
6 | */
7 |
8 | code[class*='language-'],
9 | pre[class*='language-'] {
10 | color: #f8f8f2;
11 | background: 0 0;
12 | text-shadow: 0 1px rgba(0, 0, 0, 0.3);
13 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
14 | font-size: 1em;
15 | text-align: left;
16 | white-space: pre;
17 | word-spacing: normal;
18 | word-break: normal;
19 | word-wrap: normal;
20 | line-height: 1.5;
21 | -moz-tab-size: 4;
22 | -o-tab-size: 4;
23 | tab-size: 4;
24 | -webkit-hyphens: none;
25 | -moz-hyphens: none;
26 | -ms-hyphens: none;
27 | hyphens: none;
28 | /* customization added */
29 | /* Add a scrollbar to the code block */
30 | overflow-y: scroll;
31 | /* Set a maximum height for the code block */
32 | max-height: 870px;
33 | }
34 | pre[class*='language-'] {
35 | padding: 1em;
36 | margin: 0.5em 0;
37 | overflow: auto;
38 | border-radius: 0.3em;
39 | }
40 | :not(pre) > code[class*='language-'],
41 | pre[class*='language-'] {
42 | background: #272822;
43 | }
44 | :not(pre) > code[class*='language-'] {
45 | padding: 0.1em;
46 | border-radius: 0.3em;
47 | white-space: normal;
48 | }
49 | .token.cdata,
50 | .token.comment,
51 | .token.doctype,
52 | .token.prolog {
53 | color: #708090;
54 | }
55 | .token.punctuation {
56 | color: #f8f8f2;
57 | }
58 | .namespace {
59 | opacity: 0.7;
60 | }
61 | .token.constant,
62 | .token.deleted,
63 | .token.property,
64 | .token.symbol,
65 | .token.tag {
66 | color: #f92672;
67 | }
68 | .token.boolean,
69 | .token.number {
70 | color: #ae81ff;
71 | }
72 | .token.attr-name,
73 | .token.builtin,
74 | .token.char,
75 | .token.inserted,
76 | .token.selector,
77 | .token.string {
78 | color: #a6e22e;
79 | }
80 | .language-css .token.string,
81 | .style .token.string,
82 | .token.entity,
83 | .token.operator,
84 | .token.url,
85 | .token.variable {
86 | color: #f8f8f2;
87 | }
88 | .token.atrule,
89 | .token.attr-value,
90 | .token.class-name,
91 | .token.function {
92 | color: #e6db74;
93 | }
94 | .token.keyword {
95 | color: #66d9ef;
96 | }
97 | .token.important,
98 | .token.regex {
99 | color: #fd971f;
100 | }
101 | .token.bold,
102 | .token.important {
103 | font-weight: 700;
104 | }
105 | .token.italic {
106 | font-style: italic;
107 | }
108 | .token.entity {
109 | cursor: help;
110 | }
111 | /*# sourceMappingURL=prism-okaidia.min.css.map */
112 |
113 | /* other custom styles not included in the default theme above */
114 |
115 | /* .code-block {
116 | Add styles for the code block here
117 | }
118 |
119 | .scrollable-code-block {
120 | Add a scrollbar to the code block
121 | overflow-y: scroll;
122 | Set a maximum height for the code block
123 | max-height: 500px;
124 | } */
125 |
--------------------------------------------------------------------------------
/ui/src/routes/+layout.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/ui/src/routes/+page.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home
4 |
5 |
6 |
7 |
10 |
227 |
228 |
229 |
230 |
231 |
232 |

233 |
234 |
235 |
236 |
237 |
238 | {#if messages.length === 0}
239 |
240 |
241 |
Prompts
242 |
What is your favorite color?
243 |
What is your favorite animal?
244 |
What is your favorite food?
245 |
246 |
247 |
Features
248 |
249 | - Realistic conversations
250 | - Quick responses
251 | - Unlimited chat instances
252 |
253 |
254 |
255 | {/if}
256 |
257 |
Foskaay Coding AI:
258 |
259 |
260 |
261 |
262 | {#each messages as message}
263 | {#if message.type === 'user'}
264 |
265 |
266 | {message.text}
267 |
268 | {:else}
269 |
270 | {message.text}
271 |
272 | {/if}
273 | {/each}
274 |
275 |
276 |
277 |
278 |
279 |
280 | {#if chatInstances.length > 0}
281 |
295 | {/if}
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 | {#each chatInstances as chatInstance}
306 |
307 | {#if chatInstance.isEditing}
308 |
newTitle = e.target.value}>
309 |
310 |
313 |
316 | {:else}
317 |
{chatInstance.title}
318 |
321 |
324 | {/if}
325 |
326 |
327 | {/each}
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
--------------------------------------------------------------------------------
/ui/src/routes/Header.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
42 |
43 |
44 |
45 | -
46 |
47 |
48 | -
49 |
50 |
51 |
52 |
53 |
54 |
55 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/ui/src/routes/pageCopy1.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home
4 |
5 |
6 |
7 |
10 |
210 |
211 |
212 |
213 |
214 |
215 |

216 |
217 |
218 |
219 |
220 |
221 | {#if messages.length === 0}
222 |
223 |
224 |
Prompts
225 |
What is your favorite color?
226 |
What is your favorite animal?
227 |
What is your favorite food?
228 |
229 |
230 |
Features
231 |
232 | - Realistic conversations
233 | - Quick responses
234 | - Unlimited chat instances
235 |
236 |
237 |
238 | {/if}
239 |
240 | {#each messages as message}
241 | {#if message.type === 'user'}
242 |
{message.text}
243 | {:else}
244 |
245 |
246 |
247 |
248 |
249 |
{message.text}
250 |
251 | {/if}
252 | {/each}
253 |
254 |
255 |
256 |
257 | {#if chatInstances.length > 0}
258 |
262 | {/if}
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 | {#each chatInstances as chatInstance}
273 |
274 | {#if chatInstance.isEditing}
275 |
newTitle = e.target.value}>
276 |
277 |
280 |
283 | {:else}
284 |
{chatInstance.title}
285 |
288 |
291 | {/if}
292 |
293 |
294 | {/each}
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
--------------------------------------------------------------------------------
/ui/src/routes/pageCopy2.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home
4 |
5 |
6 |
7 |
10 |
210 |
211 |
212 |
213 |
214 |
215 |

216 |
217 |
218 |
219 |
220 |
221 | {#if messages.length === 0}
222 |
223 |
224 |
Prompts
225 |
What is your favorite color?
226 |
What is your favorite animal?
227 |
What is your favorite food?
228 |
229 |
230 |
Features
231 |
232 | - Realistic conversations
233 | - Quick responses
234 | - Unlimited chat instances
235 |
236 |
237 |
238 | {/if}
239 |
240 | {#each messages as message}
241 | {#if message.type === 'user'}
242 |
243 | {message.text}
244 |
245 | {:else}
246 |
247 |
248 |
{message.text}
249 |
250 | {/if}
251 | {/each}
252 |
253 |
254 | {#if chatInstances.length > 0}
255 |
259 | {/if}
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 | {#each chatInstances as chatInstance}
270 |
271 | {#if chatInstance.isEditing}
272 |
newTitle = e.target.value}>
273 |
274 |
277 |
280 | {:else}
281 |
{chatInstance.title}
282 |
285 |
288 | {/if}
289 |
290 |
291 | {/each}
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
--------------------------------------------------------------------------------
/ui/src/routes/pageCopy3.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home
4 |
5 |
6 |
7 |
10 |
227 |
228 |
229 |
230 |
231 |
232 |

233 |
234 |
235 |
236 |
237 |
238 | {#if messages.length === 0}
239 |
240 |
241 |
Prompts
242 |
What is your favorite color?
243 |
What is your favorite animal?
244 |
What is your favorite food?
245 |
246 |
247 |
Features
248 |
249 | - Realistic conversations
250 | - Quick responses
251 | - Unlimited chat instances
252 |
253 |
254 |
255 | {/if}
256 |
257 |
NEW DISPLAY BELOW:
258 |
259 |
260 |
261 |
262 | {#each messages as message}
263 |
264 |
265 |
{message.text}
266 |
267 |
268 |
269 | {/each}
270 |
271 |
272 |
273 |
274 |
275 |
276 | {#if chatInstances.length > 0}
277 |
281 | {/if}
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 | {#each chatInstances as chatInstance}
292 |
293 | {#if chatInstance.isEditing}
294 |
newTitle = e.target.value}>
295 |
296 |
299 |
302 | {:else}
303 |
{chatInstance.title}
304 |
307 |
310 | {/if}
311 |
312 |
313 | {/each}
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
--------------------------------------------------------------------------------
/ui/src/routes/pageCopy4.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home
4 |
5 |
6 |
7 |
10 |
227 |
228 |
229 |
230 |
231 |
232 |

233 |
234 |
235 |
236 |
237 |
238 | {#if messages.length === 0}
239 |
240 |
241 |
Prompts
242 |
What is your favorite color?
243 |
What is your favorite animal?
244 |
What is your favorite food?
245 |
246 |
247 |
Features
248 |
249 | - Realistic conversations
250 | - Quick responses
251 | - Unlimited chat instances
252 |
253 |
254 |
255 | {/if}
256 |
257 |
NEW DISPLAY BELOW:
258 |
259 |
260 |
263 |
264 |
265 | {#each messages as message}
266 |
267 |
{message.text}
268 |
269 | {/each}
270 |
271 |
272 |
273 |
274 |
275 |
276 | {#if chatInstances.length > 0}
277 |
281 | {/if}
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 | {#each chatInstances as chatInstance}
292 |
293 | {#if chatInstance.isEditing}
294 |
newTitle = e.target.value}>
295 |
296 |
299 |
302 | {:else}
303 |
{chatInstance.title}
304 |
307 |
310 | {/if}
311 |
312 |
313 | {/each}
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
--------------------------------------------------------------------------------
/ui/src/routes/pageCopy5.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home
4 |
5 |
6 |
7 |
10 |
240 |
241 |
242 |
243 |
244 |
245 |

246 |
247 |
248 |
249 |
250 |
251 | {#if messages.length === 0}
252 |
253 |
254 |
Prompts
255 |
What is your favorite color?
256 |
What is your favorite animal?
257 |
What is your favorite food?
258 |
259 |
260 |
Features
261 |
262 | - Realistic conversations
263 | - Quick responses
264 | - Unlimited chat instances
265 |
266 |
267 |
268 | {/if}
269 |
270 |
NEW DISPLAY BELOW:
271 |
272 |
273 |
276 |
277 |
278 | {#each messages as message}
279 |
280 |
281 | {#if message.type === 'user'}
282 |
{message.text}
283 | {:else}
284 |
285 | {message.text}
286 |
287 | {/if}
288 |
289 | {/each}
290 |
291 |
292 |
301 |
302 |
303 |
304 |
305 | {#if chatInstances.length > 0}
306 |
310 | {/if}
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 | {#each chatInstances as chatInstance}
321 |
322 | {#if chatInstance.isEditing}
323 |
newTitle = e.target.value}>
324 |
325 |
328 |
331 | {:else}
332 |
{chatInstance.title}
333 |
336 |
339 | {/if}
340 |
341 |
342 | {/each}
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
--------------------------------------------------------------------------------
/ui/src/routes/pageCopy6.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home
4 |
5 |
6 |
7 |
10 |
227 |
228 |
229 |
230 |
231 |
232 |

233 |
234 |
235 |
236 |
237 |
238 | {#if messages.length === 0}
239 |
240 |
241 |
Prompts
242 |
What is your favorite color?
243 |
What is your favorite animal?
244 |
What is your favorite food?
245 |
246 |
247 |
Features
248 |
249 | - Realistic conversations
250 | - Quick responses
251 | - Unlimited chat instances
252 |
253 |
254 |
255 | {/if}
256 |
257 |
Foskaay Coding AI:
258 |
259 |
260 |
261 |
262 | {#each messages as message}
263 | {#if message.type === 'user'}
264 |
{message.text}
265 | {:else}
266 |
267 | {message.text}
268 |
269 | {/if}
270 | {/each}
271 |
272 |
273 |
274 |
275 |
276 |
277 | {#if chatInstances.length > 0}
278 |
282 | {/if}
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 | {#each chatInstances as chatInstance}
293 |
294 | {#if chatInstance.isEditing}
295 |
newTitle = e.target.value}>
296 |
297 |
300 |
303 | {:else}
304 |
{chatInstance.title}
305 |
308 |
311 | {/if}
312 |
313 |
314 | {/each}
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
--------------------------------------------------------------------------------
/ui/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AiHiPUniversity/ai-chatbot-openai-sveltekit-boilerplate-1/abde58b12363206eae0af605ba920b67adf89c38/ui/static/favicon.png
--------------------------------------------------------------------------------
/ui/svelte.config.js:
--------------------------------------------------------------------------------
1 | import preprocess from 'svelte-preprocess';
2 | import adapter from '@sveltejs/adapter-auto';
3 | import { vitePreprocess } from '@sveltejs/kit/vite';
4 |
5 | /** @type {import('@sveltejs/kit').Config} */
6 | const config = {
7 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors
8 | // for more information about preprocessors
9 | preprocess: [
10 | vitePreprocess(),
11 | preprocess({
12 | postcss: true
13 | })
14 | ],
15 |
16 | kit: {
17 | adapter: adapter()
18 | }
19 | };
20 |
21 | export default config;
22 |
--------------------------------------------------------------------------------
/ui/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const config = {
2 | content: ['./src/**/*.{html,js,svelte,ts}'],
3 |
4 | theme: {
5 | extend: {}
6 | },
7 |
8 | plugins: []
9 | };
10 |
11 | module.exports = config;
12 |
--------------------------------------------------------------------------------
/ui/tests/test.ts:
--------------------------------------------------------------------------------
1 | import { expect, test } from '@playwright/test';
2 |
3 | test('index page has expected h1', async ({ page }) => {
4 | await page.goto('/');
5 | await expect(page.getByRole('heading', { name: 'Welcome to SvelteKit' })).toBeVisible();
6 | });
7 |
--------------------------------------------------------------------------------
/ui/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json",
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "checkJs": true,
6 | "esModuleInterop": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "resolveJsonModule": true,
9 | "skipLibCheck": true,
10 | "sourceMap": true,
11 | "strict": true
12 | }
13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
14 | //
15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
16 | // from the referenced tsconfig.json - TypeScript does not merge them in
17 | }
18 |
--------------------------------------------------------------------------------
/ui/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { sveltekit } from '@sveltejs/kit/vite';
2 | import { defineConfig } from 'vitest/config';
3 |
4 | export default defineConfig({
5 | plugins: [sveltekit()],
6 | test: {
7 | include: ['src/**/*.{test,spec}.{js,ts}']
8 | }
9 | });
10 |
--------------------------------------------------------------------------------