@aj-archipelago/cortex 1.3.5 → 1.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/helper-apps/cortex-autogen/agents.py +31 -2
  2. package/helper-apps/cortex-realtime-voice-server/.env.sample +6 -0
  3. package/helper-apps/cortex-realtime-voice-server/README.md +22 -0
  4. package/helper-apps/cortex-realtime-voice-server/bun.lockb +0 -0
  5. package/helper-apps/cortex-realtime-voice-server/client/bun.lockb +0 -0
  6. package/helper-apps/cortex-realtime-voice-server/client/index.html +12 -0
  7. package/helper-apps/cortex-realtime-voice-server/client/package.json +65 -0
  8. package/helper-apps/cortex-realtime-voice-server/client/postcss.config.js +6 -0
  9. package/helper-apps/cortex-realtime-voice-server/client/public/favicon.ico +0 -0
  10. package/helper-apps/cortex-realtime-voice-server/client/public/index.html +43 -0
  11. package/helper-apps/cortex-realtime-voice-server/client/public/logo192.png +0 -0
  12. package/helper-apps/cortex-realtime-voice-server/client/public/logo512.png +0 -0
  13. package/helper-apps/cortex-realtime-voice-server/client/public/manifest.json +25 -0
  14. package/helper-apps/cortex-realtime-voice-server/client/public/robots.txt +3 -0
  15. package/helper-apps/cortex-realtime-voice-server/client/public/sounds/connect.mp3 +0 -0
  16. package/helper-apps/cortex-realtime-voice-server/client/public/sounds/disconnect.mp3 +0 -0
  17. package/helper-apps/cortex-realtime-voice-server/client/src/App.test.tsx +9 -0
  18. package/helper-apps/cortex-realtime-voice-server/client/src/App.tsx +126 -0
  19. package/helper-apps/cortex-realtime-voice-server/client/src/SettingsModal.tsx +207 -0
  20. package/helper-apps/cortex-realtime-voice-server/client/src/chat/Chat.tsx +553 -0
  21. package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatBubble.tsx +22 -0
  22. package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatBubbleLeft.tsx +22 -0
  23. package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatBubbleRight.tsx +21 -0
  24. package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatMessage.tsx +27 -0
  25. package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatMessageInput.tsx +74 -0
  26. package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatTile.tsx +211 -0
  27. package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/SoundEffects.ts +56 -0
  28. package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/WavPacker.ts +112 -0
  29. package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/WavRecorder.ts +571 -0
  30. package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/WavStreamPlayer.ts +290 -0
  31. package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/analysis/AudioAnalysis.ts +186 -0
  32. package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/analysis/constants.ts +59 -0
  33. package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/worklets/AudioProcessor.ts +214 -0
  34. package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/worklets/StreamProcessor.ts +183 -0
  35. package/helper-apps/cortex-realtime-voice-server/client/src/chat/components/AudioVisualizer.tsx +151 -0
  36. package/helper-apps/cortex-realtime-voice-server/client/src/chat/components/CopyButton.tsx +32 -0
  37. package/helper-apps/cortex-realtime-voice-server/client/src/chat/components/ImageOverlay.tsx +166 -0
  38. package/helper-apps/cortex-realtime-voice-server/client/src/chat/components/MicrophoneVisualizer.tsx +95 -0
  39. package/helper-apps/cortex-realtime-voice-server/client/src/chat/components/ScreenshotCapture.tsx +116 -0
  40. package/helper-apps/cortex-realtime-voice-server/client/src/chat/hooks/useWindowResize.ts +27 -0
  41. package/helper-apps/cortex-realtime-voice-server/client/src/chat/utils/audio.ts +33 -0
  42. package/helper-apps/cortex-realtime-voice-server/client/src/index.css +20 -0
  43. package/helper-apps/cortex-realtime-voice-server/client/src/index.tsx +19 -0
  44. package/helper-apps/cortex-realtime-voice-server/client/src/logo.svg +1 -0
  45. package/helper-apps/cortex-realtime-voice-server/client/src/react-app-env.d.ts +1 -0
  46. package/helper-apps/cortex-realtime-voice-server/client/src/reportWebVitals.ts +15 -0
  47. package/helper-apps/cortex-realtime-voice-server/client/src/setupTests.ts +5 -0
  48. package/helper-apps/cortex-realtime-voice-server/client/src/utils/logger.ts +45 -0
  49. package/helper-apps/cortex-realtime-voice-server/client/tailwind.config.js +14 -0
  50. package/helper-apps/cortex-realtime-voice-server/client/tsconfig.json +30 -0
  51. package/helper-apps/cortex-realtime-voice-server/client/vite.config.ts +22 -0
  52. package/helper-apps/cortex-realtime-voice-server/index.ts +19 -0
  53. package/helper-apps/cortex-realtime-voice-server/package.json +28 -0
  54. package/helper-apps/cortex-realtime-voice-server/src/ApiServer.ts +35 -0
  55. package/helper-apps/cortex-realtime-voice-server/src/SocketServer.ts +769 -0
  56. package/helper-apps/cortex-realtime-voice-server/src/Tools.ts +546 -0
  57. package/helper-apps/cortex-realtime-voice-server/src/cortex/expert.ts +29 -0
  58. package/helper-apps/cortex-realtime-voice-server/src/cortex/image.ts +29 -0
  59. package/helper-apps/cortex-realtime-voice-server/src/cortex/memory.ts +89 -0
  60. package/helper-apps/cortex-realtime-voice-server/src/cortex/reason.ts +29 -0
  61. package/helper-apps/cortex-realtime-voice-server/src/cortex/search.ts +30 -0
  62. package/helper-apps/cortex-realtime-voice-server/src/cortex/style.ts +31 -0
  63. package/helper-apps/cortex-realtime-voice-server/src/cortex/utils.ts +94 -0
  64. package/helper-apps/cortex-realtime-voice-server/src/cortex/vision.ts +34 -0
  65. package/helper-apps/cortex-realtime-voice-server/src/realtime/client.ts +484 -0
  66. package/helper-apps/cortex-realtime-voice-server/src/realtime/realtimeTypes.ts +279 -0
  67. package/helper-apps/cortex-realtime-voice-server/src/realtime/socket.ts +27 -0
  68. package/helper-apps/cortex-realtime-voice-server/src/realtime/transcription.ts +75 -0
  69. package/helper-apps/cortex-realtime-voice-server/src/realtime/utils.ts +33 -0
  70. package/helper-apps/cortex-realtime-voice-server/src/utils/logger.ts +45 -0
  71. package/helper-apps/cortex-realtime-voice-server/src/utils/prompt.ts +81 -0
  72. package/helper-apps/cortex-realtime-voice-server/tsconfig.json +28 -0
  73. package/package.json +1 -1
  74. package/pathways/basePathway.js +3 -1
  75. package/pathways/system/entity/memory/sys_memory_manager.js +3 -0
  76. package/pathways/system/entity/memory/sys_memory_update.js +42 -44
  77. package/pathways/system/entity/memory/sys_read_memory.js +86 -6
  78. package/pathways/system/entity/memory/sys_search_memory.js +66 -0
  79. package/pathways/system/entity/shared/sys_entity_constants.js +1 -1
  80. package/pathways/system/entity/sys_entity_continue.js +2 -1
  81. package/pathways/system/entity/sys_entity_start.js +10 -0
  82. package/pathways/system/entity/sys_generator_expert.js +0 -2
  83. package/pathways/system/entity/sys_generator_memory.js +31 -0
  84. package/pathways/system/entity/sys_generator_voice_sample.js +36 -0
  85. package/pathways/system/entity/sys_router_tool.js +13 -10
  86. package/pathways/system/sys_parse_numbered_object_list.js +1 -1
  87. package/server/pathwayResolver.js +41 -31
  88. package/server/plugins/azureVideoTranslatePlugin.js +28 -16
  89. package/server/plugins/claude3VertexPlugin.js +0 -9
  90. package/server/plugins/gemini15ChatPlugin.js +18 -5
  91. package/server/plugins/modelPlugin.js +27 -6
  92. package/server/plugins/openAiChatPlugin.js +10 -8
  93. package/server/plugins/openAiVisionPlugin.js +56 -0
  94. package/tests/memoryfunction.test.js +73 -1
@@ -20,6 +20,7 @@ import shutil
20
20
 
21
21
  human_input_queues = {}
22
22
  human_input_text_queues = {}
23
+ request_stored_message_queues = {}
23
24
  def background_human_input_check(request_id):
24
25
  while True:
25
26
  human_input = check_for_human_input(request_id)
@@ -176,6 +177,14 @@ def chat_with_agents(**kwargs):
176
177
  except Exception as e:
177
178
  logging.error(f"Error extracting code corrector result: {e}")
178
179
 
180
+ try:
181
+ request_stored_message_queues[request_id].put(all_messages[-2]["message"] or all_messages[-2]["content"])
182
+ request_stored_message_queues[request_id].put(all_messages[-1]["message"] or all_messages[-1]["content"])
183
+ except Exception as e:
184
+ logging.error(f"Error storing messages in queue: {e}")
185
+
186
+
187
+
179
188
  if return_type == "chat_history":
180
189
  return chat_result.chat_history
181
190
  if return_type == "chat_result":
@@ -249,6 +258,9 @@ def process_message(original_request_message_data, original_request_message_data
249
258
 
250
259
  human_input_queues[request_id] = queue.Queue()
251
260
  human_input_text_queues[request_id] = queue.Queue()
261
+ if not request_stored_message_queues.get(request_id):
262
+ request_stored_message_queues[request_id] = queue.Queue()
263
+ request_stored_message_queues[request_id].put(original_request_message)
252
264
 
253
265
  if first_run:
254
266
  thread = threading.Thread(target=background_human_input_check, args=(request_id,))
@@ -275,7 +287,7 @@ def process_message(original_request_message_data, original_request_message_data
275
287
 
276
288
  #wait for any human input before terminating
277
289
  #if you receive human input start the conversation again
278
- for i in range(16*6): # 15+1 minutes
290
+ for i in range(31*6): # 30+1 minutes
279
291
  if human_input_queues[request_id].empty():
280
292
  time.sleep(1)
281
293
  else:
@@ -284,11 +296,28 @@ def process_message(original_request_message_data, original_request_message_data
284
296
  logging.info(f"Human input to assistant: {human_input}")
285
297
  #update request with human input
286
298
  new_message_data = original_request_message_data.copy()
287
- new_message_data['message'] = human_input
299
+
300
+ old_task = original_request_message_data.get("message")
301
+
302
+ #get request_stored_message_queues
303
+ old_messages = []
304
+ if request_stored_message_queues.get(request_id):
305
+ while not request_stored_message_queues[request_id].empty():
306
+ old_messages.append(request_stored_message_queues[request_id].get())
307
+
308
+
309
+ #convert to text, limit to max 2000 characters, keep most recent
310
+ old_messages_text = "\n".join(old_messages)
311
+ old_messages_text = old_messages_text[-2000:]
312
+
313
+
314
+ new_message_data['message'] = f"NEW TASK: {human_input}\n\nPREV TASK: {old_task} STUFF DONE IN PREV TASK: {old_messages_text}\n\n{final_msg}\n\n"
288
315
  new_message_data['keywords'] = ''
289
316
  # new_message_data_obj = original_request_message_data_obj.copy()
290
317
  # new_message_data_obj['message'] = new_message_data['message']
291
318
 
319
+
320
+
292
321
  process_message(new_message_data, original_request_message_data_obj, first_run=False)
293
322
  return
294
323
 
@@ -0,0 +1,6 @@
1
+ CORTEX_API_KEY=...
2
+ CORTEX_DEV_API_KEY=...
3
+ OPENAI_API_KEY=...
4
+ CORS_HOSTS='["http://localhost:3000"]'
5
+ PORT=8081
6
+ VOICE_LIB_DEBUG=false
@@ -0,0 +1,22 @@
1
+ # cortex-realtime-voice
2
+
3
+ To install dependencies:
4
+
5
+ ```bash
6
+ bun install
7
+ ```
8
+
9
+ To run:
10
+
11
+ ```bash
12
+ cd client
13
+ bun run build
14
+ cd ..
15
+ bun run start
16
+ ```
17
+
18
+ To run in production:
19
+
20
+ ```bash
21
+ bun run start:prod
22
+ ```
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Cortex Realtime Voice</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/index.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "client",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "dependencies": {
6
+ "@emotion/react": "^11.14.0",
7
+ "@emotion/styled": "^11.14.0",
8
+ "@mui/icons-material": "^6.2.0",
9
+ "@mui/material": "^6.2.0",
10
+ "@tailwindcss/typography": "^0.5.15",
11
+ "katex": "^0.16.15",
12
+ "react": "^19.0.0",
13
+ "react-dom": "^19.0.0",
14
+ "react-markdown": "^9.0.1",
15
+ "react-spinners": "0.15.0",
16
+ "react-syntax-highlighter": "^15.6.1",
17
+ "rehype-katex": "^7.0.1",
18
+ "rehype-raw": "^7.0.0",
19
+ "remark-gfm": "^4.0.0",
20
+ "remark-math": "^6.0.0",
21
+ "socket.io-client": "4.8.1",
22
+ "typescript": "^4.4.2",
23
+ "web-vitals": "^2.1.0"
24
+ },
25
+ "devDependencies": {
26
+ "@babel/plugin-proposal-private-property-in-object": "7.21.11",
27
+ "@testing-library/jest-dom": "^5.14.1",
28
+ "@testing-library/react": "^13.0.0",
29
+ "@testing-library/user-event": "^13.2.1",
30
+ "@types/jest": "^27.0.1",
31
+ "@types/node": "^16.7.13",
32
+ "@types/react": "^18.0.0",
33
+ "@types/react-dom": "^18.0.0",
34
+ "@types/react-syntax-highlighter": "^15.5.13",
35
+ "@vitejs/plugin-react": "^4.3.4",
36
+ "autoprefixer": "^10.4.20",
37
+ "postcss": "^8.4.49",
38
+ "tailwindcss": "^3.4.17",
39
+ "vite": "^6.0.5"
40
+ },
41
+ "scripts": {
42
+ "start": "vite",
43
+ "dev": "vite",
44
+ "build": "vite build",
45
+ "preview": "vite preview"
46
+ },
47
+ "eslintConfig": {
48
+ "extends": [
49
+ "react-app",
50
+ "react-app/jest"
51
+ ]
52
+ },
53
+ "browserslist": {
54
+ "production": [
55
+ ">0.2%",
56
+ "not dead",
57
+ "not op_mini all"
58
+ ],
59
+ "development": [
60
+ "last 1 chrome version",
61
+ "last 1 firefox version",
62
+ "last 1 safari version"
63
+ ]
64
+ }
65
+ }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
@@ -0,0 +1,43 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <meta name="theme-color" content="#000000" />
8
+ <meta
9
+ name="description"
10
+ content="Chat with the Cortex Realtime Voice Server"
11
+ />
12
+ <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
13
+ <!--
14
+ manifest.json provides metadata used when your web app is installed on a
15
+ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
16
+ -->
17
+ <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
18
+ <!--
19
+ Notice the use of %PUBLIC_URL% in the tags above.
20
+ It will be replaced with the URL of the `public` folder during the build.
21
+ Only files inside the `public` folder can be referenced from the HTML.
22
+
23
+ Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
24
+ work correctly both with client-side routing and a non-root public URL.
25
+ Learn how to configure a non-root public URL by running `npm run build`.
26
+ -->
27
+ <title>Cortex Realtime Voice</title>
28
+ </head>
29
+ <body>
30
+ <noscript>You need to enable JavaScript to run this app.</noscript>
31
+ <div id="root"></div>
32
+ <!--
33
+ This HTML file is a template.
34
+ If you open it directly in the browser, you will see an empty page.
35
+
36
+ You can add webfonts, meta tags, or analytics to this file.
37
+ The build step will place the bundled scripts into the <body> tag.
38
+
39
+ To begin the development, run `npm start` or `yarn start`.
40
+ To create a production bundle, use `npm run build` or `yarn build`.
41
+ -->
42
+ </body>
43
+ </html>
@@ -0,0 +1,25 @@
1
+ {
2
+ "short_name": "React App",
3
+ "name": "Create React App Sample",
4
+ "icons": [
5
+ {
6
+ "src": "favicon.ico",
7
+ "sizes": "64x64 32x32 24x24 16x16",
8
+ "type": "image/x-icon"
9
+ },
10
+ {
11
+ "src": "logo192.png",
12
+ "type": "image/png",
13
+ "sizes": "192x192"
14
+ },
15
+ {
16
+ "src": "logo512.png",
17
+ "type": "image/png",
18
+ "sizes": "512x512"
19
+ }
20
+ ],
21
+ "start_url": ".",
22
+ "display": "standalone",
23
+ "theme_color": "#000000",
24
+ "background_color": "#ffffff"
25
+ }
@@ -0,0 +1,3 @@
1
+ # https://www.robotstxt.org/robotstxt.html
2
+ User-agent: *
3
+ Disallow:
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import App from './App';
4
+
5
+ test('renders learn react link', () => {
6
+ render(<App />);
7
+ const linkElement = screen.getByText(/learn react/i);
8
+ expect(linkElement).toBeInTheDocument();
9
+ });
@@ -0,0 +1,126 @@
1
+ import {useEffect, useState} from 'react';
2
+ import ClipLoader from "react-spinners/ClipLoader";
3
+ import Chat from "./chat/Chat";
4
+ import {SettingsModal} from "./SettingsModal";
5
+ import { SettingsData } from "./SettingsModal";
6
+ import type { Voice } from '../../src/realtime/realtimeTypes';
7
+
8
+ function App() {
9
+ const [loading, setLoading] = useState(true);
10
+ const [userName, setUserName] = useState('');
11
+ const [userId, setUserId] = useState('');
12
+ const [aiName, setAiName] = useState('Jarvis');
13
+ const [settingsOpen, setSettingsOpen] = useState(false);
14
+ const [language, setLanguage] = useState('en');
15
+ const [aiMemorySelfModify, setAiMemorySelfModify] = useState(false);
16
+ const [aiStyle, setAiStyle] = useState('Anthropic');
17
+ const [voice, setVoice] = useState('alloy' as Voice);
18
+
19
+ const onCloseSettings = () => setSettingsOpen(false);
20
+ const onSaveSettings = (settings: SettingsData) => {
21
+ console.log('Saving settings', settings);
22
+ setUserName(settings.userName);
23
+ localStorage.setItem('userName', settings.userName);
24
+
25
+ let newUserId = settings.userId;
26
+ if (!newUserId || newUserId.length === 0) {
27
+ newUserId = Math.random().toString(36).substring(7);
28
+ }
29
+ setUserId(newUserId);
30
+ localStorage.setItem('userId', newUserId);
31
+
32
+ setAiName(settings.aiName);
33
+ localStorage.setItem('aiName', settings.aiName);
34
+
35
+ setLanguage(settings.language);
36
+ localStorage.setItem('language', settings.language);
37
+
38
+ setAiMemorySelfModify(settings.aiMemorySelfModify);
39
+ localStorage.setItem('aiMemorySelfModify', String(settings.aiMemorySelfModify));
40
+
41
+ setAiStyle(settings.aiStyle);
42
+ localStorage.setItem('aiStyle', settings.aiStyle);
43
+
44
+ setVoice(settings.voice as Voice);
45
+ localStorage.setItem('voice', settings.voice);
46
+ };
47
+
48
+ useEffect(() => {
49
+ const name = localStorage.getItem('userName');
50
+ if (name) {
51
+ setUserName(localStorage.getItem('userName') as string);
52
+ } else {
53
+ setSettingsOpen(true);
54
+ }
55
+ const id = localStorage.getItem('userId');
56
+ if (id) {
57
+ setUserId(localStorage.getItem('userId') as string);
58
+ } else {
59
+ setSettingsOpen(true);
60
+ }
61
+ const ai = localStorage.getItem('aiName');
62
+ if (ai) {
63
+ setAiName(localStorage.getItem('aiName') as string);
64
+ } else {
65
+ setSettingsOpen(true);
66
+ }
67
+ const savedLanguage = localStorage.getItem('language');
68
+ if (savedLanguage) setLanguage(savedLanguage);
69
+
70
+ const savedAiMemorySelfModify = localStorage.getItem('aiMemorySelfModify');
71
+ if (savedAiMemorySelfModify) setAiMemorySelfModify(savedAiMemorySelfModify === 'true');
72
+
73
+ const savedAiStyle = localStorage.getItem('aiStyle');
74
+ if (savedAiStyle) setAiStyle(savedAiStyle);
75
+
76
+ const savedVoice = localStorage.getItem('voice');
77
+ if (savedVoice) setVoice(savedVoice as Voice);
78
+
79
+ setLoading(false);
80
+ }, []);
81
+
82
+ if (loading) {
83
+ return (
84
+ <div className="min-h-screen bg-gradient-to-b from-gray-900 via-gray-800 to-gray-900 flex justify-center items-center">
85
+ <ClipLoader color={'#0EA5E9'} loading={true} size={150}/>
86
+ </div>
87
+ );
88
+ }
89
+
90
+ return (
91
+ <div className="h-screen overflow-hidden bg-gradient-to-b from-gray-900 via-gray-800 to-gray-900">
92
+ <button
93
+ className="fixed top-4 right-4 z-10 p-2 text-gray-400 hover:text-cyan-400 transition-colors duration-200"
94
+ onClick={() => setSettingsOpen(true)}
95
+ aria-label="Settings"
96
+ >
97
+ ⚙️
98
+ </button>
99
+
100
+ {userName && userName.length > 0 && (
101
+ <Chat
102
+ userId={userId}
103
+ userName={userName}
104
+ aiName={aiName}
105
+ language={language}
106
+ aiMemorySelfModify={aiMemorySelfModify}
107
+ aiStyle={aiStyle}
108
+ voice={voice}
109
+ />
110
+ )}
111
+ <SettingsModal
112
+ aiName={aiName}
113
+ userName={userName}
114
+ userId={userId}
115
+ voice={voice}
116
+ aiStyle={aiStyle}
117
+ language={language}
118
+ isOpen={settingsOpen}
119
+ onClose={onCloseSettings}
120
+ onSave={onSaveSettings}
121
+ />
122
+ </div>
123
+ );
124
+ }
125
+
126
+ export default App;
@@ -0,0 +1,207 @@
1
+ import {ChangeEvent, FormEvent, useState} from 'react';
2
+ import type { Voice, OpenAIVoice, AzureVoice } from '../../src/realtime/realtimeTypes';
3
+
4
+ type SettingsModalProps = {
5
+ aiName: string;
6
+ userName: string;
7
+ userId: string;
8
+ voice: Voice;
9
+ aiStyle: string;
10
+ language: string;
11
+ isOpen: boolean;
12
+ onClose: () => void;
13
+ onSave: (settings: SettingsData) => void;
14
+ }
15
+
16
+ export type SettingsData = {
17
+ userName: string;
18
+ userId: string;
19
+ aiName: string;
20
+ language: string;
21
+ aiMemorySelfModify: boolean;
22
+ aiStyle: string;
23
+ voice: Voice;
24
+ }
25
+
26
+ // Define voice lists
27
+ const openaiVoices: OpenAIVoice[] = ['alloy', 'echo', 'shimmer', 'ash', 'ballad', 'coral', 'sage', 'verse'];
28
+ const azureVoices: AzureVoice[] = ['amuch', 'dan', 'elan', 'marilyn', 'meadow', 'breeze', 'cove', 'ember', 'jupiter', 'alloy', 'echo', 'shimmer'];
29
+
30
+ // Check if we're using Azure based on the environment variable
31
+ const isAzure = import.meta.env.VITE_VOICE_PROVIDER === 'azure';
32
+
33
+ export const SettingsModal = (
34
+ {aiName, userName, userId, voice, aiStyle, language, isOpen, onClose, onSave}: SettingsModalProps
35
+ ) => {
36
+ const [formData, setFormData] = useState<SettingsData>({
37
+ aiName,
38
+ userName,
39
+ userId,
40
+ language,
41
+ aiMemorySelfModify: false,
42
+ aiStyle,
43
+ voice
44
+ });
45
+
46
+ const handleChange = (e: ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
47
+ const { name, value, type } = e.target;
48
+ setFormData({
49
+ ...formData,
50
+ [name]: type === 'checkbox' ? (e.target as HTMLInputElement).checked : value
51
+ });
52
+ };
53
+
54
+ const handleSubmit = (e: FormEvent) => {
55
+ e.preventDefault();
56
+ onSave(formData);
57
+ onClose();
58
+ };
59
+
60
+ return (
61
+ <div className={`fixed inset-0 z-50 overflow-y-auto ${isOpen ? 'block' : 'hidden'}`}>
62
+ <div className="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
63
+ <div className="fixed inset-0 transition-opacity bg-gray-900 bg-opacity-75 backdrop-blur-sm" aria-hidden="true" />
64
+
65
+ <span className="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
66
+
67
+ <div className="inline-block w-full max-w-md p-6 my-8 overflow-hidden text-left align-middle transition-all transform bg-gray-800 border border-gray-700/50 rounded-2xl shadow-2xl sm:align-middle">
68
+ <h3 className="text-lg font-medium leading-6 text-gray-100 mb-4">
69
+ System Configuration
70
+ </h3>
71
+
72
+ <form onSubmit={handleSubmit} className="space-y-4">
73
+ <div>
74
+ <label className="block text-sm font-medium text-gray-300 mb-1">
75
+ Your Name
76
+ </label>
77
+ <input
78
+ type="text"
79
+ name="userName"
80
+ className="w-full px-3 py-2 bg-gray-700/50 border border-gray-600/50 rounded-lg text-gray-100 focus:outline-none focus:ring-2 focus:ring-cyan-500/50"
81
+ value={formData.userName}
82
+ onChange={handleChange}
83
+ />
84
+ </div>
85
+
86
+ <div>
87
+ <label className="block text-sm font-medium text-gray-300 mb-1">
88
+ AI Name
89
+ </label>
90
+ <input
91
+ type="text"
92
+ name="aiName"
93
+ className="w-full px-3 py-2 bg-gray-700/50 border border-gray-600/50 rounded-lg text-gray-100 focus:outline-none focus:ring-2 focus:ring-cyan-500/50"
94
+ value={formData.aiName}
95
+ onChange={handleChange}
96
+ />
97
+ </div>
98
+
99
+ <div>
100
+ <label className="block text-sm font-medium text-gray-300 mb-1">
101
+ Voice
102
+ </label>
103
+ <select
104
+ name="voice"
105
+ className="w-full px-3 py-2 bg-gray-700/50 border border-gray-600/50 rounded-lg text-gray-100 focus:outline-none focus:ring-2 focus:ring-cyan-500/50"
106
+ value={formData.voice}
107
+ onChange={handleChange}
108
+ >
109
+ {isAzure ? (
110
+ <optgroup label="Azure Voices">
111
+ {azureVoices.map(voice => (
112
+ <option key={voice} value={voice}>
113
+ {voice.charAt(0).toUpperCase() + voice.slice(1)}
114
+ </option>
115
+ ))}
116
+ </optgroup>
117
+ ) : (
118
+ <optgroup label="OpenAI Voices">
119
+ {openaiVoices.map(voice => (
120
+ <option key={voice} value={voice}>
121
+ {voice.charAt(0).toUpperCase() + voice.slice(1)}
122
+ </option>
123
+ ))}
124
+ </optgroup>
125
+ )}
126
+ </select>
127
+ </div>
128
+
129
+ <div>
130
+ <label className="block text-sm font-medium text-gray-300 mb-1">
131
+ Language
132
+ </label>
133
+ <select
134
+ name="language"
135
+ className="w-full px-3 py-2 bg-gray-700/50 border border-gray-600/50 rounded-lg text-gray-100 focus:outline-none focus:ring-2 focus:ring-cyan-500/50"
136
+ value={formData.language}
137
+ onChange={handleChange}
138
+ >
139
+ <option value="en">English</option>
140
+ <option value="es">Español</option>
141
+ <option value="fr">Français</option>
142
+ <option value="de">Deutsch</option>
143
+ <option value="it">Italiano</option>
144
+ <option value="pt">Português</option>
145
+ <option value="ru">Русский</option>
146
+ <option value="zh">中文</option>
147
+ <option value="ja">日本語</option>
148
+ <option value="ko">한국어</option>
149
+ </select>
150
+ </div>
151
+
152
+ <div>
153
+ <label className="block text-sm font-medium text-gray-300 mb-1">
154
+ AI Style
155
+ </label>
156
+ <select
157
+ name="aiStyle"
158
+ className="w-full px-3 py-2 bg-gray-700/50 border border-gray-600/50 rounded-lg text-gray-100 focus:outline-none focus:ring-2 focus:ring-cyan-500/50"
159
+ value={formData.aiStyle}
160
+ onChange={handleChange}
161
+ >
162
+ <option value="Anthropic">Anthropic</option>
163
+ <option value="OpenAI">OpenAI</option>
164
+ </select>
165
+ </div>
166
+
167
+ <div>
168
+ <label className="block text-sm font-medium text-gray-300 mb-1">
169
+ Memory Key
170
+ </label>
171
+ <input
172
+ type="text"
173
+ name="userId"
174
+ className="w-full px-3 py-2 bg-gray-700/50 border border-gray-600/50 rounded-lg text-gray-100 focus:outline-none focus:ring-2 focus:ring-cyan-500/50"
175
+ value={formData.userId}
176
+ onChange={handleChange}
177
+ />
178
+ </div>
179
+
180
+ <div className="flex items-center">
181
+ <input
182
+ type="checkbox"
183
+ id="aiMemorySelfModify"
184
+ name="aiMemorySelfModify"
185
+ checked={formData.aiMemorySelfModify}
186
+ onChange={handleChange}
187
+ className="w-4 h-4 border-gray-600 rounded bg-gray-700 text-cyan-500 focus:ring-cyan-500/50"
188
+ />
189
+ <label htmlFor="aiMemorySelfModify" className="ml-2 text-sm text-gray-300">
190
+ Enable AI Memory Self-Modification
191
+ </label>
192
+ </div>
193
+
194
+ <div className="flex justify-end mt-6">
195
+ <button
196
+ type="submit"
197
+ className="px-4 py-2 bg-gradient-to-r from-blue-500 to-cyan-500 hover:from-blue-600 hover:to-cyan-600 text-white rounded-lg shadow-lg shadow-cyan-500/20 focus:outline-none focus:ring-2 focus:ring-cyan-500/50"
198
+ >
199
+ Save Configuration
200
+ </button>
201
+ </div>
202
+ </form>
203
+ </div>
204
+ </div>
205
+ </div>
206
+ );
207
+ }