diff --git a/.gitignore b/.gitignore
index 0b19c9c..db3669d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,11 @@ dist/
.env
*.log
+# Nx
+.nx
+tmp
+.cache
+
# Vite build
.vite/
@@ -28,4 +33,7 @@ yarn.lock
.terraform/
*.tfstate
*.tfstate.backup
-.terraform.lock.hcl
\ No newline at end of file
+.terraform.lock.hcl
+.nx/installation
+.nx/cache
+.nx/workspace-data
\ No newline at end of file
diff --git a/api/project.json b/api/project.json
new file mode 100644
index 0000000..4e717df
--- /dev/null
+++ b/api/project.json
@@ -0,0 +1,12 @@
+{
+ "name": "api",
+ "targets": {
+ "dev": {
+ "executor": "nx:run-commands",
+ "options": {
+ "command": "npm run dev",
+ "cwd": "api"
+ }
+ }
+ }
+}
diff --git a/nx b/nx
new file mode 100755
index 0000000..e94326e
--- /dev/null
+++ b/nx
@@ -0,0 +1,5 @@
+#!/bin/bash
+command -v node >/dev/null 2>&1 || { echo >&2 "Nx requires NodeJS to be available. To install NodeJS and NPM, see: https://nodejs.org/en/download/ ."; exit 1; }
+command -v npm >/dev/null 2>&1 || { echo >&2 "Nx requires npm to be available. To install NodeJS and NPM, see: https://nodejs.org/en/download/ ."; exit 1; }
+path_to_root=$(dirname $BASH_SOURCE)
+node $path_to_root/.nx/nxw.js $@
\ No newline at end of file
diff --git a/nx.bat b/nx.bat
new file mode 100644
index 0000000..d6b09b7
--- /dev/null
+++ b/nx.bat
@@ -0,0 +1,10 @@
+@ECHO OFF
+SETLOCAL
+SET path_to_root=%~dp0
+WHERE node >nul 2>nul
+IF %ERRORLEVEL% NEQ 0 (ECHO Nx requires NodeJS to be available. To install NodeJS and NPM, see: https://nodejs.org/en/download/ . & GOTO exit)
+WHERE npm >nul 2>nul
+IF %ERRORLEVEL% NEQ 0 (ECHO Nx requires npm to be available. To install NodeJS and NPM, see: https://nodejs.org/en/download/ . & GOTO exit)
+node %path_to_root%\.nx\nxw.js %*
+:exit
+ cmd /c exit /b %ERRORLEVEL%
\ No newline at end of file
diff --git a/nx.json b/nx.json
new file mode 100644
index 0000000..4a52298
--- /dev/null
+++ b/nx.json
@@ -0,0 +1,16 @@
+// tools/dev-runner/project.json
+{
+ "name": "dev-runner",
+ "targets": {
+ "start": {
+ "executor": "nx:run-commands",
+ "options": {
+ "commands": [
+ { "command": "nx run api:dev" },
+ { "command": "nx run react-native-client:start" }
+ ],
+ "parallel": true
+ }
+ }
+ }
+}
diff --git a/react-native-client/project.json b/react-native-client/project.json
new file mode 100644
index 0000000..e3432fd
--- /dev/null
+++ b/react-native-client/project.json
@@ -0,0 +1,12 @@
+{
+ "name": "react-native-client",
+ "targets": {
+ "start": {
+ "executor": "nx:run-commands",
+ "options": {
+ "command": "npx expo start",
+ "cwd": "react-native-client"
+ }
+ }
+ }
+}
diff --git a/tools/dev-runner/project.json b/tools/dev-runner/project.json
new file mode 100644
index 0000000..4a52298
--- /dev/null
+++ b/tools/dev-runner/project.json
@@ -0,0 +1,16 @@
+// tools/dev-runner/project.json
+{
+ "name": "dev-runner",
+ "targets": {
+ "start": {
+ "executor": "nx:run-commands",
+ "options": {
+ "commands": [
+ { "command": "nx run api:dev" },
+ { "command": "nx run react-native-client:start" }
+ ],
+ "parallel": true
+ }
+ }
+ }
+}
diff --git a/vite-client/.gitignore b/vite-client/.gitignore
deleted file mode 100644
index a547bf3..0000000
--- a/vite-client/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
-
-node_modules
-dist
-dist-ssr
-*.local
-
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-.DS_Store
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
diff --git a/vite-client/README.md b/vite-client/README.md
deleted file mode 100644
index f768e33..0000000
--- a/vite-client/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# React + Vite
-
-This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
-
-Currently, two official plugins are available:
-
-- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
-- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
diff --git a/vite-client/eslint.config.js b/vite-client/eslint.config.js
deleted file mode 100644
index 238d2e4..0000000
--- a/vite-client/eslint.config.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import js from '@eslint/js'
-import globals from 'globals'
-import react from 'eslint-plugin-react'
-import reactHooks from 'eslint-plugin-react-hooks'
-import reactRefresh from 'eslint-plugin-react-refresh'
-
-export default [
- { ignores: ['dist'] },
- {
- files: ['**/*.{js,jsx}'],
- languageOptions: {
- ecmaVersion: 2020,
- globals: globals.browser,
- parserOptions: {
- ecmaVersion: 'latest',
- ecmaFeatures: { jsx: true },
- sourceType: 'module',
- },
- },
- settings: { react: { version: '18.3' } },
- plugins: {
- react,
- 'react-hooks': reactHooks,
- 'react-refresh': reactRefresh,
- },
- rules: {
- ...js.configs.recommended.rules,
- ...react.configs.recommended.rules,
- ...react.configs['jsx-runtime'].rules,
- ...reactHooks.configs.recommended.rules,
- 'react/jsx-no-target-blank': 'off',
- 'react-refresh/only-export-components': [
- 'warn',
- { allowConstantExport: true },
- ],
- },
- },
-]
diff --git a/vite-client/index.html b/vite-client/index.html
deleted file mode 100644
index 72e104a..0000000
--- a/vite-client/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
- Scrying AI - DEV
-
-
-
-
-
-
diff --git a/vite-client/package.json b/vite-client/package.json
deleted file mode 100644
index 5e302c0..0000000
--- a/vite-client/package.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "name": "client",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "vite build",
- "lint": "eslint .",
- "preview": "vite preview"
- },
- "dependencies": {
- "@emotion/react": "^11.14.0",
- "@emotion/styled": "^11.14.0",
- "@formkit/auto-animate": "^0.8.2",
- "@mui/icons-material": "^6.4.7",
- "@mui/material": "^6.4.7",
- "axios": "^1.7.9",
- "lodash": "^4.17.21",
- "react": "^19.0.0",
- "react-dom": "^19.0.0",
- "socket.io-client": "^4.8.1",
- "uuid": "^11.1.0"
- },
- "devDependencies": {
- "@eslint/js": "^9.19.0",
- "@types/react": "^19.0.8",
- "@types/react-dom": "^19.0.3",
- "@vitejs/plugin-react": "^4.3.4",
- "eslint": "^9.19.0",
- "eslint-plugin-react": "^7.37.4",
- "eslint-plugin-react-hooks": "^5.0.0",
- "eslint-plugin-react-refresh": "^0.4.18",
- "globals": "^15.14.0",
- "prettier": "^3.5.3",
- "vite": "^6.1.0"
- }
-}
diff --git a/vite-client/public/vite.svg b/vite-client/public/vite.svg
deleted file mode 100644
index e7b8dfb..0000000
--- a/vite-client/public/vite.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/vite-client/src/App.css b/vite-client/src/App.css
deleted file mode 100644
index 8bc1d0c..0000000
--- a/vite-client/src/App.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.logo {
- height: 6em;
- padding: 1.5em;
- will-change: filter;
- transition: filter 300ms;
-}
-.logo:hover {
- filter: drop-shadow(0 0 2em #646cffaa);
-}
-.logo.react:hover {
- filter: drop-shadow(0 0 2em #61dafbaa);
-}
-
-@keyframes logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
-
-@media (prefers-reduced-motion: no-preference) {
- a:nth-of-type(2) .logo {
- animation: logo-spin infinite 20s linear;
- }
-}
-
-.card {
- padding: 2em;
- border-radius: 0.4em;
- box-shadow: 5px 5px 14px rgba(0, 0, 0, 0.4);
- background-color: #272b2b;
-}
-
-.read-the-docs {
- color: #888;
-}
diff --git a/vite-client/src/App.jsx b/vite-client/src/App.jsx
deleted file mode 100644
index 769132b..0000000
--- a/vite-client/src/App.jsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import "./App.css";
-import SuggestionsPage from "./pages/SuggestionsPage.jsx";
-import { CssBaseline, ThemeProvider } from "@mui/material";
-import { theme } from "./theme.js";
-import { SocketProvider } from "./providers/SocketProvider.jsx";
-import { SuggestionsProvider } from "./providers/SuggestionsProvider.jsx";
-
-function App() {
- return (
-
-
-
-
-
-
-
-
- );
-}
-
-export default App;
diff --git a/vite-client/src/components/LoadingBars.jsx b/vite-client/src/components/LoadingBars.jsx
deleted file mode 100644
index a0b3de6..0000000
--- a/vite-client/src/components/LoadingBars.jsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from 'react';
-import {SvgIcon} from "@mui/material";
-
-export function LoadingBarsIcon(props){
- return (
-
- {/* credit: cog icon from https://heroicons.com */}
-
-
- )
-
-}
\ No newline at end of file
diff --git a/vite-client/src/components/SpeechToText.jsx b/vite-client/src/components/SpeechToText.jsx
deleted file mode 100644
index 316bf5a..0000000
--- a/vite-client/src/components/SpeechToText.jsx
+++ /dev/null
@@ -1,24 +0,0 @@
-// src/components/SpeechToText.jsx
-import React from 'react';
-import useSpeechRecognition from '../hooks/useSpeechRecognition';
-
-const SpeechToText = () => {
- const { transcript, listening, startListening, stopListening } = useSpeechRecognition();
-
- return (
-
-
🎙️ Live Speech Recognition
-
-
{transcript}
-
- );
-};
-
-export default SpeechToText;
diff --git a/vite-client/src/components/SuggestionControlContainer.jsx b/vite-client/src/components/SuggestionControlContainer.jsx
deleted file mode 100644
index 35d8d7b..0000000
--- a/vite-client/src/components/SuggestionControlContainer.jsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import React from "react";
-import { Button, Grid2, Paper, Typography } from "@mui/material";
-import StopIcon from "@mui/icons-material/Stop";
-import AutoAwesomeIcon from "@mui/icons-material/AutoAwesome";
-import * as PropTypes from "prop-types";
-import { useAutoAnimate } from "@formkit/auto-animate/react";
-
-export default function SuggestionControlContainer(props) {
- const [parent] = useAutoAnimate();
-
- const buttonStyles = {
- transition: "all 0.8s ease",
- "&:focus": {
- outline: "none",
- },
- };
-
- return (
-
-
-
-
- {props.show
- ? "Searching vast distances..."
- : 'To get suggestions, click "Begin Scrying"'}
-
-
-
-
-
-
-
- );
-}
-
-SuggestionControlContainer.propTypes = {
- show: PropTypes.bool.isRequired,
- listen: PropTypes.func.isRequired,
-};
diff --git a/vite-client/src/components/SuggestionItem.jsx b/vite-client/src/components/SuggestionItem.jsx
deleted file mode 100644
index b6f6a93..0000000
--- a/vite-client/src/components/SuggestionItem.jsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from "react";
-import { alpha, Grid2, Typography } from "@mui/material";
-import AutoAwesomeIcon from "@mui/icons-material/AutoAwesome";
-import CommentIcon from "@mui/icons-material/Comment";
-import * as PropTypes from "prop-types";
-
-export default function SuggestionItem(props) {
- return (
-
-
-
-
-
-
- {props.response.response}
-
-
-
-
-
-
-
- {props.response.prompt}
-
-
-
- );
-}
-
-SuggestionItem.propTypes = { response: PropTypes.any };
diff --git a/vite-client/src/components/SuggestionsContainer.jsx b/vite-client/src/components/SuggestionsContainer.jsx
deleted file mode 100644
index 17dd38e..0000000
--- a/vite-client/src/components/SuggestionsContainer.jsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import React, { useMemo } from "react";
-import { useAutoAnimate } from "@formkit/auto-animate/react";
-import { Grid2, Typography } from "@mui/material";
-import _ from "lodash";
-import { LoadingBarsIcon } from "./LoadingBars.jsx";
-import SuggestionItem from "./SuggestionItem.jsx";
-import * as PropTypes from "prop-types";
-import { useSuggestions } from "../providers/SuggestionsProvider.jsx";
-
-export function SuggestionsContainer(props) {
- const [parent] = useAutoAnimate();
- const { suggestions } = useSuggestions();
- const nonEmptySuggestions = useMemo(
- () => suggestions?.filter((r) => !_.isEmpty(r.response)),
- [suggestions],
- );
-
- return (
-
- {(suggestions?.[0]?.prompt !== props.delayedTranscript ||
- _.isEmpty(suggestions?.[0]?.response)) &&
- !_.isEmpty(props.delayedTranscript) && (
-
-
-
- {props.delayedTranscript}
-
-
-
-
-
-
- )}
-
- {nonEmptySuggestions?.map((response) => (
-
- ))}
-
- );
-}
-
-SuggestionsContainer.propTypes = {
- delayedTranscript: PropTypes.string,
-};
diff --git a/vite-client/src/hooks/useSpeechRecognition.js b/vite-client/src/hooks/useSpeechRecognition.js
deleted file mode 100644
index 2fb89cf..0000000
--- a/vite-client/src/hooks/useSpeechRecognition.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import { useEffect, useRef, useState } from "react";
-
-const useSpeechRecognition = () => {
- const [transcript, setTranscript] = useState("");
- const [listening, setListening] = useState(false);
- const recognitionRef = useRef(null);
-
- useEffect(() => {
- const SpeechRecognition =
- window.SpeechRecognition || window.webkitSpeechRecognition;
- const recognition = new SpeechRecognition();
- recognitionRef.current = recognition;
-
- recognition.continuous = true;
- recognition.interimResults = true;
- recognition.lang = "en-US";
-
- recognition.onresult = (event) => {
- const currentTranscript = Array.from(event.results)
- .map((result) => result[0])
- .map((result) => result.transcript)
- .join("");
- setTranscript(currentTranscript);
- };
-
- recognition.onerror = (event) => {
- if (event.error === "no-speech") {
- console.log("No speech detected. Restarting recognition...");
- restartListening();
- return;
- }
- if (event.error === "aborted") {
- return;
- }
- console.error("Speech recognition error:", event.error);
- };
-
- recognition.onend = () => {
- if (listening) {
- recognition.start();
- }
- };
-
- return () => {
- recognition.stop();
- };
- }, []);
-
- const startListening = () => {
- setTranscript("");
- setListening(true);
- if (recognitionRef.current) {
- recognitionRef.current.start();
- }
- };
-
- const stopListening = () => {
- setListening(false);
- if (recognitionRef.current) {
- recognitionRef.current.onend = null;
- recognitionRef.current.stop();
- }
- };
- const clearTranscript = () => {
- setTranscript("");
- recognitionRef.current.abort();
- restartListening();
- };
-
- const restartListening = () => {
- recognitionRef.current.stop();
- setTimeout(() => {
- recognitionRef.current.start();
- }, 500);
- };
-
- return {
- transcript,
- listening,
- startListening,
- stopListening,
- restartListening,
- clearTranscript,
- };
-};
-
-export default useSpeechRecognition;
diff --git a/vite-client/src/index.css b/vite-client/src/index.css
deleted file mode 100644
index f9242df..0000000
--- a/vite-client/src/index.css
+++ /dev/null
@@ -1,65 +0,0 @@
-:root {
- font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
- line-height: 1.5;
- font-weight: 400;
-
- color-scheme: light dark;
- color: rgba(255, 255, 255, 0.87);
- /*background-color: #012020*/
-;
-
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
-}
-a:hover {
- color: #535bf2;
-}
-
-body {
- min-height: 100vh;
-}
-
-h1 {
- font-size: 3.2em;
- line-height: 1.1;
-}
-
-button {
- border-radius: 8px;
- border: 1px solid transparent;
- padding: 0.6em 1.2em;
- font-size: 1em;
- font-weight: 500;
- font-family: inherit;
- background-color: #1a1a1a;
- cursor: pointer;
- transition: border-color 0.25s;
-}
-button:hover {
- border-color: #646cff;
-}
-button:focus,
-button:focus-visible {
- outline: 4px auto -webkit-focus-ring-color;
-}
-
-@media (prefers-color-scheme: light) {
- :root {
- color: #213547;
- background-color: #ffffff;
- }
- a:hover {
- color: #747bff;
- }
- button {
- background-color: #f9f9f9;
- }
-}
diff --git a/vite-client/src/main.jsx b/vite-client/src/main.jsx
deleted file mode 100644
index b9a1a6d..0000000
--- a/vite-client/src/main.jsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
-import './index.css'
-import App from './App.jsx'
-
-createRoot(document.getElementById('root')).render(
-
-
- ,
-)
diff --git a/vite-client/src/pages/SuggestionsPage.jsx b/vite-client/src/pages/SuggestionsPage.jsx
deleted file mode 100644
index 0447664..0000000
--- a/vite-client/src/pages/SuggestionsPage.jsx
+++ /dev/null
@@ -1,101 +0,0 @@
-import React, { useCallback, useEffect, useState } from "react";
-import { Container, Grid2, Typography } from "@mui/material";
-import useSpeechRecognition from "../hooks/useSpeechRecognition.js";
-import _ from "lodash";
-import SuggestionControlContainer from "../components/SuggestionControlContainer.jsx";
-import { SuggestionsContainer } from "../components/SuggestionsContainer.jsx";
-import { useSuggestions } from "../providers/SuggestionsProvider.jsx";
-
-function SuggestionsPage() {
- const { nonEmptySuggestions, getNewSuggestion } = useSuggestions();
- const [isRecording, setIsRecording] = useState(false);
- const [showContent, setShowContent] = useState(false);
- const [delayedTranscript, setDelayedTranscript] = useState("");
-
- const {
- transcript,
- listening,
- startListening,
- stopListening,
- clearTranscript,
- } = useSpeechRecognition();
-
- useEffect(() => {
- setTimeout(() => {
- setShowContent(isRecording);
- }, 450);
- return () => {};
- }, [isRecording]);
-
- useEffect(() => {
- if (isRecording !== listening) {
- setIsRecording(listening);
- }
- }, [listening]);
-
- useEffect(() => {
- if (nonEmptySuggestions?.[0]?.prompt === transcript) {
- clearTranscript();
- setDelayedTranscript("");
- }
- }, [nonEmptySuggestions]);
-
- const debouncedSendTranscript = useCallback(
- _.debounce((transcript) => getNewSuggestion(transcript), 2000, {
- trailing: true,
- }),
- [],
- );
-
- const debouncedStartListening = useCallback(
- _.debounce(startListening, 500),
- [],
- );
-
- const debouncedStopListening = useCallback(
- _.debounce(stopListening, 500),
- [],
- );
-
- useEffect(() => {
- if (!_.isEmpty(transcript)) {
- setDelayedTranscript(transcript);
- debouncedSendTranscript(transcript);
- }
- }, [transcript]);
-
- // useEffect(() => {
- // // Auto-scroll when new responses arrive
- // // if (responseBoxRef.current) {
- // // responseBoxRef.current.scrollTop = responseBoxRef.current.scrollHeight;
- // // }
- // // console.log({ current_responses: responses });
- // }, [responses]);
-
- const handleListen = () => {
- const newRecordingValue = !listening;
- if (!newRecordingValue) {
- debouncedStopListening();
- setIsRecording(newRecordingValue);
- } else {
- debouncedStartListening();
- setIsRecording(newRecordingValue);
- }
- };
-
- return (
-
-
-
-
- Scrying.AI
-
-
-
-
-
-
- );
-}
-
-export default SuggestionsPage;
diff --git a/vite-client/src/providers/SocketProvider.jsx b/vite-client/src/providers/SocketProvider.jsx
deleted file mode 100644
index 4d95e93..0000000
--- a/vite-client/src/providers/SocketProvider.jsx
+++ /dev/null
@@ -1,75 +0,0 @@
-import {
- createContext,
- useCallback,
- useContext,
- useEffect,
- useRef,
- useState,
-} from "react";
-import { io } from "socket.io-client";
-
-const SOCKET_SERVER_URL = "http://localhost:5000";
-
-const SocketContext = createContext(null);
-
-export const SocketProvider = ({ children }) => {
- const socketRef = useRef(null);
- const [isConnected, setIsConnected] = useState(false);
-
- useEffect(() => {
- socketRef.current = io(SOCKET_SERVER_URL);
-
- socketRef.current.on("connect", () => {
- setIsConnected(true);
- console.log("Connected to socket:", socketRef.current.id);
- });
-
- socketRef.current.on("disconnect", () => {
- setIsConnected(false);
- console.log("Disconnected from socket");
- });
-
- return () => {
- socketRef.current.disconnect();
- };
- }, []);
-
- const emitEvent = useCallback(
- (event, data) => {
- if (socketRef.current) {
- socketRef.current.emit(event, data);
- }
- },
- [socketRef.current],
- );
-
- const listenEvent = useCallback(
- (event, callback) => {
- if (socketRef.current) {
- socketRef.current.on(event, callback);
- }
- },
- [socketRef.current],
- );
-
- const removeEventListener = useCallback(
- (event) => {
- if (socketRef.current) {
- socketRef.current.off(event);
- }
- },
- [socketRef.current],
- );
-
- return (
-
- {children}
-
- );
-};
-
-export const useSocket = () => {
- return useContext(SocketContext);
-};
diff --git a/vite-client/src/providers/SuggestionsProvider.jsx b/vite-client/src/providers/SuggestionsProvider.jsx
deleted file mode 100644
index 8904c3c..0000000
--- a/vite-client/src/providers/SuggestionsProvider.jsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import {
- createContext,
- useContext,
- useEffect,
- useMemo,
- useRef,
- useState,
-} from "react";
-import { v4 as uuidv4 } from "uuid";
-import { useSocket } from "./SocketProvider.jsx";
-import _ from "lodash";
-
-const SuggestionsContext = createContext(null);
-
-export const SuggestionsProvider = ({ children }) => {
- const { isConnected, emitEvent, listenEvent, removeEventListener } =
- useSocket();
- const [suggestions, setSuggestions] = useState([]);
- const latencyStartTimes = useRef({}); // Store start times by request ID
-
- const nonEmptySuggestions = useMemo(
- () => suggestions?.filter((r) => !_.isEmpty(r.response)),
- [suggestions],
- );
-
- useEffect(() => {
- if (listenEvent) {
- listenEvent("ai_response", handleSuggestionMessage);
- }
-
- return () => {
- removeEventListener("ai_response");
- };
- }, [listenEvent, removeEventListener]);
-
- const prepareTranscriptForPrompt = (transcript) => {
- if (transcript.trim() !== "") {
- const id = uuidv4(); // Unique ID for each request
- latencyStartTimes.current[id] = Date.now(); // Start time per request
- setSuggestions((prevResponses) => [
- { id, prompt: transcript, response: "", latency: null },
- ...prevResponses,
- ]);
- return { id, prompt: transcript, mock: true };
- }
- };
-
- const getNewSuggestion = (transcript) => {
- const promptRequestData = prepareTranscriptForPrompt(transcript);
- console.log("SEND PROMPT: ", promptRequestData);
- emitEvent("send_prompt", promptRequestData);
- };
-
- const handleSuggestionMessage = ({ id, response }) => {
- console.log("RECEIVED MESSAGE: ", response);
- const endTime = Date.now();
- const startTime = latencyStartTimes.current[id] || endTime;
- const latency = ((endTime - startTime) / 1000).toFixed(2);
-
- setSuggestions((prevResponses) =>
- prevResponses.map((entry) =>
- entry.id === id ? { ...entry, response, latency } : entry,
- ),
- );
- };
-
- return (
-
- {children}
-
- );
-};
-
-export const useSuggestions = () => {
- return useContext(SuggestionsContext);
-};
diff --git a/vite-client/src/theme.js b/vite-client/src/theme.js
deleted file mode 100644
index 87d7093..0000000
--- a/vite-client/src/theme.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { createTheme } from "@mui/material";
-
-export const theme = createTheme({
- palette: {
- mode: "dark",
- primary: {
- light: "#abeded",
- main: "#57dbdb",
- dark: "#24a8a8",
- contrastText: "#041515",
- },
- background: {
- default: "#0d2020",
- paper: "rgb(30, 30, 30)",
- },
- },
- typography: {
- caption: {
- fontStyle: "italic",
- fontSize: "1rem",
- color: "#9e9e9e",
- },
- },
- components: {
- MuiCssBaseline: {
- styleOverrides: {
- body: {
- backgroundColor: (theme) => theme.palette.background.default,
- backgroundImage: `linear-gradient(135deg, #112a2a 10%, #091717 75%, #060f0f)`,
- },
- },
- },
- },
-});
diff --git a/vite-client/vite.config.js b/vite-client/vite.config.js
deleted file mode 100644
index 8497578..0000000
--- a/vite-client/vite.config.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { defineConfig } from 'vite';
-import react from '@vitejs/plugin-react';
-
-export default defineConfig({
- plugins: [react()],
- server: {
- host: true, // 👈 Allows network access
- port: 5173,
- allowedHosts: ['d08d-74-111-17-171.ngrok-free.app'], // 👈 Add your ngrok domain here
- },
-});