Let's begin with setup your favorite API endpoint. Since SpeakGPT Web 1.5 you
53 | can add multiple API endpoints and use SpeakGPT to access GPR, Gemini, Claude, etc. If you're
54 | using local or unknown API and receiving CORS error (see console) make sure CORS headers are
55 | present in your API endpoint.
56 |
Enter the key only if you are using this app at
57 | https://assistant.teslasoft.org/. Other links may be insecure and phishing.
95 | );
96 | }
97 |
98 | export default ApiEndpointEditDialog;
--------------------------------------------------------------------------------
/src/components/ApiHostChangeDialog.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import {MaterialButton24} from "../widgets/MaterialButton";
19 | import {MaterialEditText} from "../widgets/MaterialEditText";
20 | import {getApiHost, setApiHost} from "../util/Settings";
21 | import {MaterialDialog} from "./MaterialDialog";
22 |
23 | function ApiHostChangeDialog({chatId, setOpen, setApiHostD}) {
24 | const [apiHostX, setApiHostX] = React.useState(getApiHost(chatId));
25 |
26 | return (
27 |
48 | );
49 | }
50 |
51 | export default ApiHostChangeDialog;
--------------------------------------------------------------------------------
/src/components/ApiKeyChangeDialog.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import {MaterialEditText} from "../widgets/MaterialEditText";
19 | import {MaterialButton24, MaterialButtonError, MaterialButtonOutlined24} from "../widgets/MaterialButton";
20 | import {MaterialDialog} from "./MaterialDialog";
21 |
22 | function ApiKeyChangeDialog(props) {
23 | const [apiKey, setApiKey] = React.useState("");
24 |
25 | const saveApiKey = () => {
26 | if (apiKey !== "") {
27 | localStorage.removeItem('skipApiKeyCheck');
28 | localStorage.setItem('apiKey', apiKey);
29 | props.setIsOpen(false);
30 | }
31 | }
32 |
33 | return (
34 |
{
35 | props.setIsOpen(false);
36 | }}>
37 |
38 |
{
39 | e.stopPropagation()
40 | }}>
41 |
Change API Key
42 |
43 | setApiKey(e.target.value)}/>
44 |
You can revoke API key here and unset it. When you unset an API key your chats will not be removed.
61 | );
62 | }
63 |
64 | export default ApiKeyChangeDialog;
--------------------------------------------------------------------------------
/src/components/ApiKeyDialog.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React, {useEffect} from 'react';
18 | import {MaterialEditText} from "../widgets/MaterialEditText";
19 | import {MaterialButton24, MaterialButtonOutlined24} from "../widgets/MaterialButton";
20 | import {MaterialDialog} from "./MaterialDialog";
21 |
22 | /*
23 | * @deprecated This component is deprecated and will be removed in the future versions. Use ApiEndpointEditDialog instead.
24 | * */
25 | function ApiKeyDialog(props) {
26 | const [apiKey, setApiKey] = React.useState("");
27 |
28 | const saveApiKey = () => {
29 | if (apiKey !== "") {
30 | localStorage.setItem('apiKey', apiKey);
31 | window.location.reload();
32 | }
33 | }
34 |
35 | useEffect(() => {
36 | console.warn("ApiKeyDialog is deprecated and will be removed in the future versions. Use ApiEndpointEditDialog instead.");
37 | }, []);
38 |
39 | return (
40 | <>
41 | {
42 | (localStorage.getItem('apiKey') === null || localStorage.getItem('apiKey') === undefined || localStorage.getItem('apiKey') === "") && localStorage.getItem("skipApiKeyCheck") !== "true" ?
43 |
44 |
45 |
46 |
Setup
47 |
48 |
To use this software you need to provide your OpenAI API
49 | key. SpeakGPT uses paid OpenAI models. API usage is significantly cheaper than fixed
50 | subscription. API-key authentication is safer than username/password authentication.
51 | App can access only API but not account info. You can revoke API key anytime without
52 | losing your account. API key is stored only on your device.
53 | setApiKey(e.target.value)}/>
55 |
Enter the key only if you are using this app at
56 | https://assistant.teslasoft.org/. Other links may be insecure and phishing.
57 |
You can skip API key setup and use app features that do not require API access like access conversations or prompts store. If you want to use full functionality you need to set an API key. You can do it in chat settings. To access chat settings create or open a chat.
70 | : null
71 | }
72 | >
73 | );
74 | }
75 |
76 | export default ApiKeyDialog;
--------------------------------------------------------------------------------
/src/components/AssistantDeepLink.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import {BrowserView, MobileView} from "react-device-detect";
19 | import Placeholder from "./Placeholder";
20 | import {MaterialButton24, MaterialButtonOutlined24} from "../widgets/MaterialButton";
21 | import {Link} from "react-router-dom";
22 |
23 | function AssistantDeepLink() {
24 | return (
25 | <>
26 |
27 |
28 |
This feature is only available on mobile devices.
29 | Go to home
30 |
31 |
32 |
33 |
34 |
You need to install SpeakGPT version 3.23 or above and allow it open external links to use this feature.
45 |
46 |
47 | >
48 | );
49 | }
50 |
51 | export default AssistantDeepLink;
--------------------------------------------------------------------------------
/src/components/AssistantMobile.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | /* DEPRECATED > SUPERSEDED WITH SpeakGPT Mobile PWA */
18 | import React from 'react';
19 | import AssistantEmbedded from "./AssistantEmbedded";
20 |
21 | function setFullHeight() {
22 | const vh = window.innerHeight * 0.01;
23 | document.documentElement.style.setProperty('--vh', `${vh}px`);
24 | }
25 |
26 | // Set the height initially
27 | setFullHeight();
28 |
29 | // Re-calculate on resize or orientation change
30 | window.addEventListener('resize', setFullHeight);
31 | window.addEventListener('orientationchange', setFullHeight);
32 |
33 | function AssistantMobile() {
34 | return (
35 |
39 |
43 |
44 |
45 |
46 | );
47 | }
48 |
49 | export default AssistantMobile;
--------------------------------------------------------------------------------
/src/components/Changelog.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import DocPage from "./DocPage";
19 |
20 | const pageContent = `
21 | > This version of SpeakGPT is currently experimental. You can try it before official release. Be careful as some rough edges may appear.
22 |
23 | ## 1.5.6
24 | - Fixed model list
25 |
26 | ## 1.5.5
27 | - MISSING DESCRIPTION
28 |
29 | ## 1.5.4
30 | - GPT 4o is now default model for image recognition
31 |
32 | ## 1.5.3
33 | - Extended FAQ page
34 |
35 | ## 1.5.2
36 | - Added FAQ page
37 |
38 | ## 1.5.1
39 | - Added GPT 4o as a default model in models list, removed gpt 4 32k as it's not available for anyone
40 |
41 | ## 1.5.0
42 | - Added API endpoint selector
43 |
44 | ## 1.4.1
45 | - Fixed chat creation
46 |
47 | ## 1.4.0
48 | - Added AI photo editor
49 |
50 | ## 1.3.0
51 | - Added AI playground
52 |
53 | ## 1.2.0
54 | - Fixed /imagine command
55 |
56 | ## 1.1.0
57 | - Updated features list
58 |
59 | ## 1.0.0-rc6
60 | - Added documentation and legal pages
61 | - Now you will no longer see API key dialog on the main screen. API key dialog will be shown only when you need to enter API key to perform API-restricted actions.
62 | - Fixed Markdown lists appearance
63 |
64 | ## 1.0.0-rc5
65 | - Added support for app and deep links
66 |
67 | ## 1.0.0-rc4
68 | - Added first message in chat list
69 |
70 | ## 1.0.0-rc3
71 | - Improved mobile UI
72 |
73 | ## 1.0.0-rc2
74 | - Bugfix
75 |
76 | ## 1.0.0-rc1
77 | - Mobile version
78 |
79 | ## 0.9.0-beta09
80 | - Personalize embedded assistants with icon and description
81 |
82 |
83 | ## 0.8.0-beta08
84 | - Customize embedded assistants with payload
85 |
86 | ## 0.7.0-beta07
87 | - Embedded assistant chats are now saved
88 |
89 | ## 0.6.0-beta06
90 | - Assistant message bar autofocus
91 |
92 | ## 0.5.0-beta05
93 | - Small fixes
94 |
95 | ## 0.4.0-beta04
96 | - Added mobile assistant
97 |
98 | ## 0.3.0-beta03
99 | - Minor fixes
100 |
101 | ## 0.2.0-beta02
102 | - Added embedded assistant
103 |
104 | ## 0.1.1-beta01
105 | - Minor fixes
106 |
107 | ## 0.1.0-beta01
108 | - First public beta release.
109 | - Improved images upload.
110 |
111 | ## 0.0.14-alpha14
112 | - Finished Prompts Store.
113 | - Added Quick Assistant.
114 |
115 | ## 0.0.13-alpha13
116 | - UI improvements.
117 |
118 | ## 0.0.12-alpha12
119 | - Added code highlighting form more programming languages.
120 |
121 | ## 0.0.11-alpha11
122 | - Now you can unset your API key and skip API key setup.
123 | - Added full list of available models
124 |
125 | ## 0.0.10-alpha10
126 | - Search chat added
127 | - Tips page added
128 |
129 | ## 0.0.9-alpha9
130 | - Minor bugs fixed
131 |
132 | ## 0.0.8-alpha8
133 | - Implemented GPT 4 Vision
134 | - Chats settings are now take effect
135 |
136 | ## 0.0.7-alpha7
137 | - Added chat settings
138 |
139 | ## 0.0.6-alpha6
140 | - Added ability to clear chats
141 | - Bugs fixed
142 |
143 | ## 0.0.5-alpha5
144 | - Minor bugs fixed
145 |
146 | ## 0.0.4-alpha4
147 | - Added code highlighting
148 | - Minor improvements
149 |
150 | ## 0.0.3-alpha3
151 | - Added image generation.
152 | - Fixed minor bugs.
153 |
154 | ## 0.0.2-alpha2
155 | - Changed chats location. Chats are now located in the indexed DB. We're preparing for image generation and chats import/export. You might also noticed that you chats has gone. Open Developers Tools > Console and put command localStorage.chatId, where chatId is a sha256 hash of the chat name to recover a chat. You can load chat as JSON in SpeakGPT mobile app now. Web version will receive this feature soon.
156 | - Added autoscroll in chats.
157 |
158 | ## 0.0.1-alpha1
159 | - Initial release.
160 | - You can create multiple chats.
161 | - You can select different AI models.
162 |
163 | `;
164 |
165 | function WelcomePage() {
166 | return (
167 |
168 | {pageContent}
169 |
170 | );
171 | }
172 |
173 | export default WelcomePage;
174 |
--------------------------------------------------------------------------------
/src/components/Chat.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import Placeholder from "./Placeholder";
19 | import Chats from "./Chats";
20 |
21 | function Chat(props) {
22 | return (
23 |
24 |
25 |
SpeakGPT
26 |
27 |
28 |
29 |
30 |
31 |
32 | );
33 | }
34 |
35 | export default Chat;
36 |
--------------------------------------------------------------------------------
/src/components/ChatItem.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React, {useEffect} from 'react';
18 | import gpt from "./../gpt.svg";
19 | import {Link} from "react-router-dom";
20 | import {isMobile} from "react-device-detect";
21 |
22 | function ChatItem({name, id, model, type, firstMessage, isActive, setDeleteChat, setEditChat, setIsDelete, setIsEdit, ...props}) {
23 |
24 | const [intType, setIntType] = React.useState(0);
25 |
26 | useEffect(() => {
27 | if (type === "GPT 3.5") {
28 | setIntType(1);
29 | } else if (type === "GPT 4 Turbo") {
30 | setIntType(2);
31 | } else if (type === "GPT 4") {
32 | setIntType(3);
33 | } else if (type === "FT") {
34 | setIntType(4);
35 | } else if (type === "GPT 3.5 (0125)") {
36 | setIntType(5);
37 | } else if (type === "O1") {
38 | setIntType(5);
39 | }
40 | }, [type]);
41 |
42 | return (
43 |
47 |
73 | );
74 | }
75 |
76 | export default Chats;
--------------------------------------------------------------------------------
/src/components/ConfirmChatClear.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import {MaterialButton24, MaterialButtonOutlined24} from "../widgets/MaterialButton";
19 | import {MaterialDialog} from "./MaterialDialog";
20 |
21 | function ConfirmChatClear({setOpenState, confirm, isAssistant}) {
22 | return (
23 |
47 | );
48 | }
49 |
50 | export default ConfirmChatClear;
--------------------------------------------------------------------------------
/src/components/DeleteChatDialog.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import {MaterialButton24, MaterialButtonOutlined24} from "../widgets/MaterialButton";
19 | import {MaterialDialog} from "./MaterialDialog";
20 |
21 | function DeleteChatDialog({setOpenState, chatName, setChatName, ...props}) {
22 | return (
23 |
47 | );
48 | }
49 |
50 | export default DeleteChatDialog;
--------------------------------------------------------------------------------
/src/components/DocPage.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import {isMobile} from "react-device-detect";
19 | import {Link} from "react-router-dom";
20 | import Prism from "../prism";
21 | import {highlightCode, linesNumbers} from "../util/MarkDownCode";
22 | import remarkGfm from "remark-gfm";
23 | import Markdown from "react-markdown";
24 |
25 | function setFullHeight() {
26 | const vh = window.innerHeight * 0.01;
27 | document.documentElement.style.setProperty('--vh', `${vh}px`);
28 | }
29 |
30 | // Set the height initially
31 | setFullHeight();
32 |
33 | // Re-calculate on resize or orientation change
34 | window.addEventListener('resize', setFullHeight);
35 | window.addEventListener('orientationchange', setFullHeight);
36 |
37 | function DocPage({children, title}) {
38 | return (
39 |
102 | );
103 | }
104 |
105 | export default DocPage;
--------------------------------------------------------------------------------
/src/components/MaterialDialog.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 | import {styled} from "@mui/material/styles";
17 | import {Dialog} from "@mui/material";
18 |
19 | export const MaterialDialog = styled(Dialog)(({ theme }) => ({
20 | '&:MuiPaper-root': {
21 | borderRadius: "24px",
22 | }
23 | }));
--------------------------------------------------------------------------------
/src/components/MaterialWindow.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import NavigationBar from "../widgets/NavigationBar";
19 | import Assistant from "./Assistant";
20 | import {BrowserView, MobileView, isMobile} from "react-device-detect";
21 | import NavigationBarMobile from "../widgets/NavigationBarMobile";
22 |
23 | function setFullHeight() {
24 | const vh = window.innerHeight * 0.01;
25 | document.documentElement.style.setProperty('--vh', `${vh}px`);
26 | }
27 |
28 | // Set the height initially
29 | setFullHeight();
30 |
31 | // Re-calculate on resize or orientation change
32 | window.addEventListener('resize', setFullHeight);
33 | window.addEventListener('orientationchange', setFullHeight);
34 |
35 | function MaterialWindow({children, page, ...props}) {
36 |
37 | const [assistantOpened, setAssistantOpened] = React.useState(false);
38 |
39 | return (
40 |
70 | );
71 | }
72 |
73 | export default MaterialWindow;
--------------------------------------------------------------------------------
/src/components/NewChatDialog.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React, {useEffect} from 'react';
18 | import {MaterialEditText} from "../widgets/MaterialEditText";
19 | import {MaterialButton24, MaterialButtonOutlined24} from "../widgets/MaterialButton";
20 | import {MaterialDialog} from "./MaterialDialog";
21 |
22 | function NewChatDialog({chatName, setChatName, invalidState, invalidMessage, setChatDialogOpen, isEdit, chatModel, setIsEditing, ...props}) {
23 | const [tempChatName, setTempChatName] = React.useState("");
24 |
25 | useEffect(() => {
26 | setTempChatName(chatName);
27 | }, [chatName]);
28 |
29 | return (
30 |
54 | );
55 | }
56 |
57 | export default NewChatDialog;
58 |
--------------------------------------------------------------------------------
/src/components/NotFound.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import Placeholder from "./Placeholder";
19 | import {MaterialButton24} from "../widgets/MaterialButton";
20 | import {Link} from "react-router-dom";
21 |
22 | function NotFound() {
23 | return (
24 |
25 |
The page you are looking for does not exist.
26 | Go to home
27 |
28 | );
29 | }
30 |
31 | export default NotFound;
--------------------------------------------------------------------------------
/src/components/Placeholder.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 |
19 | function Placeholder({children, icon, message}) {
20 | return (
21 |
27 | );
28 | }
29 |
30 | export default Placeholder;
--------------------------------------------------------------------------------
/src/components/PlaceholderLoading.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import {CircularProgress} from "@mui/material";
19 | import {isMobile} from "react-device-detect";
20 |
21 | function setFullHeight() {
22 | const vh = window.innerHeight * 0.01;
23 | document.documentElement.style.setProperty('--vh', `${vh}px`);
24 | }
25 |
26 | // Set the height initially
27 | setFullHeight();
28 |
29 | // Re-calculate on resize or orientation change
30 | window.addEventListener('resize', setFullHeight);
31 | window.addEventListener('orientationchange', setFullHeight);
32 |
33 | function Placeholder() {
34 | return (
35 |
38 |
43 |
44 | );
45 | }
46 |
47 | export default Placeholder;
--------------------------------------------------------------------------------
/src/components/ProTip.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 |
19 | import {isMobile} from "react-device-detect";
20 |
21 | function ProTip({text}) {
22 | return (
23 |
24 |
{text}
27 |
28 | );
29 | }
30 |
31 | export default ProTip;
--------------------------------------------------------------------------------
/src/components/PromptCard.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 |
19 | import {isMobile} from "react-device-detect";
20 |
21 | function PromptCard({prompt, onPromptClick}) {
22 | return (
23 |
{
24 | onPromptClick();
25 | }}>
26 |
{prompt.name}
27 |
{prompt.desc}
28 |
{prompt.author}
{prompt.likes}thumb_up
32 |
33 |
34 | );
35 | }
36 |
37 | export default PromptCard;
--------------------------------------------------------------------------------
/src/components/SelectResolutionDialog.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import {MaterialButton24, MaterialButtonOutlined24} from "../widgets/MaterialButton";
19 | import {MaterialDialog} from "./MaterialDialog";
20 |
21 | function SelectResolutionDialog({setIsOpen, setResolution, resolution, isAssistant}) {
22 | const availableResolutions = [
23 | "256x256",
24 | "512x512",
25 | "1024x1024",
26 | ]
27 |
28 | const [selectedResolution, setSelectedResolution] = React.useState(resolution);
29 | return (
30 |
66 | );
67 | }
68 |
69 | export default SelectResolutionDialog;
--------------------------------------------------------------------------------
/src/components/SystemMessageEditDialog.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import {MaterialEditText} from "../widgets/MaterialEditText";
19 | import {MaterialButton24, MaterialButtonOutlined24} from "../widgets/MaterialButton";
20 | import {MaterialDialog} from "./MaterialDialog";
21 |
22 | function SystemMessageEditDialog({setIsOpen, message, setMessage, isAssistant}) {
23 |
24 | const [currentMessage, setCurrentMessage] = React.useState(message);
25 |
26 | return (
27 |
51 | );
52 | }
53 |
54 | export default SystemMessageEditDialog;
--------------------------------------------------------------------------------
/src/components/Tile.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 |
19 | import {isMobile} from "react-device-detect";
20 |
21 | function Tile({clickAction, icon, title, subtitle, description, checkable, checked, setChecked}) {
22 | const [checkedState, setCheckedState] = React.useState(checked);
23 |
24 | return (
25 |
41 | );
42 | }
43 |
44 | export default Tile;
--------------------------------------------------------------------------------
/src/components/Tips.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import ProTip from "./ProTip";
19 | import {isMobile, MobileView} from "react-device-detect";
20 |
21 | const tips = [
22 | "Start your message with /imagine to generate an image.",
23 | "Search tricks:\n\nUse \"author:\" " +
24 | "prefix to search by author.\nUse \"title:\" " +
25 | "prefix to search by title.\nUse \"id:\" " +
26 | "prefix to search by id.\nUse \"cat:\" " +
27 | "prefix to search y category.\nUse \"type:\" " +
28 | "prefix to search by type.",
29 | "ChatGPT is stuffy? Try out other models. Sometimes you may get very interesting results.",
30 | "Only GPT models can remember previous messages. Other models are not optimized for it.",
31 | "Sometimes some weird or useless features may appear. It because this app is in beta test.",
32 | "SpeakGPT is too slow? Try to reduce max tokens per output.",
33 | "Getting the same picture in the photo editor as you sent? Don't forget to draw a mask.",
34 | "Getting generation errors after updating to SpeakGPT 1.5.0? Add or change API endpoint. Usually it will be done automatically, but if not you can do it manually."
35 | ]
36 |
37 | function setFullHeight() {
38 | const vh = window.innerHeight * 0.01;
39 | document.documentElement.style.setProperty('--vh', `${vh}px`);
40 | }
41 |
42 | // Set the height initially
43 | setFullHeight();
44 |
45 | // Re-calculate on resize or orientation change
46 | window.addEventListener('resize', setFullHeight);
47 | window.addEventListener('orientationchange', setFullHeight);
48 |
49 | function Tips() {
50 | return (
51 |
72 | );
73 | }
74 |
75 | export default Tips;
--------------------------------------------------------------------------------
/src/documentation/ApiSafety.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import DocPage from "../components/DocPage";
19 |
20 | const pageContent = `
21 | SpeakGPT uses OpenAI API to provide you with the best experience. Using API-keys is more secure than using your username/password. Your personal info can't be obtained using API key. OpenAI provides cheap API access to their services. Your API key is stored locally on your device and is not shared with anyone. SpeakGPT does not collect any personal data. SpeakGPT is open-source and you can check the code yourself. Each release of SpeakGPT is checked on VirusTotal.
22 | If you have any concerns you can secure either [revoke your API key](https://platform.openai.com/account/api-keys) or use a separate API key for SpeakGPT.
23 |
24 | To secure your API key perform the following steps:
25 |
26 | 1. Make sure you have separate API key for SpeakGPT
27 | 2. Set up billing limit
28 | 3. Enable usage monitoring, so you can see how much resources SpeakGPT uses and how much it costs
29 | 4. If you have any concerns you can revoke your API key
30 |
31 | > Why we obfuscate our code in production releases?
32 | >
33 | > Obfuscation and resources shrinking allows us to optimize app size, it performance and secure it against reverse engineering or tamper and make sure your credentials like API keys in a safe place. You can request an unobfuscated build or compile it by self to make sure our app is safe.
34 |
35 |
36 | > Developer identity
37 | >
38 | > Developer name: Dmytro Ostapenko (AndraxDev)\\
39 | > Contact: dostapenko82@gmail.com, +421951829517\\
40 | > Legal address: Južná trieda 4B, 04001 Košice, Slovakia 04001\\
41 | > Legal entity ID: 55545386
42 | `;
43 |
44 | function ApiSafety() {
45 | return (
46 |
47 | {pageContent}
48 |
49 | );
50 | }
51 |
52 | export default ApiSafety;
--------------------------------------------------------------------------------
/src/documentation/Contact.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import DocPage from "../components/DocPage";
19 |
20 | const pageContent = `
21 | > Name: Dmytro Ostapenko (AndraxDev)
22 | >
23 | > Email: dostapenko82@gmail.com
24 | >
25 | > Phone: +421951829517
26 | >
27 | > Legal address: Južná trieda 4B, 04001 Košice, Slovakia 04001
28 | >
29 | > Legal entity ID: 55545386
30 | >
31 | > Site: [andrax.dev](https://andrax.dev)
32 | >
33 | > GitHub: [github.com/AndraxDev](https://github.com/AndraxDev)
34 | `;
35 |
36 | function Contact() {
37 | return (
38 |
39 | {pageContent}
40 |
41 | );
42 | }
43 |
44 | export default Contact;
--------------------------------------------------------------------------------
/src/documentation/Debug.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import DocPage from "../components/DocPage";
19 |
20 | const pageContent = `
21 | Supported app links:
22 |
23 | [https://assistant.teslasoft.org/chat](https://assistant.teslasoft.org/chat)
24 |
25 | [https://assistant.teslasoft.org/prompts/vswPyF3848](https://assistant.teslasoft.org/prompts/vswPyF3848)
26 |
27 | [https://assistant.teslasoft.org/assistant](https://assistant.teslasoft.org/assistant)
28 |
29 | > If these links are pointing you to a web pages instead of app or you have 404 error, please make sure you have installed SpeakGPT version 3.21 or newer and opening supported links is permitted for this app.
30 | `;
31 |
32 | function Debug() {
33 | return (
34 |
35 | {pageContent}
36 |
37 | );
38 | }
39 |
40 | export default Debug;
41 |
--------------------------------------------------------------------------------
/src/documentation/DeleteData.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import DocPage from "../components/DocPage";
19 |
20 | const pageContent = `
21 | ## To delete your data from mobile app SpeakGPT, please follow these steps:
22 |
23 | 1. Go to Device settings > Apps > SpeakGPT > Clear data
24 | 2. To disable analytics open app settings and search for "Usage and diagnostics" option
25 | 3. To disable all data collecting open app settings and search for "Revoke authorization" option
26 | 4. To delete analytics data, please contact us via admin@teslasoft.org
27 |
28 | ## To delete data from web app SpeakGPT, please follow these steps:
29 |
30 | 1. Go to your browser settings > Browsing data > Select "assistant.teslasoft.org" > Clear all data
31 |
32 | > SpeakGPT Lite does not collect any personal data. To delete all local data, go to Device settings > Apps > SpeakGPT > Clear data
33 |
34 | ## To delete your account from API Provider (Like OpenAI), refer to it's Privacy Policy. Here are some account close links for popular API providers:
35 | - [OpenAI](https://help.openai.com/en/articles/6378407-how-to-delete-your-account)
36 | - [OpenRouter](https://openrouter.ai/docs/faq#how-can-i-delete-my-account)
37 |
38 | Read Privacy Policy here: [Privacy Policy for regular SpeakGPT mobile/web app](/privacy) and [Privacy Policy for SpeakGPT Lite](/privacy_lite)
39 | `;
40 |
41 | function DeleteData() {
42 | return (
43 |
44 | {pageContent}
45 |
46 | );
47 | }
48 |
49 | export default DeleteData;
--------------------------------------------------------------------------------
/src/documentation/FAQ.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import DocPage from "../components/DocPage";
19 |
20 | const pageContent = `
21 | ## What is it?
22 |
23 | > SpeakGPT is a chatbot that uses external API to provide you access to GPT, Gemini, Claude, Perplexity and other powerful LLMs.
24 |
25 | ## What is LLM?
26 |
27 | > LLM stands for Large Language Model. It's a model that can generate human-like text based on the input it receives.
28 |
29 | ## Is SpeakGPT free?
30 |
31 | > SpeakGPT is only client app that you can access for free and without registration, but some models (like GPT 4, Gemini) are paid and require API key to use.
32 |
33 | ## Why should I download Android app?
34 |
35 | > Android app has more features than web version. It includes offline access, chat import/export, mobile assistant, context menu, quick access, advanced model params, customization and more.
36 |
37 | ## Where can I find Android app?
38 |
39 | > Download it from [Google Play](https://play.google.com/store/apps/details?id=org.teslasoft.assistant) or [GitHub](https://github.com/AndraxDev/speak-gpt).
40 |
41 | ## Why this app requires API key?
42 |
43 | > This app provides you access to different AI models and API providers. API usage is cheaper and most of API providers have pay-as-you-go pricing model. Learn more about how we use API key in our [Privacy Policy](/privacy) and [API key safety](/api/safety).
44 |
45 | ## How can I get API key?
46 |
47 | > You can visit API provider page. Here are some of them: [OpenAI](https://openai.com/), [OpenRouter](https://openrouter.ai/).
48 |
49 | ## How can I report bugs?
50 |
51 | > Here are 2 GitHub repositories where you can report bugs: [For web version click here](https://github.com/AndraxDev/speak-gpt-web), [for mobile version click here](https://github.com/AndraxDev/speak-gpt). Just open issues and describe your problem but pay attention for duplicates. Duplicated issues will be closed without prior notice.
52 |
53 | ## How can I contribute?
54 |
55 | > You can donate us at [Buy me a coffee](https://buymeacoffee.com/andrax_dev) or [Ko-fi](https://ko-fi.com/andrax_dev).
56 |
57 | ## How can I set an API key?
58 |
59 | > For desktop version follow these instructions:
60 | > 1. Launch quick assistant (click on square icon with a circle inside on the top left corner)
61 | > 2. Click on "Settings" button
62 | > 3. Click on "API endpoint" button
63 | > 4. Click edit button on the right side of the default API endpoint
64 | > 5. Enter your API key and click "Save" button
65 | > 6. Change base url (optional, if you want to use another API provider like OpenRouter)
66 |
67 | ## How can I access Gemini or Claude, I see only GPT?
68 |
69 | > You need to setup OpenRouter API endpoint and select it for the current chat.
70 | > OpenRouter base url is: https://openrouter.ai/api/v1/
71 |
72 | ## I don't see GPT 4 model in the list
73 |
74 | > To use GPT 4 you need to have paid OpenAI account (Not GPT Plus). View more info at [OpenAI rate limits](https://platform.openai.com/docs/guides/rate-limits).
75 |
76 | ## I'm getting quota error when using GPT 4 model
77 |
78 | > See previous answer.
79 |
80 | ## Which limits are applied to me?
81 |
82 | > It depends on the API provider, model, usage and your spending. You can view more info at [OpenAI rate limits](https://platform.openai.com/docs/guides/rate-limits).
83 |
84 | ## Is it expensive to use this app?
85 |
86 | > It depends on efficient usage of app, model and API provider.
87 | > For more info about OpenAI pricing visit [OpenAI pricing](https://openai.com/api/pricing/)
88 | > For more info about OpenRouter pricing visit [OpenRouter pricing](https://openrouter.ai/docs#models)
89 |
90 | ## I had a very large chat and now I received a high bill?
91 |
92 | > It's possible because when you are sending a message to the AI model, the whole conversation will be passed to the model input.
93 | > Here are some tricks to avoid high bills:
94 | > - Optimize messages size
95 | > - Don't use multiple topics in a single chat (as previous context will become unuseful and you will be charged for it)
96 | > - Play with prompts, system messages and formulate your tasks exactly
97 | > - For routine tasks like code generating, text translation or summarization use playground. Here you can find additional model params that can help improve models response. Playground is not a chat so only your prompt will me sent to the model.
98 |
99 | ## Didn't find answer to your question?
100 |
101 | > Contact us at [dostapenko82@gmail.com](mailto:dostapenko82@gmail.com)
102 | `;
103 |
104 | function Faq() {
105 | return (
106 |
107 | {pageContent}
108 |
109 | );
110 | }
111 |
112 | export default Faq;
--------------------------------------------------------------------------------
/src/documentation/Optimize.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import DocPage from "../components/DocPage";
19 |
20 | const pageContent = `
21 | This page describes some tricks how you can optimize your costs when using SpeakGPT.
22 |
23 | ## How chat models are billed?
24 |
25 | Let's assume the following example chat:
26 |
27 | > [System] > System message
28 | >
29 | > [User] > Message 1
30 | >
31 | > [Assistant] > Message 2
32 | >
33 | > [User] > Message 3
34 | >
35 | > [Assistant] > Message 4
36 | >
37 | > [User] > Message 5
38 | >
39 | > [Assistant] > Message 6
40 |
41 | When you use chat models, then you will be billed for th entire chat, because chat history becomes input context. So you will be billed for system message and first 2 messages (User + Bot messages) 3 times because you perform 3 server requests and each time, system and first 2 messages are included in the user input.
42 | Respectfully, you will be billed for the third and fourth messages 2 times, because it included in 2 server requests. This is the underwater stone in the API billing system.
43 |
44 | To avoid this we created Playground mode that can be used for bulk actions like generating translations or config files.
45 | Playground does not remember your messages so you wil be billed only once for each message.
46 |
47 | ## When to use right features?
48 |
49 | ### Chat
50 |
51 | > You can use chats for non-bulk actions like asking questions, generating text, performing iterative code generation, etc. Don't use single chat for multiple topics. It will confuse AI model and incur additional charges. Create a new chat for each topics and you will see how much money you would save.
52 |
53 | ### Playground
54 |
55 | > You can use Playground for bulk actions like generating translations, config files, etc.
56 |
57 | ## Use right model!
58 |
59 | > Some of models are expensive, but not all of the are suited for performing actions. For easy tasks it is not necessary to use expensive and powerful models.
60 |
61 | > Interesting fact: GPT 3.5 is less capable than gpt 4o, but it 10 times more expensive. This is because OpenAI rarely changes prices for existing models and pushing developers to use better models.
62 |
63 | ## Set budget limits and alerts
64 |
65 | > Check if your API provider allows to set soft and hard budget limits. This will help you to avoid unexpected costs. Please note, that hitting hard limit will stop your API key and you will not be able to use it until you remove the limit. Soft limit will just notify you about exceeding the limit, but will not stop your API key.
66 | `;
67 |
68 | function Optimize(props) {
69 | return (
70 |
71 | {pageContent}
72 |
73 | );
74 | }
75 |
76 | export default Optimize;
--------------------------------------------------------------------------------
/src/documentation/Privacy.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import DocPage from "../components/DocPage";
19 |
20 | const pageContent = `
21 | > This page describes which data we use and why.
22 |
23 | ## Data we do not collect
24 |
25 | - Chats list
26 | - Conversations content
27 | - Audio samples of your voice
28 | - API keys
29 |
30 | > This info is securely stored on your device, but it might be sent to OpenAI (or other API providers selected by you) to provide basic functionality. We don't store this info on our servers. To learn more about how your data is used, refer to the Privacy Policy of the API provider you are using.
31 |
32 | ---
33 |
34 | ## Optional data we may collect
35 |
36 | - Installation ID*
37 | - Crash logs
38 | - Advertising ID
39 | - Device info (mode, OS version, etc)
40 |
41 | > This info is used for analytical purposes only. We do not share this info with third-party organizations. This info is collected only when "Usage and diagnostics" feature is enabled. You can also send this info manually. You are able to delete this info from our servers, reset or/and delete installation ID. You can also revoke authorization to use this data without losing access to the app.
42 |
43 | ---
44 |
45 | ## Required data we collect
46 |
47 | - Name
48 | - User-generated content**
49 |
50 | > This data is required for function "Prompts store". We do not collect this data unless you published a prompt. You can still delete this data by reporting a prompt or contacting us via admin@teslasoft.org. This data is stored permanently unless you request your data to be deleted. This data can be accessed by other users.
51 |
52 | ---
53 |
54 | > *. When you install this app an installation ID will be created. This id is a random UUID string and it does not belong to Android id or any of hardware IDs. You can either reset or delete installation ID. In this case we will stop to collect data associated with installation ID.
55 |
56 | > **. User-generated content is all content created and published by users using this app. We may review public content for violations and remove inappropriate content. We don't have access to private content (like chats list, conversations, etc). User-generated content term doesn't include your chat list, chat content or app preferences.
57 |
58 | Learn how to delete your data here: [Delete my data](/data/delete)
59 | `;
60 |
61 | function Privacy() {
62 | return (
63 |
64 | {pageContent}
65 |
66 | );
67 | }
68 |
69 | export default Privacy;
--------------------------------------------------------------------------------
/src/documentation/PrivacyLite.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import DocPage from "../components/DocPage";
19 |
20 | const pageContent = `
21 | > This page describes which data we use and why.
22 |
23 | ## Data we DO NOT collect
24 |
25 | - Chats list
26 | - Conversations content
27 | - Audio samples of your voice
28 | - API keys
29 |
30 | > This info is securely stored on your device and encrypted with a military-grade encryption (AES-256-GCM), but it might be sent to OpenAI (or other API providers selected by you) to provide basic functionality. We don't store this info on our servers. To learn more about how your data is used, refer to the Privacy Policy of the API provider you are using.
31 |
32 | ---
33 |
34 | ## Optional data we may collect
35 |
36 | > No optional data is collected. SpeakGPT Lite does not contain any proprietary services, online features or analytics.
37 |
38 | ---
39 |
40 | ## Required data we collect
41 |
42 | > No required data is collected. SpeakGPT Lite does not contain any proprietary services, online features or analytics. SpeakGPT Lite does not contain Prompt Library so you cannot interact with it through this app.
43 |
44 | ---
45 |
46 | Learn how to delete your data here: [Delete my data](/data/delete)
47 | `;
48 |
49 | function Privacy() {
50 | return (
51 |
52 | {pageContent}
53 |
54 | );
55 | }
56 |
57 | export default Privacy;
--------------------------------------------------------------------------------
/src/gpt.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import ReactDOM from 'react-dom/client';
19 | import './index.css';
20 | import App from './App';
21 |
22 | import {setMaxSettings, setMinSettings} from "./util/Settings";
23 |
24 | function loadStylesheet(path) {
25 | let link = document.createElement('link');
26 | link.rel = 'stylesheet';
27 | link.type = 'text/css';
28 | link.href = path;
29 | link.media = 'all';
30 |
31 | document.head.appendChild(link);
32 | }
33 |
34 | const root = ReactDOM.createRoot(document.getElementById('root'));
35 | root.render(
36 |
37 | );
38 |
39 | loadStylesheet('/prism.css');
40 | loadStylesheet('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap');
41 | loadStylesheet('https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200');
42 |
43 | /* Set max global settings */
44 | window._debug_setMaxSettings = () => {
45 | setMaxSettings();
46 | window.location.reload();
47 | }
48 |
49 | /* Set min global settings */
50 | window._debug_setMinSettings = () => {
51 | setMinSettings();
52 | window.location.reload();
53 | }
54 |
55 |
56 | window.debug_setExperiment = (experiment) => {
57 | window.localStorage.setItem('experiment-' + experiment, "true")
58 | window.location.reload();
59 | }
60 |
61 | window.debug_unsetExperiment = (experiment) => {
62 | window.localStorage.removeItem('experiment-' + experiment);
63 | window.location.reload();
64 | }
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/prism.css:
--------------------------------------------------------------------------------
1 | /* PrismJS 1.29.0
2 | https://prismjs.com/download.html#themes=prism-dark&languages=markup+css+clike+javascript+abap+abnf+actionscript+ada+agda+al+antlr4+apacheconf+apex+apl+applescript+aql+arduino+arff+armasm+arturo+asciidoc+aspnet+asm6502+asmatmel+autohotkey+autoit+avisynth+avro-idl+awk+bash+basic+batch+bbcode+bbj+bicep+birb+bison+bnf+bqn+brainfuck+brightscript+bro+bsl+c+csharp+cpp+cfscript+chaiscript+cil+cilkc+cilkcpp+clojure+cmake+cobol+coffeescript+concurnas+csp+cooklang+coq+crystal+css-extras+csv+cue+cypher+d+dart+dataweave+dax+dhall+diff+django+dns-zone-file+docker+dot+ebnf+editorconfig+eiffel+ejs+elixir+elm+etlua+erb+erlang+excel-formula+fsharp+factor+false+firestore-security-rules+flow+fortran+ftl+gml+gap+gcode+gdscript+gedcom+gettext+gherkin+git+glsl+gn+linker-script+go+go-module+gradle+graphql+groovy+haml+handlebars+haskell+haxe+hcl+hlsl+hoon+http+hpkp+hsts+ichigojam+icon+icu-message-format+idris+ignore+inform7+ini+io+j+java+javadoc+javadoclike+javastacktrace+jexl+jolie+jq+jsdoc+js-extras+json+json5+jsonp+jsstacktrace+js-templates+julia+keepalived+keyman+kotlin+kumir+kusto+latex+latte+less+lilypond+liquid+lisp+livescript+llvm+log+lolcode+lua+magma+makefile+markdown+markup-templating+mata+matlab+maxscript+mel+mermaid+metafont+mizar+mongodb+monkey+moonscript+n1ql+n4js+nand2tetris-hdl+naniscript+nasm+neon+nevod+nginx+nim+nix+nsis+objectivec+ocaml+odin+opencl+openqasm+oz+parigp+parser+pascal+pascaligo+psl+pcaxis+peoplecode+perl+php+phpdoc+php-extras+plant-uml+plsql+powerquery+powershell+processing+prolog+promql+properties+protobuf+pug+puppet+pure+purebasic+purescript+python+qsharp+q+qml+qore+r+racket+cshtml+jsx+tsx+reason+regex+rego+renpy+rescript+rest+rip+roboconf+robotframework+ruby+rust+sas+sass+scss+scala+scheme+shell-session+smali+smalltalk+smarty+sml+solidity+solution-file+soy+sparql+splunk-spl+sqf+sql+squirrel+stan+stata+iecst+stylus+supercollider+swift+systemd+t4-templating+t4-cs+t4-vb+tap+tcl+tt2+textile+toml+tremor+turtle+twig+typescript+typoscript+unrealscript+uorazor+uri+v+vala+vbnet+velocity+verilog+vhdl+vim+visual-basic+warpscript+wasm+web-idl+wgsl+wiki+wolfram+wren+xeora+xml-doc+xojo+xquery+yaml+yang+zig */
3 | /**
4 | * prism.js Dark theme for JavaScript, CSS and HTML
5 | * Based on the slides of the talk “/Reg(exp){2}lained/”
6 | * @author Lea Verou
7 | */
8 |
9 | code[class*="language-"],
10 | pre[class*="language-"] {
11 | color: white;
12 | background: none;
13 | text-shadow: 0 -.1em .2em black;
14 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
15 | font-size: 1em;
16 | text-align: left;
17 | white-space: pre;
18 | word-spacing: normal;
19 | word-break: normal;
20 | word-wrap: normal;
21 | line-height: 1.5;
22 |
23 | -moz-tab-size: 4;
24 | -o-tab-size: 4;
25 | tab-size: 4;
26 |
27 | -webkit-hyphens: none;
28 | -moz-hyphens: none;
29 | -ms-hyphens: none;
30 | hyphens: none;
31 | }
32 |
33 | @media print {
34 | code[class*="language-"],
35 | pre[class*="language-"] {
36 | text-shadow: none;
37 | }
38 | }
39 |
40 | pre[class*="language-"],
41 | :not(pre) > code[class*="language-"] {
42 | background: hsl(30, 20%, 25%);
43 | }
44 |
45 | /* Code blocks */
46 | pre[class*="language-"] {
47 | padding: 1em;
48 | margin: .5em 0;
49 | overflow: auto;
50 | border: .3em solid hsl(30, 20%, 40%);
51 | border-radius: .5em;
52 | box-shadow: 1px 1px .5em black inset;
53 | }
54 |
55 | /* Inline code */
56 | :not(pre) > code[class*="language-"] {
57 | padding: .15em .2em .05em;
58 | border-radius: .3em;
59 | border: .13em solid hsl(30, 20%, 40%);
60 | box-shadow: 1px 1px .3em -.1em black inset;
61 | white-space: normal;
62 | }
63 |
64 | .token.comment,
65 | .token.prolog,
66 | .token.doctype,
67 | .token.cdata {
68 | color: hsl(30, 20%, 50%);
69 | }
70 |
71 | .token.punctuation {
72 | opacity: .7;
73 | }
74 |
75 | .token.namespace {
76 | opacity: .7;
77 | }
78 |
79 | .token.property,
80 | .token.tag,
81 | .token.boolean,
82 | .token.number,
83 | .token.constant,
84 | .token.symbol {
85 | color: hsl(350, 40%, 70%);
86 | }
87 |
88 | .token.selector,
89 | .token.attr-name,
90 | .token.string,
91 | .token.char,
92 | .token.builtin,
93 | .token.inserted {
94 | color: hsl(75, 70%, 60%);
95 | }
96 |
97 | .token.operator,
98 | .token.entity,
99 | .token.url,
100 | .language-css .token.string,
101 | .style .token.string,
102 | .token.variable {
103 | color: hsl(40, 90%, 60%);
104 | }
105 |
106 | .token.atrule,
107 | .token.attr-value,
108 | .token.keyword {
109 | color: hsl(350, 40%, 70%);
110 | }
111 |
112 | .token.regex,
113 | .token.important {
114 | color: #e90;
115 | }
116 |
117 | .token.important,
118 | .token.bold {
119 | font-weight: bold;
120 | }
121 | .token.italic {
122 | font-style: italic;
123 | }
124 |
125 | .token.entity {
126 | cursor: help;
127 | }
128 |
129 | .token.deleted {
130 | color: red;
131 | }
132 |
133 |
--------------------------------------------------------------------------------
/src/theme/AppWidgetTheme.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | export const AppWidgetTheme = {
18 | components: {
19 | MuiButton: {
20 | styleOverrides: {
21 | root: {
22 | borderRadius: '16px',
23 | width: 260,
24 | height: 260,
25 | },
26 | },
27 | }
28 | },
29 | }
30 |
--------------------------------------------------------------------------------
/src/theme/BaseTheme.css:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | @import "colors.css";
18 |
19 | * {
20 | color-scheme: dark;
21 | }
22 |
23 | html, body {
24 | background-color: var(--color-accent-200);
25 | }
26 |
27 | html {
28 | overflow-y: scroll;
29 | }
30 |
31 | .ui {
32 | margin-top: 56px;
33 | width: 100%;
34 | display: flex;
35 | flex-direction: column;
36 | align-items: center;
37 | background-color: var(--color-accent-0);
38 | min-height: calc(100vh - 56px);
39 | }
40 |
41 | .ui__dialog {
42 | margin-top: 48px;
43 | min-width: 300px;
44 | /*min-height: 180px;*/
45 | padding: 16px;
46 | border-radius: 24px;
47 | display: flex;
48 | align-items: center;
49 | flex-direction: column;
50 | color: var(--color-secondary-light);
51 | background-color: var(--color-accent-50);
52 | }
53 |
54 | .ui__dialog__title {
55 | padding: 0;
56 | margin: 4px;
57 | color: var(--color-accent-800);
58 | font-size: 18pt;
59 | }
60 |
61 | .ui__disclaimer {
62 | margin-top: 48px;
63 | color: var(--color-disclaimer);
64 | text-align: center;
65 | width: 720px;
66 | font-size: 12pt;
67 | }
68 |
69 | @media only screen and (max-width: 721px) {
70 | .ui__disclaimer {
71 | width: 360px;
72 | }
73 | }
74 |
75 | .app_logo {
76 | margin-top: 64px;
77 | width: 120px;
78 | height: 120px;
79 | background-color: var(--color-accent-200);
80 | border-radius: 50%;
81 | animation: logo 30s linear infinite;
82 | }
83 |
84 | @keyframes logo {
85 | 0% {
86 | transform: rotate(0deg);
87 | background-color: var(--color-dark-red);
88 | }
89 |
90 | 33% {
91 | transform: rotate(360deg);
92 | background-color: var(--color-dark-green);
93 | }
94 |
95 | 67% {
96 | transform: rotate(720deg);
97 | background-color: var(--color-dark-blue);
98 | }
99 |
100 | 100% {
101 | transform: rotate(1080deg);
102 | background-color: var(--color-dark-red);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/theme/Theme.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | export const BaseTheme = {
18 | palette: {
19 | mode: 'dark',
20 | primary: {
21 | main: '#3786ff',
22 | },
23 | secondary: {
24 | main: '#00ffff',
25 | },
26 | error: {
27 | main: '#db4437',
28 | },
29 | warning: {
30 | main: '#ff3d00',
31 | },
32 | success: {
33 | main: '#2e8b57',
34 | },
35 | },
36 |
37 | components: {
38 | MuiButton: {
39 | styleOverrides: {
40 | root: {
41 | borderRadius: '50pc',
42 | },
43 | },
44 | },
45 | MuiPaper: {
46 | styleOverrides: {
47 | root: {
48 | borderRadius: '8px',
49 | minWidth: 320,
50 | },
51 |
52 | },
53 | },
54 | MuiDialogContentText: {
55 | styleOverrides: {
56 | root: {
57 | overflowWrap: "anywhere",
58 | userSelect: "text",
59 | },
60 | },
61 | }
62 | },
63 | }
64 |
--------------------------------------------------------------------------------
/src/theme/colors.css:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | :root {
18 | --color-primary-light: #ffffff;
19 | --color-secondary-light: rgba(255, 255, 255, 0.8);
20 | --color-tretinary-light: rgba(255, 255, 255, 0.7);
21 | /*--color-accent-overlay: rgba(24, 29, 26, 0.8);*/
22 | /*--color-accent-0: #181d1a;*/
23 | /*--color-accent-50: #141715;*/
24 | /*--color-accent-100: #181d1a;*/
25 | /*--color-accent-200: #29342c;*/
26 | /*--color-accent-300: #354e3d;*/
27 | /*--color-accent-400: #4c6754;*/
28 | /*--color-accent-800: #99ffbb;*/
29 | /*--color-accent-900: #d2ffdf;*/
30 |
31 | --color-accent-overlay: rgba(25, 25, 25, 0.8);
32 | --color-accent-0: #0e0e0e;
33 | --color-accent-50: #0f0f0f;
34 | --color-accent-100: #181818;
35 | --color-accent-200: #1f1f1f;
36 | --color-accent-300: #2a2d35;
37 | --color-accent-400: #383c43;
38 | --color-accent-800: #bbd3ff;
39 | --color-accent-900: #d6e3ff;
40 |
41 | /*--color-accent-overlay: rgba(26, 29, 35, 0.8);*/
42 | /*--color-accent-0: #181b22;*/
43 | /*--color-accent-50: #121417;*/
44 | /*--color-accent-100: #181c22;*/
45 | /*--color-accent-200: #20252e;*/
46 | /*--color-accent-300: #272f39;*/
47 | /*--color-accent-400: #374355;*/
48 | /*--color-accent-800: #bbd3ff;*/
49 | /*--color-accent-900: #d6e3ff;*/
50 |
51 | /*--color-accent-overlay: rgba(43, 32, 32, 0.8);*/
52 | /*--color-accent-0: #2b2020;*/
53 | /*--color-accent-50: #201919;*/
54 | /*--color-accent-100: #2b2020;*/
55 | /*--color-accent-200: #3e2c2c;*/
56 | /*--color-accent-300: #583e3e;*/
57 | /*--color-accent-400: #715555;*/
58 | /*--color-accent-800: #ffa9a9;*/
59 | /*--color-accent-900: #ffd6d6;*/
60 |
61 | --color-accent-1000: #ffffff;
62 |
63 | --color-primary-accent-transparent: rgba(255, 255, 255, 0.07);
64 | --color-secondary-accent: #00ffff;
65 | --color-disclaimer: #ffff00;
66 | --color-dark-red: #422121;
67 | --color-dark-green: #214221;
68 | --color-dark-blue: #212142;
69 | --color-autofill: #181d1a;
70 | --color-warn: #ffe6e4;
71 | --color-warn-transparent: rgba(155, 75, 66, 0.2);
72 | --color-warn-transparent-hover: rgba(219, 68, 55, 0.5);
73 | }
74 |
--------------------------------------------------------------------------------
/src/util/MarkDownCode.js:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import Prism from "../prism";
18 |
19 | export const linesNumbers = (str) => {
20 | let lines = str.split("\n").length - 1;
21 |
22 | let l = [];
23 |
24 | for (let i = 0; i < lines; i++) {
25 | l.push("" + (i+1) + "");
26 | }
27 |
28 | return l.join("\n");
29 | }
30 |
31 | export const highlightCode = (code, lang, l) => {
32 | try {
33 | return Prism.highlight(code, lang, l);
34 | } catch (e) {
35 | return null;
36 | }
37 | }
--------------------------------------------------------------------------------
/src/util/ModelTypeConverter.js:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | export const modelToType = (modelName) => {
18 | if (modelName === "gpt-3.5-turbo-0125") {
19 | return "GPT 3.5 (0125)"
20 | } else if (modelName.includes("gpt-3.5-turbo")) {
21 | return "GPT 3.5"
22 | } else if (modelName.includes("gpt-4-turbo")) {
23 | return "GPT 4 Turbo"
24 | } else if (modelName.includes("gpt-4")) {
25 | return "GPT 4"
26 | } else if (modelName.includes("o1")) {
27 | return "O1"
28 | } else {
29 | return "FT"
30 | }
31 | }
32 |
33 | export const supportedFileTypes = ["image/png", "image/jpeg", "image/jpg", "image/gif", "image/webp"];
34 |
--------------------------------------------------------------------------------
/src/widgets/MaterialEditText.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import { styled } from '@mui/material/styles';
18 | import './../theme/colors.css'
19 | import {TextField} from "@mui/material";
20 |
21 | export const MaterialEditText = styled(TextField)(({ theme }) => ({
22 | '&': {
23 | width: "100%"
24 | },
25 | '& label': {
26 | color: 'var(--color-accent-900)',
27 | },
28 | '& label.Mui-focused': {
29 | color: 'var(--color-accent-900)',
30 | },
31 | '& .MuiInput-underline:after': {
32 | borderBottomColor: 'var(--color-accent-900)',
33 | },
34 | '& .MuiOutlinedInput-root': {
35 | '&.Mui-focused fieldset': {
36 | borderColor: 'var(--color-accent-900)',
37 | color: 'var(--color-accent-900)',
38 | },
39 | },
40 | }));
--------------------------------------------------------------------------------
/src/widgets/NavigationBar.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import NavigationBarItem from "./NavigationBarItem";
19 | import {MaterialButtonTonal16, MaterialButtonTonal16V2} from "./MaterialButton";
20 | import {Tooltip} from "@mui/material";
21 | import {Link} from "react-router-dom";
22 |
23 | function NavigationBar({page, openAssistant}) {
24 | return (
25 |
61 | );
62 | }
63 |
64 | export default NavigationBar;
65 |
--------------------------------------------------------------------------------
/src/widgets/NavigationBarItem.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import {Link} from "react-router-dom";
19 | import {BrowserView, MobileView} from "react-device-detect";
20 |
21 | function NavigationBarItem({name, icon, isActive, page}) {
22 | return (
23 | <>
24 |
25 |
26 |
27 |
28 | {icon}
31 |
32 |
33 |
{name}
34 |
35 |
36 |
37 |
38 |
39 |
40 | {icon}
43 |
44 |
45 |
{name}
46 |
47 |
48 | >
49 | );
50 | }
51 |
52 | export default NavigationBarItem;
--------------------------------------------------------------------------------
/src/widgets/NavigationBarMobile.jsx:
--------------------------------------------------------------------------------
1 | /****************************************************************
2 | * Copyright (c) 2023-2025 Dmytro Ostapenko. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *****************************************************************/
16 |
17 | import React from 'react';
18 | import NavigationBarItem from "./NavigationBarItem";
19 |
20 | function NavigationBar({page, openAssistant}) {
21 | return (
22 |