Compare commits

..

No commits in common. "237909c164bce186a70582a21957b952ec353d39" and "35151b2c539cef498d03d7dd292c183d6f0ebcf7" have entirely different histories.

34 changed files with 567 additions and 682 deletions

View file

@ -1,19 +1,16 @@
// getLocalStorageData.ts
// Function to retrieve all items from localStorage
export const getAllLocalStorageItems = (): Record<string, string | null> => {
const allData: Record<string, string | null> = {}; // Object to hold key-value pairs from localStorage
// Check if localStorage is available
const allData: Record<string, string | null> = {};
if (typeof localStorage !== 'undefined') {
// Iterate through all localStorage keys
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i); // Get the key at the current index
if (key) {
const value = localStorage.getItem(key); // Retrieve the value associated with the key
allData[key] = value; // Store the key-value pair in the allData object
}
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key) {
const value = localStorage.getItem(key);
allData[key] = value;
}
}
}
return allData; // Return the object containing all localStorage items
};
return allData;
};

View file

@ -9,7 +9,7 @@ import { getWeather } from "./weather";
import { changeHistory, getHistory } from "./database";
const InputOutputBackend: React.FC = () => {
//#region variables
// # variables
type Message = {
role: string
content: string
@ -37,7 +37,7 @@ const InputOutputBackend: React.FC = () => {
}
console.log(setSelectedIndex)
//#region useEffect
useEffect(() => {
setMessages(chatHistory.chats[chatHistory.selectedIndex].messages)
}, [chatHistory.selectedIndex])
@ -86,7 +86,6 @@ const InputOutputBackend: React.FC = () => {
}
}, [chatHistory])
//#region functions
const getWeatherHere = async () => {
setWeatherData(await getWeather({ "unit_type": preferredMeasurement, "city": localStorage.getItem("weatherInfo") || "New York" }))
console.log("Got the Data!")
@ -105,7 +104,7 @@ const InputOutputBackend: React.FC = () => {
}
setChatHistoryTriggered(true)
}
//#region system-prompt
useEffect(() => {
console.log("creating system prompt")
console.log(weatherData)
@ -134,7 +133,7 @@ const InputOutputBackend: React.FC = () => {
console.log(messages)
}, [systemMessage])
//#region more variables and functions
const conversationRef = useRef<HTMLDivElement>(null)
const [copyClicked, setCopyClicked] = useState(false)
const [accessToken, setAccessToken] = useState("")
@ -145,7 +144,7 @@ const InputOutputBackend: React.FC = () => {
const [isRecording, setIsRecording] = useState(false)
const mediaRecorderRef = useRef<MediaRecorder | null>(null)
const audioChunks = useRef<Blob[]>([])
//#region chat functions
useEffect(() => {
getNewToken()
@ -267,7 +266,7 @@ const InputOutputBackend: React.FC = () => {
}
}
}
//#region speech recognition
const startRecording = async (): Promise<string> => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecorder = new MediaRecorder(stream);
@ -310,7 +309,7 @@ const InputOutputBackend: React.FC = () => {
stopRecording();
}
};
//#region chat buttons
const handleStopClick = () => {
endGetWorker()
getNewToken()
@ -357,7 +356,7 @@ const InputOutputBackend: React.FC = () => {
setCopyClicked(false)
}
//#region The "html" return
return (
<>
<ConversationFrontend

View file

@ -1,40 +1,55 @@
import axios from "axios";
// Construct the base API URL based on the environment
const apiURL = new URL("http://localhost:5000/interstellar_ai/db");
/*
This is the guide on how to user this function:
data should be the json containing everything relevant, the json can contain the following keys:
action -> contains the action you want to do, there are: create_account, change_password, get_data, change_data, check_credentials, delete_account
username -> contains the current username, required for create_account, but can be omitted in favor of email in other requests. Preffered over email authentication.
email -> contains the current email, required for create_account, but just like the username, it can be omitted, in favor of the other, sending both is possible too.
password -> contains the password, required for all requests.
new_password -> in the case you are changing your password, you will need to use this in addition to password, to specify the new password.
data -> data contains all the data you want to store, you have to always give the entire data, because the data you give here overwrites the data in the database,
so if you only give the chat history for example, all settings will be deleted, and if you only give settings, all chat histories will get deleted.
if all went well, you will get the status 200 in response.data.status
to check if the request was accepted or declined, check response.data.response, it will be either true or false depending on if it worked, or not.
*/
const apiURL = new URL("http://localhost:5000/interstellar_ai/db")
if (typeof window !== 'undefined') {
apiURL.hostname = window.location.hostname; // Set hostname for browsers
apiURL.hostname = window.location.hostname;
} else {
apiURL.hostname = "localhost"; // Default to localhost for non-browser environments
apiURL.hostname = "localhost"
}
// Function to send data to the database and return a success status
export const sendToDatabase = async (data: object): Promise<boolean> => {
try {
const response = await axios.post(apiURL.href, data);
const status = response.data.status;
const success = response.data.response;
postMessage({ status, success }); // Send status back to the main thread
return success; // Return success status
postMessage({ status, success });
return success;
} catch (error) {
postMessage({ status: 500, success: false }); // Handle errors
console.log(error);
return false; // Return false on error
postMessage({ status: 500, success: false });
console.log(error)
return false;
}
};
// Function to send data and get a string response
export const sendToDatabaseAndGetString = async (data: object): Promise<string> => {
try {
const response = await axios.post(apiURL.href, data);
const status = response.data.status;
const success = response.data.response;
postMessage({ status, success });
return success; // Return response string
return success;
} catch (error) {
postMessage({ status: 500, success: false });
console.log(error);
return "false"; // Return "false" on error
console.log(error)
return "false";
}
};
@ -46,7 +61,7 @@ export const createAccount = async (username: string, email: string, password: s
email: email,
password: password,
};
return await sendToDatabase(data); // Send account creation request
return await sendToDatabase(data);
};
export const changePassword = async (usernameOrEmail: string, password: string, newPassword: string) => {
@ -57,7 +72,7 @@ export const changePassword = async (usernameOrEmail: string, password: string,
password,
new_password: newPassword,
};
return await sendToDatabase(data); // Send password change request
return await sendToDatabase(data);
};
export const getSettings = async (usernameOrEmail: string, password: string) => {
@ -67,7 +82,7 @@ export const getSettings = async (usernameOrEmail: string, password: string) =>
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password,
};
return await sendToDatabaseAndGetString(data); // Get user settings
return await sendToDatabaseAndGetString(data);
};
export const changeSettings = async (usernameOrEmail: string, password: string, newData: object) => {
@ -78,7 +93,7 @@ export const changeSettings = async (usernameOrEmail: string, password: string,
password,
data: newData,
};
return await sendToDatabase(data); // Send settings change request
return await sendToDatabase(data);
};
export const getHistory = async (usernameOrEmail: string, password: string) => {
@ -88,7 +103,7 @@ export const getHistory = async (usernameOrEmail: string, password: string) => {
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password,
};
return await sendToDatabaseAndGetString(data); // Get user history
return await sendToDatabaseAndGetString(data);
};
export const changeHistory = async (usernameOrEmail: string, password: string, newData: object) => {
@ -99,7 +114,7 @@ export const changeHistory = async (usernameOrEmail: string, password: string, n
password,
data: newData,
};
return await sendToDatabase(data); // Send history change request
return await sendToDatabase(data);
};
export const getEmail = async (usernameOrEmail: string, password: string): Promise<string> => {
@ -109,7 +124,7 @@ export const getEmail = async (usernameOrEmail: string, password: string): Promi
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password,
};
return await sendToDatabaseAndGetString(data); // Get user email
return await sendToDatabaseAndGetString(data);
};
export const getName = async (usernameOrEmail: string, password: string): Promise<string> => {
@ -119,9 +134,10 @@ export const getName = async (usernameOrEmail: string, password: string): Promis
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password,
};
return await sendToDatabaseAndGetString(data); // Get user name
return await sendToDatabaseAndGetString(data);
};
export const checkCredentials = async (usernameOrEmail: string, password: string) => {
const data = {
action: "check_credentials",
@ -129,16 +145,15 @@ export const checkCredentials = async (usernameOrEmail: string, password: string
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password,
};
const sendBack = await sendToDatabase(data); // Check user credentials
const sendBack = await sendToDatabase(data);
if (sendBack) {
if (typeof localStorage !== 'undefined') {
// Store user data in localStorage if credentials are valid
localStorage.setItem("accountEmail", await getEmail(usernameOrEmail, password));
localStorage.setItem("accountName", await getName(usernameOrEmail, password));
localStorage.setItem("accountPassword", password);
localStorage.setItem("accountEmail", await getEmail(usernameOrEmail, password))
localStorage.setItem("accountName", await getName(usernameOrEmail, password))
localStorage.setItem("accountPassword", password)
}
}
return sendBack; // Return success status
return sendBack
};
export const deleteAccount = async (usernameOrEmail: string, password: string) => {
@ -148,5 +163,5 @@ export const deleteAccount = async (usernameOrEmail: string, password: string) =
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password,
};
return await sendToDatabase(data); // Send account deletion request
return await sendToDatabase(data);
};

View file

@ -1,32 +1,37 @@
import axios from "axios";
let windownameGlobal = ""; // Global variable to hold the window name
let accesstoken = ""; // Variable to store the access token
let windownameGlobal = ""
let accesstoken = ""
onmessage = (event) => {
const { action, access_token, windowname } = event.data;
accesstoken = access_token;
windownameGlobal = windowname;
const { action, access_token, windowname } = event.data
accesstoken = access_token
windownameGlobal = windowname
if (action === "start") {
fetchData(); // Start fetching data on 'start' action
fetchData()
} else if (action === "terminate") {
}
}
const fetchData = () => {
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/ai_get?access_token=" + accesstoken);
apiURL.hostname = windownameGlobal; // Set the hostname
console.log(apiURL.href); // Log the constructed URL
const fetchData = () => {
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/ai_get?access_token=" + accesstoken)
apiURL.hostname = windownameGlobal;
console.log(apiURL.href)
axios.get(apiURL.href)
.then(response => {
postMessage(response.data); // Send data back on success
setTimeout(fetchData, 100); // Schedule next fetch
const data = response.data
postMessage(data)
setTimeout(fetchData, 100)
})
.catch(error => {
console.log('Error fetching data:', error);
postMessage({ error: "failed fetching data" }); // Send error message
setTimeout(() => fetchData(), 1000); // Retry after 1 second
});
}
postMessage({ error: "failed fetching data" })
setTimeout(() => fetchData(), 1000)
})
}

View file

@ -1,32 +1,31 @@
import axios from "axios";
// Event listener for incoming messages
onmessage = (e) => {
const { messages, ai_model, model_type, access_token, api_key, windowname } = e.data;
const { messages, ai_model, model_type, access_token, api_key, windowname } = e.data
// Construct the message object to send to the API
const Message = {
messages: messages,
ai_model: ai_model,
model_type: model_type,
access_token: access_token,
api_key: api_key
};
}
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/ai_send");
console.log(windowname); // Log the window name
apiURL.hostname = windowname; // Set the hostname for the API request
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/ai_send")
console.log(windowname)
apiURL.hostname = windowname;
console.log(apiURL.href); // Log the constructed API URL
console.log(apiURL.href)
// Make a POST request to the API with the message object
axios.post(apiURL.href, Message)
.then(response => {
const status = response.data.status;
postMessage({ status }); // Send the response status back
const status = response.data.status
postMessage({ status })
})
.catch(error => {
console.log("Error calling API:", error);
postMessage({ status: 500 }); // Send error status if API call fails
});
}
console.log("Error calling API:", error)
postMessage({ status: 500 })
})
}

View file

@ -1,26 +1,24 @@
import axios from "axios";
export const sendToVoiceRecognition = (audio_data: Blob): Promise<string> => {
// Create a new FormData instance to send the audio file
const formdata = new FormData();
formdata.append("audio", audio_data); // Append the audio data to the FormData
// Set the API URL dynamically based on the environment
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/voice_recognition");
const formdata = new FormData()
formdata.append("audio", audio_data)
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/voice_recognition")
if (typeof window !== 'undefined') {
apiURL.hostname = window.location.hostname; // Use the current hostname in the browser
apiURL.hostname = window.location.hostname;
} else {
apiURL.hostname = "localhost"; // Fallback for server-side
apiURL.hostname = "localhost"
}
// Send the audio data to the API using POST request
return axios.post(apiURL.href, formdata)
.then((response) => {
return response.data.response; // Return the response from the API
return response.data.response
})
.catch(error => {
console.log("Error calling API:", error); // Log any error that occurs
postMessage({ status: 500 }); // Indicate an error status to the worker
return "Error"; // Return a fallback error message
});
};
console.log("Error calling API:", error)
postMessage({ status: 500 })
return "Error"
})
}

View file

@ -1,29 +1,23 @@
import axios from "axios";
// Initialize the API URL for the weather service
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/weather");
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/weather")
if (typeof window !== 'undefined') {
apiURL.hostname = window.location.hostname; // Use current hostname in the browser
apiURL.hostname = window.location.hostname;
} else {
apiURL.hostname = "localhost"; // Fallback for server-side
apiURL.hostname = "localhost"
}
// Function to get weather data
export const getWeather = async (data: object): Promise<string> => {
try {
// Make a POST request to the weather API with the provided data
const response = await axios.post(apiURL.href, data);
const status = response.data.status; // Extract the status from the response
const success = response.data.response; // Extract the actual weather data from the response
// Send the status and success response back to the worker
const status = response.data.status;
const success = response.data.response;
postMessage({ status, success });
console.log(JSON.stringify(success)); // Log the successful response for debugging
return JSON.stringify(success); // Return the weather data as a JSON string
console.log(JSON.stringify(success))
return JSON.stringify(success);
} catch (error) {
// Handle any errors that occur during the request
postMessage({ status: 500, success: false });
console.log(error); // Log the error for debugging
return ""; // Return an empty string in case of an error
console.log(error)
return "";
}
};
};

View file

@ -5,10 +5,9 @@ import InputOutputBackend from '../backend/InputOutputHandler';
const AI: React.FC = () => {
return (
<div className="ai-container">
{/* Render the InputOutputBackend component for AI input/output handling */}
<InputOutputBackend />
</div>
);
};
export default AI;
export default AI;

View file

@ -1,45 +1,24 @@
import React from 'react';
// Main Credits Component
const Credits: React.FC = () => (
<div className="credits-container">
<section id="credits" className="credits-section">
<h1 className="title">Credits</h1>
<h2 className="subtitle">Icons</h2>
<p className="paragraph">This project utilizes the following icon resources:</p>
<CreditLink href="https://fontawesome.com/v4/license/" label="FontAwesome" />
<CreditLink href="https://fontawesome.com/v4/license/" label="fontawesome" />
<h2 className="subtitle">Fonts</h2>
<p className="paragraph">The fonts used in this project are provided by:</p>
<CreditLink href="https://github.com/itfoundry/Poppins" label="Poppins" />
<CreditLink
href="https://openfontlicense.org"
label="Inconsolata, Merriweather, Noto Sans, Noto Serif, Playfair Display, Bangers, Caveat, Frederika the Great, Sofadi One, Zilla Slab Highlight"
/>
<CreditLink
href="http://www.apache.org/licenses/LICENSE-2.0"
label="Roboto, Rock Salt"
/>
<CreditLink href="https://openfontlicense.org" label="Inconsolata, Merriweather, Noto Sans, Noto Serif, Playfair Display, Bangers, Caveat, Frederika the Great, Sofadi One, Zilla Slab Highlight" />
<CreditLink href="http://www.apache.org/licenses/LICENSE-2.0" label="Roboto, Rock Salt" />
<CreditLink href="https://ubuntu.com/legal/font-licence" label="Ubuntu" />
</section>
</div>
);
// CreditLink Component for rendering individual credit links
const CreditLink: React.FC<{ href: string; label: string }> = ({ href, label }) => (
<a
href={href}
className="credit-btn"
target="_blank"
rel="noopener noreferrer"
aria-label={`Visit ${label} license page`} // Improve accessibility
>
{label}
</a>
const CreditLink = ({ href, label }: { href: string; label: string }) => (
<a href={href} className="credit-btn" target="_blank" rel="noopener noreferrer">{label}</a>
);
export default Credits;
// also thank you Leart and Tristan without you two we would not have come this far
// and a special thanks and why are you so annoying to Eslint

View file

@ -1,7 +1,6 @@
import React from 'react';
// Documentation Component
const Documentation: React.FC = () => {
const Documentation = () => {
return (
<section id="documentation" className="documentation-section">
<div className='docDiv'>

View file

@ -1,62 +1,107 @@
import React from 'react';
// FAQ Component
const FAQ: React.FC = () => {
return (
<section id="faq"> {/* Main section for FAQs */}
<h2>Frequently Asked Questions</h2> {/* Title for the FAQ section */}
<section id="faq">
<h2>Frequently Asked Questions</h2>
<div className="faq-item">
<h3>Why doesn't my selection in the category dropdown menu apply?</h3>
<p>Currently, the dropdown menu for selecting AI models does not retain your choice after a website refresh.</p>
<h3>What is this AI assistant for?</h3>
<p>This AI assistant helps you with various tasks such as answering questions, generating text, and even helping with code or writing tasks.</p>
</div>
<div className="faq-item">
<h3>Why is the AI suddenly talking about the weather when I didn't select that option?</h3>
<p>The AI is programmed to provide weather information even if you haven't specifically selected the weather option.</p>
<h3>How does the AI assistant work?</h3>
<p>The assistant uses machine learning algorithms to understand your input and provide contextually relevant answers or generate content based on the task you&apos;ve described.</p>
</div>
<div className="faq-item">
<h3>Why isn't the online API working?</h3>
<p>At the moment, the online APIs for Google and La Plateforme are not operational. However, the OpenAI and Anthropic APIs may still function.</p>
<h3>Can I trust the answers given by the AI assistant?</h3>
<p>While the AI strives to give accurate and helpful answers, it is important to verify critical information, especially for complex or sensitive queries.</p>
</div>
<div className="faq-item">
<h3>Why is the AI discussing unrelated topics?</h3>
<p>Try disabling the AI system prompt settings, as the AI sometimes tends to focus on those topics excessively.</p>
<h3>What kind of questions can I ask?</h3>
<p>You can ask a wide range of questions from simple factual queries to more complex requests like generating creative writing or code snippets.</p>
</div>
<div className="faq-item">
<h3>Why isn't the AI responding in the format I specified in the settings?</h3>
<p>Please check if the system prompt settings are enabled. If the issue persists, it may be because the AI is unable to fully adhere to the command.</p>
<h3>Is my data secure when using the AI assistant?</h3>
<p>We take privacy seriously. Your data is handled according to our privacy policy, ensuring that any personal information shared is securely processed and not misused.</p>
</div>
<div className="faq-item">
<h3>Does this AI have the ability to know my location or search the web?</h3>
<p>No, this AI does not possess any capabilities to access your location or browse the web.</p>
<h3>How can I provide feedback about the AI assistant?</h3>
<p>Feedback can be provided through our feedback form, available on our website. We appreciate your input and use it to improve the AI assistant&apos;s performance.</p>
</div>
<div className="faq-item">
<h3>Does the AI really work offline?</h3>
<p>Yes! Once you download the necessary models, it can operate fully offline, with the exception of the weather API.</p>
<h3>Can I customize the AI assistant&apos;s responses?</h3>
<p>Customization options are limited in the current version, but we are working on features that will allow users to tailor responses to better suit their needs.</p>
</div>
<div className="faq-item">
<h3>Are my messages encrypted?</h3>
<p>Unfortunately, not at this time. We recommend keeping your messages as anonymous as possible.</p>
<h3>How frequently is the AI assistant updated?</h3>
<p>The AI assistant is updated regularly to improve its functionality and incorporate new features. Stay tuned to our update logs for information on the latest improvements.</p>
</div>
<div className="faq-item">
<h3>Where is my data saved?</h3>
<p>All data, including accounts, settings, and chats, is stored locally on your computer.</p>
<h3>What should I do if the AI assistant is not working properly?</h3>
<p>If you encounter any issues with the AI assistant, please contact our support team for assistance. Provide details about the problem to help us resolve it quickly.</p>
</div>
<div className="faq-item">
<h3>Is this a virus?</h3>
<p>No, this is not a virus. The warning appears because the application is not officially signed.</p>
<h3>Will the AI assistant be available in multiple languages?</h3>
<p>Yes, the AI assistant is designed to support multiple languages. You can specify your language preference in the settings to receive responses in your chosen language.</p>
</div>
<div className="faq-item">
<h3>How can I integrate the AI assistant into my own application?</h3>
<p>Integration guidelines are available in our developer documentation. Follow the instructions to incorporate the AI assistant into your application via our API.</p>
</div>
<div className="faq-item">
<h3>Is there a mobile version of the AI assistant?</h3>
<p>Currently, the AI assistant is optimized for desktop use. We are working on a mobile version to provide a seamless experience on smartphones and tablets.</p>
</div>
<div className="faq-item">
<h3>Can the AI assistant handle multiple simultaneous conversations?</h3>
<p>Yes, the AI assistant is capable of managing multiple conversations at once, ensuring that each interaction is handled efficiently.</p>
</div>
<div className="faq-item">
<h3>What are the system requirements to use the AI assistant?</h3>
<p>The AI assistant can be accessed through most modern web browsers. Ensure your browser is up-to-date for the best experience.</p>
</div>
<div className="faq-item">
<h3>How can I access previous conversations?</h3>
<p>Previous conversations can be accessed through the chat history feature available in the assistant&apos;s interface.</p>
</div>
<div className="faq-item">
<h3>What are the limitations of the current AI assistant?</h3>
<p>The AI assistant may have limitations in understanding highly specialized or nuanced topics. We are continuously working to expand its capabilities.</p>
</div>
<div className="faq-item">
<h3>How do I update my profile or settings?</h3>
<p>Profile and settings updates can be made through the account management section of the application. Ensure you save your changes before exiting.</p>
</div>
<div className="faq-item">
<h3>Can the AI assistant be used offline?</h3>
<p>Currently, the AI assistant requires an internet connection to function. Offline capabilities are being explored for future updates.</p>
</div>
<div className="faq-item">
<h3>Who can I contact for technical support?</h3>
<p>Technical support can be reached through our support contact page on the website. Our team is available to help with any technical issues you may encounter.</p>
</div>
</section>
);
};
export default FAQ; // Exporting the FAQ component
export default FAQ;

View file

@ -1,13 +1,12 @@
import React, { useState, useRef, useEffect } from 'react';
import Login from './Login'; // Importing the Login component
import Login from './Login';
// Define the props for the Header component
interface HeaderProps {
onViewChange: (view: 'AI' | 'FAQ' | 'Documentation' | 'Credits') => void; // Function to change views
showDivs: boolean; // State to show/hide divs
toggleDivs: () => void; // Function to toggle divs
showHistoryModelsToggle: boolean; // State to show/hide history models
showToggle: boolean; // State to show/hide toggle button
onViewChange: (view: 'AI' | 'FAQ' | 'Documentation' | 'Credits') => void;
showDivs: boolean;
toggleDivs: () => void;
showHistoryModelsToggle: boolean;
showToggle: boolean;
}
const Header: React.FC<HeaderProps> = ({
@ -17,53 +16,50 @@ const Header: React.FC<HeaderProps> = ({
showHistoryModelsToggle,
showToggle,
}) => {
// State to manage menu open/closed state
const [menuOpen, setMenuOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement | null>(null); // Ref for dropdown menu
const toggleRef = useRef<HTMLDivElement | null>(null); // Ref for hamburger toggle
const dropdownRef = useRef<HTMLDivElement | null>(null);
const toggleRef = useRef<HTMLDivElement | null>(null);
// Pages to be displayed in the navigation menu
// Pages that will be displayed in the menu
const pages: ('AI' | 'FAQ' | 'Documentation' | 'Credits')[] = ['AI', 'FAQ', 'Documentation', 'Credits'];
// Function to toggle the dropdown menu state
// Toggle menu state
const toggleMenu = () => {
setMenuOpen((prevMenuOpen) => !prevMenuOpen);
};
// Function to handle view change when a menu item is clicked
// Handle button click
const handleViewChange = (page: 'AI' | 'FAQ' | 'Documentation' | 'Credits') => {
onViewChange(page); // Call the onViewChange function with the selected page
setMenuOpen(false); // Close the menu after selection
onViewChange(page);
setMenuOpen(false); // Close the menu when a button is clicked
};
// Effect to handle clicks outside the dropdown to close it
// Effect to handle clicks outside of the dropdown
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
// Check if the click is outside the dropdown and toggle elements
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node) &&
toggleRef.current &&
!toggleRef.current.contains(event.target as Node)
) {
setMenuOpen(false); // Close the menu if the click is outside
setMenuOpen(false);
}
};
document.addEventListener('mousedown', handleClickOutside); // Listen for clicks
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside); // Cleanup listener on unmount
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
return (
<>
<header>
{/* Show the toggle button for divs if conditions are met */}
{showToggle && showHistoryModelsToggle && (
<button onClick={toggleDivs} className="nav-btn show-hide-btn">
{showDivs ? ( // Conditional rendering of icon based on showDivs state
{showDivs ? (
<>
<svg style={{ fill: "var(--text-color)" }} width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c8.4-19.3 10.6-41.4 4.8-63.3c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zM373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5L373 389.9z"/>
@ -78,32 +74,27 @@ const Header: React.FC<HeaderProps> = ({
)}
</button>
)}
{/* Navigation menu */}
<nav ref={dropdownRef} className={`nav-links ${menuOpen ? "active" : ""}`}>
{pages.map(page => ( // Map through pages to create buttons
{pages.map(page => (
<button key={page} onClick={() => handleViewChange(page)} className="nav-btn">
{page}
</button>
))}
</nav>
{/* Hamburger menu toggle */}
<div ref={toggleRef} className={`hamburger ${menuOpen ? "open" : ""}`} onClick={toggleMenu}>
<span></span> {/* Top bar of the hamburger */}
<span></span> {/* Middle bar of the hamburger */}
<span></span> {/* Bottom bar of the hamburger */}
<span></span>
<span></span>
<span></span>
</div>
<div className="header-logo">
{/* Placeholder for AI logo or text */}
{/* AI logo or text */}
</div>
<div className="login-button-container">
<Login /> {/* Include the Login component */}
<Login />
</div>
</header>
</>
);
};
export default Header; // Exporting the Header component
export default Header;

View file

@ -1,114 +1,96 @@
import React, { useState } from 'react';
import { useChatHistory } from '../hooks/useChatHistory'; // Importing the custom hook for chat history
import { useChatHistory } from '../hooks/useChatHistory';
const History: React.FC = () => {
// Destructuring values from the useChatHistory hook
const [chatHistory, setSelectedIndex, setChatHistory] = useChatHistory();
const [isEditing, setIsEditing] = useState(false); // State to manage edit mode
const [inputValue, setInputValue] = useState<string>(''); // State for input field
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null); // State to track hovered chat index
const [chatHistory, setSelectedIndex, setChatHistory] = useChatHistory()
const [isEditing, setIsEditing] = useState(false);
const [inputValue, setInputValue] = useState<string>('');
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
// Function to activate editing mode
const handleEditButtonClick = () => {
setIsEditing(true);
};
// Function to update input value as the user types
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value);
};
// Function to save the new chat
const handleSaveButtonClick = () => {
setIsEditing(false); // Exit edit mode
// Add a new chat entry to the history
chatHistory.chats.push({ name: inputValue, messages: [], timestamp: 5 });
setInputValue(''); // Reset input value
setIsEditing(false);
chatHistory.chats.push({ name: inputValue, messages: [], timestamp: 5 })
setInputValue("")
};
// Function to select a chat from the history
const handleHistoryClick = (index: number) => {
setSelectedIndex(index); // Set the selected index to the clicked chat
console.log("index", index);
};
setSelectedIndex(index)
console.log("index",index);
}
// Function to handle hover over a chat entry
const handleHistoryHover = (index: number) => {
setHoveredIndex(index); // Set hovered index
};
const handleHistoryHover = (index:number) => {
setHoveredIndex(index)
}
// Function to reset hovered index when not hovering
const handleHistoryNotHover = () => {
setHoveredIndex(null); // Reset hovered index
};
setHoveredIndex(null)
}
console.log("chat length",chatHistory.chats.length)
console.log("index",chatHistory.selectedIndex)
// Debugging information for chat history length and selected index
console.log("chat length", chatHistory.chats.length);
console.log("index", chatHistory.selectedIndex);
// Function to delete a chat entry
const handleHistoryDeletion = (index: number) => {
const currentIndex = chatHistory.selectedIndex; // Get the currently selected index
const currentIndex = chatHistory.selectedIndex;
// Create a new copy of the chat history
// Create a new copy of the current chat history
const copyChats = { ...chatHistory };
copyChats.chats = [...chatHistory.chats];
copyChats.chats = [...chatHistory.chats]
// Remove the chat at the specified index
copyChats.chats.splice(index,1)
// Remove the chat at the specified index
copyChats.chats.splice(index, 1);
// Determine new selectedIndex
let newSelectedIndex = currentIndex;
// Determine the new selectedIndex
let newSelectedIndex = currentIndex;
// Adjust selectedIndex based on the deletion
if (index === currentIndex) {
// If the deleted index is currently selected, reset the selected index
newSelectedIndex = copyChats.chats.length > 0 ? (index > 0 ? index - 1 : 0) : -1; // Set to previous or first chat or -1 if no chats left
} else if (index < currentIndex) {
// If the deleted chat is before the current selected index, decrement the selected index
newSelectedIndex = currentIndex - 1;
// Adjust selectedIndex based on the deletion
if (index === currentIndex) {
// If the deleted index is the currently selected one, reset the selected index
newSelectedIndex = copyChats.chats.length > 0 ? (index > 0 ? index - 1 : 0) : -1; // Set to previous or first chat or -1 if no chats left
} else if (index < currentIndex) {
// If the deleted chat is before the current selected index, decrement the selected index
newSelectedIndex = currentIndex - 1;
}
copyChats.selectedIndex = newSelectedIndex
console.log(copyChats)
copyChats.selectedIndex = newSelectedIndex; // Update the selected index
// Debugging information to inspect the modified chat history
console.log(copyChats);
// Set the updated chat history
setChatHistory(copyChats);
};
// Set the updated chat history
setChatHistory(copyChats);
};
return (
<div className="history-background">
<div className="history">
<ul>
{/* Render chat history items */}
{chatHistory.chats.map((chat, index) => (
<li key={index} onMouseOver={() => handleHistoryHover(index)} onMouseOut={handleHistoryNotHover}>
<a
href="#"
onClick={() => handleHistoryClick(index)} // Handle click to select chat
style={{
backgroundColor: chatHistory.selectedIndex === index ? "var(--input-button-color)" : "",
borderRadius: "5px",
width: index === hoveredIndex && chatHistory.chats.length > 1 ? "85%" : "100%"
}}
>
{chat.name} {/* Display chat name */}
{/* Populate with history items */}
{chatHistory.chats.map((chats, index) => (
<li key={index} onMouseOver={()=>handleHistoryHover(index)} onMouseOut={handleHistoryNotHover} >
<a href="#" onClick={() => handleHistoryClick(index)} style={{
backgroundColor: chatHistory.selectedIndex == index ? "var(--input-button-color)" : "",
borderRadius: "5px",
width: index==hoveredIndex && chatHistory.chats.length >1 ? "85%":"100%"
}}>
{chatHistory.chats[index].name}
</a>
<button
id="delete-chat-button"
onClick={() => handleHistoryDeletion(index)} // Handle chat deletion
disabled={!(index === hoveredIndex && chatHistory.chats.length > 1)} // Disable if not hovered
<button id="delete-chat-button"
onClick={()=>handleHistoryDeletion(index)}
disabled={(index == hoveredIndex && chatHistory.chats.length >1) ? false : true}
style={{
width: index === hoveredIndex && chatHistory.chats.length > 1 ? "15%" : "0",
visibility: index === hoveredIndex && chatHistory.chats.length > 1 ? "visible" : "hidden",
marginLeft: index === hoveredIndex && chatHistory.chats.length > 1 ? "0.5em" : 0
}}
>
<svg viewBox="0 0 448 512">
<path d="M135.2 17.7L128 32 32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l384 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0-7.2-14.3C307.4 6.8 296.3 0 284.2 0L163.8 0c-12.1 0-23.2 6.8-28.6 17.7zM416 128L32 128 53.2 467c1.6 25.3 22.6 45 47.9 45l245.8 0c25.3 0 46.3-19.7 47.9-45L416 128z" />
</svg>
width: index == hoveredIndex && chatHistory.chats.length >1 ? "15%" : "0",
visibility: index == hoveredIndex && chatHistory.chats.length >1 ? "visible" : "hidden",
marginLeft: index == hoveredIndex && chatHistory.chats.length >1? "0.5em":0
}}>
<svg viewBox="0 0 448 512"><path d="M135.2 17.7L128 32 32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l384 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0-7.2-14.3C307.4 6.8 296.3 0 284.2 0L163.8 0c-12.1 0-23.2 6.8-28.6 17.7zM416 128L32 128 53.2 467c1.6 25.3 22.6 45 47.9 45l245.8 0c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>
</button>
</li>
))}
@ -118,17 +100,17 @@ const History: React.FC = () => {
<input
type="text"
value={inputValue}
onChange={handleInputChange} // Update input value as user types
onChange={handleInputChange}
placeholder="Enter text"
className="chat-input"
/>
/>
<button onClick={handleSaveButtonClick} className="save-btn">
Save {/* Button to save new chat */}
Save
</button>
</div>
) : (
<button onClick={handleEditButtonClick} className="newChat-btn">
New Chat {/* Button to initiate a new chat */}
New Chat
</button>
)}
</li>
@ -138,4 +120,4 @@ const History: React.FC = () => {
);
}
export default History; // Exporting the History component
export default History;

View file

@ -2,7 +2,6 @@
import React, { useState, useEffect } from 'react';
// Define all models that should be available.
//#region modelist
const modelList = {
'Offline Fast': {
model_type: 'local',
@ -113,7 +112,7 @@ const selectedAIFunction = [
'Language',
'Weather'
]
//#region variables
const ModelSection: React.FC = () => {
// Initialize state with value from localStorage or default to ''
const [selectedModelDropdown, setSelectedModelDropdown] = useState('');
@ -121,7 +120,7 @@ const ModelSection: React.FC = () => {
const [activeSelectedAIFunction, setActiveSelectedAIFunction] = useState('');
const [currentSelectedAIFunction, setCurrentSelectedAIFunction] = useState<string | null>("");
const [isOpenSourceMode, setIsOpenSourceMode] = useState<string|null>("false")
//#region functions
useEffect(() => {
if (typeof localStorage !== 'undefined') {
const defaultValues = {
@ -176,7 +175,7 @@ const ModelSection: React.FC = () => {
modelClicked(model)
}
};
//#region dropdown
// Determine the filtered models based on current radioSelection
const filteredModels = (() => {
let models = [];
@ -242,7 +241,7 @@ const ModelSection: React.FC = () => {
localStorage.setItem("type", modelList[selectedAIFunction]['model_type' as keyof typeof modelList[typeof selectedAIFunction]])
}
}
//#region return "html"
return (
<div className="model-background">
<div className="models">

View file

@ -1,19 +1,17 @@
import React from 'react';
// Define the props for the ButtonSetting component
interface ButtonSettingProps {
label: string; // The label to display on the button
onClick: () => void; // The function to call when the button is clicked
className?: string; // Optional additional classes for styling
}
// Functional component definition
const ButtonSetting: React.FC<ButtonSettingProps> = ({ label, onClick, className }) => {
const ButtonSetting: React.FC<ButtonSettingProps> = ({ label, onClick }) => {
return (
<div className="settings-option"> {/* Container for the button */}
<div className="settings-option">
<button
onClick={onClick} // Call the onClick function when the button is clicked
className={`export-button ${className || ''}`} // Apply any additional classes, default to empty if not provided
className={"export-button"} // Apply any additional classes
>
{label} {/* Display the label on the button */}
</button>

View file

@ -1,28 +1,25 @@
import React from 'react';
// Define the props for the CheckboxSetting component
interface CheckboxSettingProps {
label: string; // The label to display
checked: boolean; // The checked state of the checkbox
setChecked: (value: boolean) => void; // Method to update the state
}
// Functional component definition
const CheckboxSetting: React.FC<CheckboxSettingProps> = ({ label, checked, setChecked }) => {
// Handler to toggle the checkbox state
const handleCheckboxChange = () => {
setChecked(!checked); // Toggle the checked state
setChecked(!checked);
};
return (
<div className="settings-option"> {/* Container for the checkbox setting */}
<div className="settings-option">
<label>
<input
type="checkbox" // Checkbox input type
checked={checked} // Set the checked state based on the prop
onChange={handleCheckboxChange} // Call the handler on change
type="checkbox"
checked={checked}
onChange={handleCheckboxChange}
/>
{label} {/* Display the label next to the checkbox */}
{label}
</label>
</div>
);

View file

@ -1,32 +1,29 @@
import React from 'react';
import React from 'react';
// Define the props for the ColorSetting component
interface ColorSettingProps {
interface ColorSettingProps {
name: string; // The name to display in the <p> tag
value: string; // The current color value
setValue: (newColor: string) => void; // The method to update the state
cssVariable: string; // The CSS variable name to set
}
}
// Functional component definition
const ColorSetting: React.FC<ColorSettingProps> = ({ name, value, setValue, cssVariable }) => {
// Handler to change the color value
const ColorSetting: React.FC<ColorSettingProps> = ({ name, value, setValue, cssVariable }) => {
const handleColorChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newColor = e.target.value; // Get the new color from the input
setValue(newColor); // Update the state with the new color
document.documentElement.style.setProperty(cssVariable, newColor); // Set the CSS variable
const newColor = e.target.value;
setValue(newColor);
document.documentElement.style.setProperty(cssVariable, newColor);
};
return (
<div className="settings-option"> {/* Container for the color setting */}
<p>{name}</p> {/* Display the name */}
<input
type="color" // Input type for color picker
value={value} // Set the input value to the current color
onChange={handleColorChange} // Call the handler on change
/>
<div className="settings-option">
<p>{name}</p>
<input
type="color"
value={value}
onChange={handleColorChange}
/>
</div>
);
};
};
export default ColorSetting;
export default ColorSetting;

View file

@ -1,39 +1,35 @@
import React from 'react';
// Define the structure of each option in the dropdown
interface Option {
value: string; // The actual value to be used
label: string; // The label to display for the option
value: string; // The actual value to be used
label: string; // The label to display for the option
}
// Define the props for the DropdownSetting component
interface DropdownSettingProps {
label: string; // The label to display above the dropdown
value: string; // The currently selected value
setValue: (newValue: string) => void; // Method to update the state with the new value
options: Option[]; // List of options for the dropdown
label: string; // The label to display
value: string; // The current selected value
setValue: (newValue: string) => void; // The method to update the state
options: Option[]; // List of options for the dropdown
}
// Functional component definition
const DropdownSetting: React.FC<DropdownSettingProps> = ({ label, value, setValue, options }) => {
// Handler to change the selected option
const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const newValue = e.target.value; // Get the new selected value
setValue(newValue); // Update the state with the new value
};
const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const newValue = e.target.value;
setValue(newValue);
};
return (
<div className="settings-option"> {/* Container for the dropdown setting */}
<label>{label}</label> {/* Display the label */}
<select value={value} onChange={handleSelectChange}> {/* Dropdown selection */}
{options.map((option) => ( // Map through options to create <option> elements
<option key={option.value} value={option.value}>
{option.label} {/* Display the label for the option */}
</option>
))}
</select>
</div>
);
return (
<div className="settings-option">
<label>{label}</label>
<select value={value} onChange={handleSelectChange}>
{options.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
</div>
);
};
export default DropdownSetting;

View file

@ -2,10 +2,9 @@
import React from 'react';
const ThemeDropdown: React.FC<{
selectedTheme: string; // Currently selected theme
setSelectedTheme: (theme: string) => void; // Function to update the selected theme
selectedTheme: string;
setSelectedTheme: (theme: string) => void;
}> = ({ selectedTheme, setSelectedTheme }) => {
// Define available theme options
const themeOptions = [
{ value: 'IOMARKET', label: 'IOMARKET' },
{ value: 'WHITE', label: 'WHITE' },
@ -15,22 +14,22 @@ const ThemeDropdown: React.FC<{
];
return (
<div className="settings-option"> {/* Container for the dropdown */}
<p>Select Theme</p> {/* Label for the dropdown */}
<div className="settings-option">
<p>Select Theme</p>
<select
value={selectedTheme} // Current selected theme
onChange={(e) => { // Handler for dropdown changes
const theme = e.target.value; // Get the selected value
value={selectedTheme}
onChange={(e) => {
const theme = e.target.value;
if (theme !== 'default' && typeof localStorage !== 'undefined') {
setSelectedTheme(theme); // Update the selected theme state
localStorage.setItem('selectedTheme', theme); // Save the theme to localStorage
setSelectedTheme(theme);
localStorage.setItem('selectedTheme', theme);
}
}}
>
<option value="default">Select your style...</option> {/* Default option */}
{themeOptions.map((option) => ( // Map through theme options to create <option> elements
<option value="default">Select your style...</option>
{themeOptions.map((option) => (
<option key={option.value} value={option.value}>
{option.label} {/* Display the label for the option */}
{option.label}
</option>
))}
</select>

View file

@ -2,29 +2,28 @@
import React from 'react';
interface FontSizeSettingProps {
fontSize: string; // The current font size as a string (e.g., "16px")
fontSize: string; // The current font size
setFontSize: (newSize: string) => void; // Function to update the font size
}
const FontSizeSetting: React.FC<FontSizeSettingProps> = ({ fontSize, setFontSize }) => {
// Handle changes to the font size input
const handleFontSizeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newSize = `${e.target.value}px`; // Create the new font size string
setFontSize(newSize); // Update the font size state
document.documentElement.style.setProperty('--font-size', newSize); // Update the CSS variable
const newSize = `${e.target.value}px`;
setFontSize(newSize);
document.documentElement.style.setProperty('--font-size', newSize);
};
return (
<div className="settings-option"> {/* Container for the font size setting */}
<p>Font Size</p> {/* Label for the setting */}
<div className="settings-option">
<p>Font Size</p>
<input
type="range" // Range input for selecting font size
min="12" // Minimum font size
max="30" // Maximum font size
value={parseInt(fontSize, 10)} // Ensure value is a number for the slider
onChange={handleFontSizeChange} // Update font size on change
type="range"
min="12"
max="30"
value={parseInt(fontSize, 10)} // Ensure value is a number
onChange={handleFontSizeChange}
/>
<span>{fontSize}</span> {/* Display the current font size */}
<span>{fontSize}</span>
</div>
);
};

View file

@ -12,26 +12,25 @@ const OpenSourceModeToggle: React.FC<OpenSourceModeToggleProps> = ({
setOpenSourceMode,
setSelectedOption
}) => {
// Handle toggle change event
const handleToggleChange = () => {
const newValue = !openSourceMode; // Toggle the current state
setOpenSourceMode(newValue); // Update the open source mode state
const newValue = !openSourceMode;
setOpenSourceMode(newValue);
// Update radio selection based on the new openSourceMode value
if (newValue) {
setSelectedOption('FOSS'); // Set to FOSS if enabling open source mode
} else {
setSelectedOption('None'); // Set to a default value when disabling
setSelectedOption('None'); // Or any other default value when disabling
}
};
return (
<div className="settings-option"> {/* Container for the toggle setting */}
<div className="settings-option">
<label>
<input
type="checkbox" // Checkbox for toggling open source mode
checked={openSourceMode} // Check if the mode is currently enabled
onChange={handleToggleChange} // Handle changes to the checkbox
type="checkbox"
checked={openSourceMode}
onChange={handleToggleChange}
/>
Enable Open Source Mode
</label>

View file

@ -14,28 +14,28 @@ const PrivacySettings: React.FC<PrivacySettingsProps> = ({ selectedOption, handl
<div className="settings-option">
<p>Disable Options:</p>
<div className="slider">
{/* Offline Option */}
{/* Offline */}
<div
className={`slider-option ${selectedOption === 'Offline' ? 'active' : ''}`} // Active class based on selection
onClick={() => handleRadioChange('Offline')} // Handle selection change
className={`slider-option ${selectedOption === 'Offline' ? 'active' : ''}`}
onClick={() => handleRadioChange('Offline')} // Allow selection only if not in open-source mode
>
Offline tools{openSourceMode ? ' (FOSS)' : ''} {/* Display FOSS label if applicable */}
Offline tools{openSourceMode ? ' (FOSS)' : ''}
</div>
{/* Online Option */}
{/* Online */}
<div
className={`slider-option ${selectedOption === 'Online' ? 'active' : ''}`} // Active class based on selection
onClick={() => handleRadioChange('Online')} // Handle selection change
className={`slider-option ${selectedOption === 'Online' ? 'active' : ''}`}
onClick={() => handleRadioChange('Online')}
>
Online tools{openSourceMode ? ' (FOSS)' : ''} {/* Display FOSS label if applicable */}
Online tools{openSourceMode ? ' (FOSS)' : ''}
</div>
{/* None Option */}
{/* None */}
<div
className={`slider-option ${selectedOption === 'None' ? 'active' : ''}`} // Active class based on selection
onClick={() => handleRadioChange('None')} // Handle selection change
className={`slider-option ${selectedOption === 'None' ? 'active' : ''}`}
onClick={() => handleRadioChange('None')}
>
None{openSourceMode ? ' (FOSS)' : ''} {/* Display FOSS label if applicable */}
None{openSourceMode ? ' (FOSS)' : ''}
</div>
</div>
<br />

View file

@ -65,7 +65,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
// Measurement setting
const [preferredMeasurement, setPreferredMeasurement] = useState(() => localStorage.getItem('preferredMeasurement') || 'Metric');
//#region Theme settings
// Theme settings
const [backgroundColor, setBackgroundColor] = useState(() => getComputedStyle(document.documentElement).getPropertyValue('--background-color').trim());
const [headerBackground, setHeaderBackground] = useState(() => getComputedStyle(document.documentElement).getPropertyValue('--header-background-color').trim());
const [textColor, setTextColor] = useState(() => getComputedStyle(document.documentElement).getPropertyValue('--text-color').trim());
@ -122,7 +122,6 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
const [google, setGoogle] = useState(localStorage.getItem('google') || "");
const [myBoolean, setMyBoolean] = useState<boolean>(() => getItemFromLocalStorage('myBoolean'));
//#region Json
const settings = {
userPreferences: {
activeSection,
@ -186,7 +185,6 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
},
};
//#region color settings
const colorSettings = [
{ name: "Background Color", value: backgroundColor, setValue: setBackgroundColor, cssVariable: "--background-color" },
{ name: "Header Background Color", value: headerBackground, setValue: setHeaderBackground, cssVariable: "--header-background-color" },
@ -221,7 +219,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ name: "Burger Menu Background Color", value: burgerMenuBackgroundColor, setValue: setBurgerMenuBackgroundColor, cssVariable: "--burger-menu-background-color" },
];
//#region time settings
const timeZoneOptions = [
{ value: 'GMT', label: 'GMT' },
{ value: 'EST', label: 'EST' },
@ -235,7 +233,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ value: 'JST', label: 'JST' },
];
//#region language settings
const languageOptions = [
{ code: 'en', name: 'English' },
{ code: 'es', name: 'Spanish' },
@ -248,7 +246,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ code: 'ru', name: 'Russian' },
{ code: 'ar', name: 'Arabic' },
];
//#region currency settings
const currencyOptions = [
{ code: 'usd', name: 'USD' },
{ code: 'eur', name: 'EUR' },
@ -260,7 +258,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ code: 'cny', name: 'CNY' },
{ code: 'inr', name: 'INR' },
];
//#region date settings
const dateFormatOptions = [
{ value: 'mm/dd/yyyy', label: 'MM/DD/YYYY' },
{ value: 'dd/mm/yyyy', label: 'DD/MM/YYYY' },
@ -278,7 +276,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ value: 'Metric', label: 'Metric' },
{ value: 'Imperial', label: 'Imperial' },
];
//#region text settings
const fontOptions = [
{ value: "'Poppins', sans-serif", label: 'Poppins' },
{ value: "'Inconsolata', monospace", label: 'Inconsolata' },
@ -296,7 +294,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ value: "'Zilla Slab Highlight', serif", label: 'Zilla Slab Highlight' },
];
//#region Function
//#region Start of the code
const handleLogout = () => {
localStorage.clear();
alert('Successfully logged out!');

View file

@ -10,7 +10,6 @@ export function exportSettings(): string {
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key) {
// Exclude sensitive information
if (key !== "accountName" && key !== "accountPassword" && key !== "accountEmail") {
settings[key] = localStorage.getItem(key) || "";
}
@ -40,28 +39,25 @@ export function importSettings(jsonData: string): void {
}
}
// Send current settings to the database
export const sendToDatabase = async () => {
const useName = localStorage.getItem("accountName");
const usePassword = localStorage.getItem("accountPassword");
const useName = localStorage.getItem("accountName")
const usePassword = localStorage.getItem("accountPassword")
if (useName && usePassword) {
const result = await changeSettings(useName, usePassword, JSON.parse(exportSettings()));
if (result === true) {
// Only reload if the settings change was successful
const result = await changeSettings(useName, usePassword, JSON.parse(exportSettings()))
if (result == true) {
window.location.reload();
}
}
window.location.reload();
};
// Import settings from the database based on username and password
export const importDatabase = async (useName: string, usePassword: string) => {
const databaseSettings = await getSettings(useName, usePassword);
// Ensure user settings exist before flattening and storing
if (typeof databaseSettings === 'object' && databaseSettings) {
if (typeof databaseSettings == 'object' && databaseSettings) {
importSettings(JSON.stringify(databaseSettings, null, 2)); // Pass only the current user's settings
} else {
console.error('Database settings are not in the expected format.');
}
};
}

View file

@ -1,4 +1,3 @@
//#region IOMARKET
export const applyIOMarketTheme = () => {
document.documentElement.style.setProperty('--header-background-color', '#7e7e7e');
document.documentElement.style.setProperty('--header-text-color', '#ffffff');
@ -36,7 +35,7 @@ export const applyIOMarketTheme = () => {
document.documentElement.style.setProperty('--font-family', "'Poppins', 'sans-serif'");
document.documentElement.style.setProperty('--font-size', '16px');
};
//#region WHITE
export const applyWhiteTheme = () => {
document.documentElement.style.setProperty('--header-background-color', '#f0f0f0'); // Lighter header background
document.documentElement.style.setProperty('--header-text-color', '#333'); // Dark text for contrast
@ -74,7 +73,7 @@ export const applyWhiteTheme = () => {
document.documentElement.style.setProperty('--font-family', "'Poppins', 'sans-serif'"); // Same font family
document.documentElement.style.setProperty('--font-size', '16px'); // Same font size
};
//#region BLACK
export const applyBlackTheme = () => {
document.documentElement.style.setProperty('--header-background-color', '#1a1a1a'); // Dark header background
document.documentElement.style.setProperty('--header-text-color', '#ffffff'); // White text for header
@ -113,7 +112,7 @@ export const applyBlackTheme = () => {
document.documentElement.style.setProperty('--font-size', '16px'); // Font size
};
//#region CUSTOM
export const applyCustomTheme = () => {
if (typeof localStorage !== 'undefined') {
const themeVariables = {
@ -192,8 +191,6 @@ export const applyCustomTheme = () => {
};
}
//#region BASIC-CUSTOM
// TypeScript types for color parameters
type Color = string;
@ -280,7 +277,6 @@ const lightenColor = (color: Color, percent: number): Color => {
return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
};
//#region APPLY-THEME
// This is the new function that calls the appropriate theme application
export const applyTheme = (theme: string, primary: string, secondary: string, accent: string, background: string, text: string) => {
switch (theme) {

View file

@ -1,98 +1,68 @@
import { useEffect, useState } from "react";
import { useEffect, useState } from "react"
// Define the structure of a Message
interface Message {
role: string; // The role of the message sender (e.g., system, user, assistant)
content: string; // The content of the message
role: string
content:string
}
// Define the structure for each chat session
interface ChatMessages {
name: string; // The name or title of the chat
messages: Message[]; // Array of messages in the chat
timestamp: number; // Timestamp for the chat session
name: string
messages: Message[]
timestamp: number
}
// Define the structure for the global chat history
interface GlobalChatHistory {
chats: ChatMessages[]; // Array of chat sessions
selectedIndex: number; // Index of the currently selected chat
chats: ChatMessages[]
selectedIndex: number
}
// Initial global chat history state
let globalChatHistory: GlobalChatHistory = {
chats: [
{
name: "Welcome!",
messages: [
{ role: "system", content: "you are a helpful assistant" },
{ role: "assistant", content: "Hello! How can I help you?" }
],
timestamp: 4
},
{ name: "Welcome!", messages: [{role:"system",content:"you are a helpful assistant"},{role:"assistant",content:"Hello! How can I help you?"}], timestamp: 4 },
],
selectedIndex: 0
};
selectedIndex:0
}
let listeners: ((state: GlobalChatHistory) => void)[] = []
// Listeners for state changes
let listeners: ((state: GlobalChatHistory) => void)[] = [];
// Function to set a new global state and notify listeners
const setGlobalState = (newState: GlobalChatHistory): void => {
globalChatHistory = newState; // Update the global state
listeners.forEach((listener) => listener(globalChatHistory)); // Notify all listeners
globalChatHistory = newState;
listeners.forEach((listener) => listener(globalChatHistory))
}
// Custom hook to manage chat history
export const useChatHistory = (): [
GlobalChatHistory, // Current state
(index: number) => void, // Function to set selected index
(newState: GlobalChatHistory) => void, // Function to set global state
(messageIndex: number, newContent: string) => void // Function to update a message
] => {
const [state, setState] = useState<GlobalChatHistory>(globalChatHistory); // Local state initialized with global state
export const useChatHistory = (): [GlobalChatHistory, (index:number)=>void, (newState:GlobalChatHistory) => void,(messageIndex: number, newContent:string)=> void] => {
const [state, setState] = useState<GlobalChatHistory>(globalChatHistory)
useEffect(() => {
// Log the initial state for debugging
console.log("Current global chat history:", globalChatHistory);
console.log("help", globalChatHistory);
// Listener to update local state when global state changes
const listener = (newState: GlobalChatHistory) => {
setState(newState);
};
setState(newState)
}
listeners.push(listener); // Add the listener to the array
listeners.push(listener)
// Cleanup function to remove the listener when the component unmounts
return () => {
listeners = listeners.filter((l) => l !== listener);
};
}, []);
listeners = listeners.filter((l) => l!== listener)
}
}, [])
// Function to set the selected chat index
const setSelectedIndex = (index: number) => {
setGlobalState({ ...state, selectedIndex: index }); // Update the global state
setGlobalState({...state,selectedIndex:index})
}
// Function to update a specific message in the current chat
const updateMessage = (messageIndex: number, newContent: string) => {
const updatedChats = [...state.chats]; // Make a copy of the current chats
const chatIndex = globalChatHistory.selectedIndex; // Get the currently selected chat index
// Check if the selected chat index is valid
const updatedChats = [...state.chats]
const chatIndex = globalChatHistory.selectedIndex
if (chatIndex >= 0 && chatIndex < updatedChats.length) {
const updatedMessages = [...updatedChats[chatIndex].messages]; // Copy messages of the selected chat
// Check if the message index is valid
const updatedMessages = [...updatedChats[chatIndex].messages]
if (messageIndex >= 0 && messageIndex < updatedMessages.length) {
// Update the content of the specified message
updatedMessages[messageIndex] = { ...updatedMessages[messageIndex], content: newContent };
updatedChats[chatIndex] = { ...updatedChats[chatIndex], messages: updatedMessages }; // Update the chat with new messages
setGlobalState({ ...state, chats: updatedChats }); // Set the updated global state
updatedMessages[messageIndex] = { ...updatedMessages[messageIndex], content: newContent }
updatedChats[chatIndex] = { ...updatedChats[chatIndex], messages: updatedMessages }
setGlobalState({...state, chats: updatedChats})
}
}
}
// Return the current state and action functions
return [state, setSelectedIndex, setGlobalState, updateMessage];
}
return [state, setSelectedIndex, setGlobalState, updateMessage]
}

View file

@ -1,23 +1,24 @@
import { ReactNode } from 'react';
// Metadata for the application, used for SEO and page information
export const metadata = {
title: 'AI Assistant | Interstellar Development', // Title of the page
description: 'A little AI chat that is able to assist you in little tasks', // Description of the page
title: 'AI Assistant | Interstellar Development',
description: 'A little AI chat that is able to assist you in little tasks',
};
// RootLayout component definition
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en"> {/* Set the language of the document */}
<html lang="en">
<head>
<title>{metadata.title}</title> {/* Set the page title */}
<meta name="description" content={metadata.description} /> {/* Set the page description for SEO */}
{/* Link to the favicon for the site */}
<title>{metadata.title}</title>
<meta name="description" content={metadata.description} />
{/* Tried adding the favicon here */}
<link rel="icon" href="./favicon.ico" type="image/x-icon" />
</head>
<body>
<main>{children}</main> {/* Render the child components inside the main element */}
<main>{children}</main>
</body>
</html>
);

View file

@ -7,30 +7,21 @@ import Documentation from './components/Documentation'; // Ensure the import pat
import History from './components/History';
import Models from './components/Models';
import Credits from './components/Credits';
import {
applyIOMarketTheme,
applyWhiteTheme,
applyBlackTheme,
applyCustomTheme,
applyBasicCustomTheme
} from './components/settings/theme';
import { applyIOMarketTheme, applyWhiteTheme, applyBlackTheme, applyCustomTheme, applyBasicCustomTheme } from './components/settings/theme';
import './styles/master.css';
const LandingPage: React.FC = () => {
// State to control visibility of the left panels
const [showDivs, setShowDivs] = useState(true);
// State to track which view is currently displayed
const [view, setView] = useState<'AI' | 'FAQ' | 'Documentation' | 'Credits'>('AI');
const conversationRef = useRef<HTMLDivElement>(null);
// State for theme colors
const [primaryColor, setPrimaryColor] = useState("#fefefe");
const [secondaryColor, setSecondaryColor] = useState("#fefefe");
const [accentColor, setAccentColor] = useState("#fefefe");
const [basicBackgroundColor, setBasicBackgroundColor] = useState("#fefefe");
const [basicTextColor, setBasicTextColor] = useState("#fefefe");
const [primaryColor, setPrimaryColor] = useState("#fefefe");
const [secondaryColor, setSecondaryColor] = useState("#fefefe");
const [accentColor, setAccentColor] = useState("#fefefe");
const [basicBackgroundColor, setBasicBackgroundColor] = useState("#fefefe");
const [basicTextColor, setBasicTextColor] = useState("#fefefe");
// Synchronize theme colors with local storage on component mount
// Synchronize state with local storage on mount
useEffect(() => {
if (typeof localStorage !== 'undefined') {
setPrimaryColor(localStorage.getItem("primaryColor") || "#fefefe");
@ -41,21 +32,18 @@ const LandingPage: React.FC = () => {
}
}, [primaryColor, secondaryColor, accentColor, basicBackgroundColor, basicTextColor]);
// Toggle visibility of the left panels
const toggleDivs = () => {
setShowDivs(prevState => !prevState);
};
// Change the current view based on user selection
const handleViewChange = (view: 'AI' | 'FAQ' | 'Documentation' | 'Credits') => {
setView(view);
// Hide left panels if the selected view is not 'AI'
if (view !== 'AI') {
setShowDivs(false);
}
};
// Apply the selected theme and color settings based on local storage
// Apply theme based on selectedTheme and color settings
useEffect(() => {
if (typeof localStorage !== 'undefined') {
const savedTheme = localStorage.getItem('selectedTheme');
@ -64,8 +52,8 @@ const LandingPage: React.FC = () => {
case 'IOMARKET':
applyIOMarketTheme();
break;
case 'WHITE':
applyWhiteTheme();
case 'WHITE':
applyWhiteTheme();
break;
case 'BLACK':
applyBlackTheme();
@ -73,8 +61,8 @@ const LandingPage: React.FC = () => {
case 'CUSTOM':
applyCustomTheme();
break;
case 'BASIC-CUSTOM':
applyBasicCustomTheme(
case 'BASIC-CUSTOM':
applyBasicCustomTheme(
primaryColor,
secondaryColor,
accentColor,
@ -83,16 +71,15 @@ const LandingPage: React.FC = () => {
);
break;
default:
applyIOMarketTheme(); // Fallback theme
applyIOMarketTheme();
break;
}
}
}
}, [primaryColor, secondaryColor, accentColor, basicBackgroundColor, basicTextColor]); // Apply themes whenever color states change
}, [primaryColor, secondaryColor, accentColor, basicBackgroundColor, basicTextColor]); // Watch color states and apply themes accordingly
return (
<>
{/* Header component with props for toggling and view change */}
<Header
toggleDivs={toggleDivs}
showDivs={showDivs}
@ -104,14 +91,12 @@ const LandingPage: React.FC = () => {
<div className={`left-panel ${showDivs ? 'visible' : 'hidden'}`}>
{showDivs && (
<div className="history-models">
{/* Show History and Models components if left panels are visible */}
<History />
<Models />
</div>
)}
</div>
<div className={`conversation-container ${showDivs ? 'collapsed' : 'expanded'}`} ref={conversationRef}>
{/* Render the selected view based on the current state */}
{view === 'AI' && <AI />}
{view === 'FAQ' && <FAQ />}
{view === 'Documentation' && <Documentation />}

View file

@ -4,11 +4,10 @@ import google.generativeai as genai
import anthropic
import ollama
class AI:
@staticmethod
def process_local(model, messages, return_class, access_token):
"""Process chat messages using the Ollama model locally."""
# Stream the chat response from the Ollama model
stream = ollama.chat(
model=model,
messages=messages,
@ -16,61 +15,50 @@ class AI:
options={"temperature": 0.5},
)
# Initialize the AI response for the given access token
with return_class.ai_response_lock:
return_class.ai_response[access_token] = ""
# Collect the response chunks and append to the response for the given access token
for chunk in stream:
with return_class.ai_response_lock:
return_class.ai_response[access_token] += chunk["message"]["content"]
@staticmethod
def process_mistralai(model, messages, return_class, access_token, api_key):
"""Process chat messages using the Mistral AI model."""
client = Mistral(api_key=api_key)
# Stream the chat response from the Mistral model
stream_response = client.chat.stream(model=model, messages=messages)
# Initialize the AI response for the given access token
with return_class.ai_response_lock:
return_class.ai_response[access_token] = ""
# Collect the response chunks and append to the response for the given access token
for chunk in stream_response:
with return_class.ai_response_lock:
return_class.ai_response[access_token] += chunk.data.choices[0].delta.content
return_class.ai_response[access_token] += chunk.data.choices[
0
].delta.content
@staticmethod
def process_openai(model, messages, return_class, access_token, api_key):
"""Process chat messages using the OpenAI model."""
client = OpenAI(api_key=api_key)
# Stream the chat response from the OpenAI model
stream_response = client.chat.completions.create(
model=model, messages=messages, stream=True
)
# Initialize the AI response for the given access token
with return_class.ai_response_lock:
return_class.ai_response[access_token] = ""
# Collect the response chunks and append to the response for the given access token
for chunk in stream_response:
with return_class.ai_response_lock:
return_class.ai_response[access_token] += chunk.choices[0].delta.content
@staticmethod
def process_anthropic(model, messages, return_class, access_token, api_key):
"""Process chat messages using the Anthropic model."""
client = anthropic.Anthropic(api_key=api_key)
# Initialize the AI response for the given access token
with return_class.ai_response_lock:
return_class.ai_response[access_token] = ""
# Stream the chat response from the Anthropic model
with client.messages.stream(
max_tokens=1024,
model=model,
@ -82,27 +70,24 @@ class AI:
@staticmethod
def process_google(model, messages, return_class, access_token, api_key):
"""Process chat messages using the Google Generative AI model."""
message = messages[-1]["content"] # Get the latest message content
messages.pop() # Remove the latest message from the list
message = messages[-1]["content"]
messages.pop()
# Prepare messages for the Google Generative AI format
for msg in messages:
msg["parts"] = msg.pop()["content"]
# Change 'assistant' role to 'model' for compatibility
for msg in messages:
if msg["role"] == "assistant":
msg["role"] = "model"
# Configure the Google Generative AI client
genai.configure(api_key=api_key)
# Start a chat session with the specified model and message history
model = genai.GenerativeModel(model)
chat = model.start_chat(history=messages)
# Send the message and stream the response
chat = model.start_chat(
history=messages,
)
response = chat.send_message(message, stream=True)
for chunk in response:
return_class.ai_response[access_token] += chunk.text

122
py/api.py
View file

@ -1,4 +1,5 @@
from time import sleep
from flask import Flask, request, jsonify
from flask_cors import CORS
import secrets
@ -12,58 +13,53 @@ from tts import TTS
class API:
def __init__(self):
# Initialize the API class with necessary components and configurations
self.crypt_size = 64 # Size for generating secure tokens
self.app = Flask(__name__) # Create a Flask app instance
self.ai_response = {} # Dictionary to store AI responses keyed by access token
self.ai = AI() # AI processing instance
self.db = DB() # Database instance
self.weather = Weather() # Weather data retrieval instance
self.voice = VoiceRecognition() # Voice recognition instance
self.tts = TTS() # Text-to-Speech instance
self.db.load_database() # Load the database on startup
self.ai_response_lock = threading.Lock() # Lock for thread-safe access to AI responses
CORS(self.app) # Enable Cross-Origin Resource Sharing
self.crypt_size = 64
self.app = Flask(__name__)
self.ai_response = {}
self.ai = AI()
self.db = DB()
self.weather = Weather()
self.voice = VoiceRecognition()
self.tts = TTS()
self.db.load_database()
self.ai_response_lock = threading.Lock()
CORS(self.app)
def run(self):
# Route to create a new AI session
@self.app.route("/interstellar_ai/api/ai_create", methods=["GET"])
def create_ai():
access_token = secrets.token_urlsafe(self.crypt_size) # Generate a secure access token
access_token = secrets.token_urlsafe(self.crypt_size)
# Ensure the access token is unique
while access_token in self.ai_response:
access_token = secrets.token_urlsafe(self.crypt_size)
self.ai_response[access_token] = "" # Initialize the response for the new session
self.ai_response[access_token] = ""
return jsonify({"status": 200, "access_token": access_token})
# Route to send messages to the AI
@self.app.route("/interstellar_ai/api/ai_send", methods=["POST"])
def send_ai():
data = request.get_json() # Get JSON data from the request
messages = data.get("messages") # Extract messages
model_type = data.get("model_type") # Extract model type
ai_model = data.get("ai_model") # Extract AI model name
access_token = data.get("access_token") # Extract access token
data = request.get_json()
messages = data.get("messages")
model_type = data.get("model_type")
ai_model = data.get("ai_model")
access_token = data.get("access_token")
print(model_type) # Debugging output
print(model_type)
if access_token not in self.ai_response:
return jsonify({"status": 401, "error": "Invalid access token"}) # Token validation
return jsonify({"status": 401, "error": "Invalid access token"})
# Start a new thread to process AI requests based on the model type
if model_type == "local":
thread = threading.Thread(
target=self.ai.process_local,
args=(ai_model, messages, self, access_token),
)
thread.start()
thread.join() # Wait for the thread to complete
sleep(0.5) # Sleep for a short duration
thread.join()
sleep(0.5)
return jsonify({"status": 200})
elif model_type == "mistral":
print(model_type) # Debugging output
api_key = data.get("api_key") # Get API key
print(model_type)
api_key = data.get("api_key")
thread = threading.Thread(
target=self.ai.process_mistralai,
args=(ai_model, messages, self, access_token, api_key),
@ -73,7 +69,7 @@ class API:
sleep(0.5)
return jsonify({"status": 200})
elif model_type == "openai":
api_key = data.get("api_key") # Get API key
api_key = data.get("api_key")
thread = threading.Thread(
target=self.ai.process_openai,
args=(ai_model, messages, self, access_token, api_key),
@ -83,7 +79,7 @@ class API:
sleep(0.5)
return jsonify({"status": 200})
elif model_type == "anthropic":
api_key = data.get("api_key") # Get API key
api_key = data.get("api_key")
thread = threading.Thread(
target=self.ai.process_anthropic,
args=(ai_model, messages, self, access_token, api_key),
@ -93,7 +89,7 @@ class API:
sleep(0.5)
return jsonify({"status": 200})
elif model_type == "google":
api_key = data.get("api_key") # Get API key
api_key = data.get("api_key")
thread = threading.Thread(
target=self.ai.process_google,
args=(ai_model, messages, self, access_token, api_key),
@ -103,85 +99,79 @@ class API:
sleep(0.5)
return jsonify({"status": 200})
return jsonify({"status": 401, "error": "Invalid AI model type"}) # Model type validation
return jsonify({"status": 401, "error": "Invalid AI model type"})
# Route to retrieve AI response based on access token
@self.app.route("/interstellar_ai/api/ai_get", methods=["GET"])
def get_ai():
data = request.args.get("access_token") # Get access token from query parameters
data = request.args.get("access_token")
if data not in self.ai_response:
return jsonify({"status": 401, "error": "Invalid access token"}) # Token validation
return jsonify({"status": 200, "response": self.ai_response[data]}) # Return AI response
return jsonify({"status": 401, "error": "Invalid access token"})
return jsonify({"status": 200, "response": self.ai_response[data]})
# Route for database operations
@self.app.route("/interstellar_ai/db", methods=["POST"])
def db_manipulate():
sent_data = request.get_json() # Get JSON data from the request
action = sent_data.get("action") # Extract action type
sent_data = request.get_json()
action = sent_data.get("action")
if action == "create_account":
return jsonify({"status": 200, "response": self.db.add_user(sent_data)}) # Add user
return jsonify({"status": 200, "response": self.db.add_user(sent_data)})
elif action == "change_password":
return jsonify(
{"status": 200, "response": self.db.update_password(sent_data)} # Update password
{"status": 200, "response": self.db.update_password(sent_data)}
)
elif action == "get_settings":
return jsonify(
{"status": 200, "response": self.db.get_settings(sent_data)} # Get user settings
{"status": 200, "response": self.db.get_settings(sent_data)}
)
elif action == "change_settings":
return jsonify(
{"status": 200, "response": self.db.change_settings(sent_data)} # Change user settings
{"status": 200, "response": self.db.change_settings(sent_data)}
)
elif action == "get_history":
return jsonify(
{"status": 200, "response": self.db.get_history(sent_data)} # Get user history
{"status": 200, "response": self.db.get_history(sent_data)}
)
elif action == "change_history":
return jsonify(
{"status": 200, "response": self.db.change_history(sent_data)} # Change user history
{"status": 200, "response": self.db.change_history(sent_data)}
)
elif action == "check_credentials":
return jsonify(
{"status": 200, "response": self.db.check_credentials(sent_data)} # Check user credentials
{"status": 200, "response": self.db.check_credentials(sent_data)}
)
elif action == "delete_account":
return jsonify(
{"status": 200, "response": self.db.delete_user(sent_data)} # Delete user account
{"status": 200, "response": self.db.delete_user(sent_data)}
)
elif action == "get_email":
return jsonify(
{"status": 200, "response": self.db.get_email(sent_data)} # Get user email
{"status": 200, "response": self.db.get_email(sent_data)}
)
elif action == "get_name":
return jsonify({"status": 200, "response": self.db.get_name(sent_data)}) # Get user name
return jsonify({"status": 200, "response": self.db.get_name(sent_data)})
return jsonify({"status": 401, "response": "Invalid action"}) # Action validation
return jsonify({"status": 401, "response": "Invalid action"})
# Route for voice recognition
@self.app.route("/interstellar_ai/api/voice_recognition", methods=["POST"])
def voice_recognition():
audio = request.files.get("audio") # Get audio file from request
text = self.voice.recognition(audio) # Perform voice recognition
return jsonify({"status": 200, "response": text}) # Return recognized text
audio = request.files.get("audio")
text = self.voice.recognition(audio)
return jsonify({"status": 200, "response": text})
# Route for weather information retrieval
@self.app.route("/interstellar_ai/api/weather", methods=["POST"])
def get_weather():
sent_data = request.get_json() # Get JSON data from the request
unit_type = sent_data.get("unit_type") # Extract unit type (metric, imperial)
city = sent_data.get("city") # Extract city name
weather_data = self.weather.getweather(unit_type, city) # Get weather data
return jsonify({"status": 200, "response": weather_data}) # Return weather data
sent_data = request.get_json()
unit_type = sent_data.get("unit_type")
city = sent_data.get("city")
weather_data = self.weather.getweather(unit_type, city)
return jsonify({"status": 200, "response": weather_data})
self.app.run(debug=True, host="0.0.0.0", port=5000) # Start the Flask app
self.app.run(debug=True, host="0.0.0.0", port=5000)
# Route for Text-to-Speech conversion
@self.app.route("/interstellar_ai/api/tts", methods=["POST"])
def tts():
text = request.args.get("text") # Get text from query parameters
return jsonify({"status": 200, "response": self.tts.gen_tts(text)}) # Generate TTS and return response
text = request.args.get("text")
return jsonify({"status": 200, "response": self.tts.gen_tts(text)})
# Initialize the API class and run the application
api = API()
api.run()

View file

@ -3,13 +3,12 @@ import json
import os
import pycouchdb
class DB:
def __init__(self):
# Initialize the database dictionary to store user data
self.database = {}
def ensure_username(self, data):
# Ensure a username can be retrieved either from username or email
if "username" in data:
return data.get("username")
elif "email" in data:
@ -19,17 +18,15 @@ class DB:
@staticmethod
def hash_password(password):
# Hash the password with a salt for secure storage
salt = "your_secret_salt" # Consider using a secure random salt
salt = "your_secret_salt"
hashed_password = hashlib.sha256((password + salt).encode()).hexdigest()
return hashed_password
def add_user(self, data):
# Add a new user to the database if username is unique
username = data.get("username")
password = data.get("password")
email = data.get("email")
hashed_password = self.hash_password(password) # Hash the password
hashed_password = self.hash_password(password)
user_data = {
"hashed_password": hashed_password,
"email": email,
@ -38,123 +35,112 @@ class DB:
}
if username not in self.database:
self.database[username] = user_data
self.save_database() # Save changes to the database
self.save_database()
return True
return False # User already exists
return False
def delete_user(self, data):
# Delete a user from the database if credentials are valid
username = self.ensure_username(data)
if not self.check_credentials(data):
return False # Invalid credentials
return False
del self.database[username] # Remove user from database
self.save_database() # Save changes
del self.database[username]
self.save_database()
return True
def update_password(self, data):
# Update the user's password if credentials are valid
username = self.ensure_username(data)
new_password = data.get("new_password")
if not self.check_credentials(data):
return False # Invalid credentials
return False
hashed_new_password = self.hash_password(new_password) # Hash the new password
hashed_new_password = self.hash_password(new_password)
self.database[username].update({"hashed_password": hashed_new_password})
self.save_database() # Save changes
self.save_database()
return True
def check_credentials(self, data):
# Verify if provided credentials match stored data
username = self.ensure_username(data)
password = data.get("password")
if username not in self.database:
return False # User not found
return False
stored_hashed_password = self.database[username]["hashed_password"]
entered_hashed_password = self.hash_password(password)
return stored_hashed_password == entered_hashed_password # Check hashed password
return stored_hashed_password == entered_hashed_password
def change_settings(self, data):
# Change user settings if credentials are valid
username = self.ensure_username(data)
if not self.check_credentials(data):
return False # Invalid credentials
return False
self.database[username]["settings"] = data.get("data") # Update settings
self.save_database() # Save changes
self.database[username]["settings"] = data.get("data")
self.save_database()
return True
def get_settings(self, data):
# Retrieve user settings if credentials are valid
username = self.ensure_username(data)
if not self.check_credentials(data):
return None # Invalid credentials
return None
send_back = self.database[username].get("settings") # Get settings
send_back = self.database[username].get("settings")
return send_back
def change_history(self, data):
# Change user history if credentials are valid
username = self.ensure_username(data)
if not self.check_credentials(data):
return False # Invalid credentials
return False
self.database[username]["history"] = data.get("data") # Update history
self.save_database() # Save changes
self.database[username]["history"] = data.get("data")
self.save_database()
return True
def get_history(self, data):
# Retrieve user history if credentials are valid
username = self.ensure_username(data)
if not self.check_credentials(data):
return None # Invalid credentials
return None
send_back = self.database[username].get("history") # Get history
send_back = self.database[username].get("history")
return send_back
def get_email(self, data):
# Retrieve user email if credentials are valid
username = self.ensure_username(data)
if not self.check_credentials(data):
return None # Invalid credentials
return None
send_back = self.database[username].get("email") # Get email
send_back = self.database[username].get("email")
return send_back
def get_name(self, data):
# Retrieve username if credentials are valid
if not self.check_credentials(data):
return None # Invalid credentials
return None
send_back = self.ensure_username(data) # Get username
send_back = self.ensure_username(data)
return send_back
def save_database(self):
# Save the database to the specified storage (CouchDB or JSON file)
if os.environ.get("PRODUCTION") == "YES":
server = pycouchdb.Server("http://admin:admin@localhost:5984/")
db = server.database("interstellar_ai")
db.save(self.database) # Save to CouchDB
db.save(self.database)
else:
with open("database.json", "w") as file:
json.dump(self.database, file) # Save to JSON file
json.dump(self.database, file)
def load_database(self):
# Load the database from the specified storage (CouchDB or JSON file)
if os.environ.get("PRODUCTION") == "YES":
server = pycouchdb.Server("http://admin:admin@localhost:5984/")
db = server.database("interstellar_ai")
if db:
self.database = db # Load from CouchDB
self.database = db
else:
server.create("interstellar_ai") # Create database if it doesn't exist
server.create("interstellar_ai")
db = server.database("interstellar_ai")
db.save(self.database) # Save initial empty database
db.save(self.database)
else:
try:
with open("database.json", "r") as file:
self.database = json.load(file) # Load from JSON file
self.database = json.load(file)
except FileNotFoundError:
pass # File not found, do nothing
pass

View file

@ -1,5 +1,6 @@
import pyttsx3
class TTS:
@staticmethod
def gen_tts(text):

View file

@ -6,28 +6,20 @@ from pydub import AudioSegment
class VoiceRecognition:
@staticmethod
def recognition(audio):
# Read the audio file into a BytesIO buffer
audio_buffer = io.BytesIO(audio.read())
# Load the audio file using pydub
audio_segment = AudioSegment.from_file(audio_buffer, format="ogg")
# Export the audio to a WAV format in a BytesIO buffer
wav_io = io.BytesIO()
audio_segment.export(wav_io, format="wav")
wav_io.seek(0) # Reset the buffer pointer to the start
wav_io.seek(0)
# Load the Whisper model
model_size = "base" # Specify the model size
model_size = "base"
model = WhisperModel(model_size, device="cpu", compute_type="int8")
# Transcribe the audio
segments, _ = model.transcribe(wav_io)
transcription = ""
# Combine the transcribed segments into a single string
for segment in segments:
transcription += segment.text + " "
result = transcription.strip() # Strip any leading/trailing whitespace
result = transcription.strip()
return result

View file

@ -15,7 +15,6 @@ class Weather:
async with python_weather.Client(unit=unit_type) as client:
weather = await client.get(city)
# Collect weather data
data = {
"temperature": weather.temperature,
"humidity": weather.humidity,