From d3b9d259afa39b65ac7d3de0a8c43686d1e13084 Mon Sep 17 00:00:00 2001 From: flukexp Date: Sun, 5 Jan 2025 01:09:17 +0700 Subject: [PATCH 01/11] fixed external api build updated config to sync with localStorage on startup --- logs.json | 115 ++++++++++++++++++++++++- public/debugLogger.js | 6 +- src/features/amicaLife/eventHandler.ts | 7 +- src/features/chat/chat.ts | 7 +- src/pages/api/amicaHandler.ts | 16 +++- src/pages/api/dataHandler.ts | 36 ++++++-- src/pages/api/mediaHandler.ts | 5 +- src/utils/config.ts | 51 +++++++---- 8 files changed, 210 insertions(+), 33 deletions(-) diff --git a/logs.json b/logs.json index 1610ea1..4d10a62 100644 --- a/logs.json +++ b/logs.json @@ -1,3 +1,116 @@ [ - + { + "type": "warn", + "ts": 1736014069964, + "arguments": { + "0": "THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead." + } + }, + { + "type": "log", + "ts": 1736014069927, + "arguments": { + "0": "Starting Amica Life" + } + }, + { + "type": "log", + "ts": 1736014070523, + "arguments": { + "0": "[Fast Refresh] rebuilding" + } + }, + { + "type": "log", + "ts": 1736014071838, + "arguments": { + "0": "vrm loaded" + } + }, + { + "type": "debug", + "ts": 1736014072216, + "arguments": { + "0": "[VAD]", + "1": "initializing vad" + } + }, + { + "type": "warn", + "ts": 1736014072889, + "arguments": { + "0": "2025-01-05 01:07:52.888400 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '140'. It is not used by any node and should be removed from the model." + } + }, + { + "type": "warn", + "ts": 1736014072895, + "arguments": { + "0": "2025-01-05 01:07:52.894799 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '131'. It is not used by any node and should be removed from the model." + } + }, + { + "type": "warn", + "ts": 1736014072896, + "arguments": { + "0": "2025-01-05 01:07:52.895900 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '139'. It is not used by any node and should be removed from the model." + } + }, + { + "type": "warn", + "ts": 1736014072898, + "arguments": { + "0": "2025-01-05 01:07:52.897099 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '136'. It is not used by any node and should be removed from the model." + } + }, + { + "type": "warn", + "ts": 1736014072905, + "arguments": { + "0": "2025-01-05 01:07:52.902500 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '134'. It is not used by any node and should be removed from the model." + } + }, + { + "type": "warn", + "ts": 1736014072908, + "arguments": { + "0": "2025-01-05 01:07:52.906700 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '628'. It is not used by any node and should be removed from the model." + } + }, + { + "type": "warn", + "ts": 1736014072913, + "arguments": { + "0": "2025-01-05 01:07:52.912799 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '625'. It is not used by any node and should be removed from the model." + } + }, + { + "type": "warn", + "ts": 1736014072915, + "arguments": { + "0": "2025-01-05 01:07:52.914400 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '623'. It is not used by any node and should be removed from the model." + } + }, + { + "type": "warn", + "ts": 1736014072917, + "arguments": { + "0": "2025-01-05 01:07:52.916400 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '629'. It is not used by any node and should be removed from the model." + } + }, + { + "type": "warn", + "ts": 1736014072919, + "arguments": { + "0": "2025-01-05 01:07:52.918299 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '620'. It is not used by any node and should be removed from the model." + } + }, + { + "type": "debug", + "ts": 1736014073014, + "arguments": { + "0": "[VAD]", + "1": "vad is initialized" + } + } ] \ No newline at end of file diff --git a/public/debugLogger.js b/public/debugLogger.js index 3d0d75d..7d8a154 100644 --- a/public/debugLogger.js +++ b/public/debugLogger.js @@ -14,7 +14,11 @@ if (typeof window !== "undefined") { ts: +new Date, arguments, }); - let dataHandlerUrl = new URL("http://localhost:3000/api/dataHandler"); + const baseUrl = window.location.hostname === "localhost" + ? "http://localhost:3000" + : "https://amica.arbius.ai"; + + let dataHandlerUrl = new URL("/api/dataHandler", baseUrl); dataHandlerUrl.searchParams.append('type', 'logs'); fetch(dataHandlerUrl, { method: "POST", diff --git a/src/features/amicaLife/eventHandler.ts b/src/features/amicaLife/eventHandler.ts index 8b13c0c..070d9ea 100644 --- a/src/features/amicaLife/eventHandler.ts +++ b/src/features/amicaLife/eventHandler.ts @@ -11,6 +11,7 @@ import { functionCalling } from "@/features/functionCalling/functionCalling"; import { AmicaLife } from "./amicaLife"; import { Viewer } from "../vrmViewer/viewer"; import { config } from "@/utils/config"; +import isDev from "@/utils/isDev"; export const idleEvents = [ "VRMA", @@ -48,7 +49,11 @@ export type TimestampedPrompt = { // Placeholder for storing compressed subconscious prompts export let storedSubconcious: TimestampedPrompt[] = []; -let dataHandlerUrl = new URL("http://localhost:3000/api/dataHandler"); +const baseUrl = isDev + ? "http://localhost:3000" + : "https://amica.arbius.ai"; + +let dataHandlerUrl = new URL("/api/dataHandler", baseUrl); dataHandlerUrl.searchParams.append('type', 'subconscious'); let previousAnimation = ""; diff --git a/src/features/chat/chat.ts b/src/features/chat/chat.ts index 6c4ea2a..193b46f 100644 --- a/src/features/chat/chat.ts +++ b/src/features/chat/chat.ts @@ -26,6 +26,7 @@ import { processResponse } from "@/utils/processResponse"; import { wait } from "@/utils/wait"; import { isCharacterIdle, characterIdleTime, resetIdleTimer } from "@/utils/isIdle"; import { loadVRMAnimation } from '@/lib/VRMAnimation/loadVRMAnimation'; +import isDev from '@/utils/isDev'; type Speak = { @@ -336,7 +337,11 @@ export class Chat { if (!amicaLife) { console.log('receiveMessageFromUser', message); - let dataHandlerUrl = new URL("http://localhost:3000/api/dataHandler"); + const baseUrl = isDev + ? "http://localhost:3000" + : "https://amica.arbius.ai"; + + let dataHandlerUrl = new URL("/api/dataHandler", baseUrl); dataHandlerUrl.searchParams.append('type', 'userInputMessages'); fetch(dataHandlerUrl, { method: "POST", diff --git a/src/pages/api/amicaHandler.ts b/src/pages/api/amicaHandler.ts index d622d3b..dc2578f 100644 --- a/src/pages/api/amicaHandler.ts +++ b/src/pages/api/amicaHandler.ts @@ -4,7 +4,8 @@ import { randomBytes } from "crypto"; import type { NextApiRequest, NextApiResponse } from "next"; import { twitterClientInstance as twitterClient } from "@/features/socialMedia/twitterClient"; import { telegramClientInstance as telegramCLient } from "@/features/socialMedia/telegramClient"; -import { config } from "@/utils/config"; +import { config, fetchServerConfig } from "@/utils/config"; +import isDev from "@/utils/isDev"; interface ApiResponse { sessionId?: string; @@ -24,13 +25,18 @@ interface LogEntry { const logs: LogEntry[] = []; const clients: Array<{ res: NextApiResponse }> = []; -let subconsciousUrl = new URL("http://localhost:3000/api/dataHandler"); + +const baseUrl = isDev + ? "http://localhost:3000" + : "https://amica.arbius.ai"; + +let subconsciousUrl = new URL("/api/dataHandler", baseUrl); subconsciousUrl.searchParams.append("type", "subconscious"); -let logsUrl = new URL("http://localhost:3000/api/dataHandler"); +let logsUrl = new URL("/api/dataHandler", baseUrl); logsUrl.searchParams.append("type", "logs"); -let userInputMessagesUrl = new URL("http://localhost:3000/api/dataHandler"); +let userInputMessagesUrl = new URL("/api/dataHandler", baseUrl); userInputMessagesUrl.searchParams.append("type", "userInputMessages"); // Helper Functions @@ -176,6 +182,8 @@ const processRequest = async ( inputType: string, payload: any ): Promise<{ response: any; outputType: string }> => { + // Syncing config to be accessible from server side + await fetchServerConfig(); switch (inputType) { case "Normal Chat Message": return { response: await processNormalChat(payload), outputType: "Complete stream" }; diff --git a/src/pages/api/dataHandler.ts b/src/pages/api/dataHandler.ts index b63cb58..e347b8c 100644 --- a/src/pages/api/dataHandler.ts +++ b/src/pages/api/dataHandler.ts @@ -91,23 +91,41 @@ const handlePostRequest = (type: string, req: NextApiRequest, res: NextApiRespon // Sub-functions const updateConfig = (body: any, res: NextApiResponse) => { - const { key, value } = body; - - if (!key || value === undefined) { - return res.status(400).json({ error: 'Key and value are required to update the config.' }); + if (!body || (typeof body !== 'object' && !Array.isArray(body))) { + return res.status(400).json({ error: 'Body must be an object or array of key-value pairs.' }); } const config = readFile(configFilePath); - if (!config.hasOwnProperty(key)) { - return res.status(400).json({ error: `Config key "${key}" not found.` }); + // Handle single key-value update + if (body.key && body.value !== undefined) { + const { key, value } = body; + if (!config.hasOwnProperty(key)) { + return res.status(400).json({ error: `Config key "${key}" not found.` }); + } + + config[key] = value; + writeFile(configFilePath, config); + return res.status(200).json({ message: 'Config updated successfully.' }); } - config[key] = value; - writeFile(configFilePath, config); - res.status(200).json({ message: 'Config updated successfully.' }); + // Handle multiple key-value updates + if (typeof body === 'object' && !Array.isArray(body)) { + for (const [key, value] of Object.entries(body)) { + if (!config.hasOwnProperty(key)) { + console.log("body : ",key,config) + return res.status(400).json({ error: `Config key "${key}" not found.` }); + } + config[key] = value; + } + writeFile(configFilePath, config); + return res.status(200).json({ message: 'Config updated successfully.' }); + } + + return res.status(400).json({ error: 'Invalid body format. Please provide either a key-value pair or an object with multiple key-value pairs.' }); }; + const updateSubconscious = (body: any, res: NextApiResponse) => { const { subconscious } = body; diff --git a/src/pages/api/mediaHandler.ts b/src/pages/api/mediaHandler.ts index a2f95b7..37a11cf 100644 --- a/src/pages/api/mediaHandler.ts +++ b/src/pages/api/mediaHandler.ts @@ -2,7 +2,7 @@ import { openaiWhisper } from '@/features/openaiWhisper/openaiWhisper'; import { whispercpp } from '@/features/whispercpp/whispercpp'; import { askVisionLLM } from '@/utils/askLlm'; import { TimestampedPrompt } from '@/features/amicaLife/eventHandler'; -import { config as configs} from '@/utils/config'; +import { config as configs, fetchServerConfig} from '@/utils/config'; // import { logs } from './amicaHandler'; import { randomBytes } from 'crypto'; @@ -62,6 +62,9 @@ async function handleRequest(sessionId: string, timestamp: string, fields: any, const inputType = fields.inputType[0]; const payload = files?.payload[0] ; + + // Syncing config to be accessible from server side + await fetchServerConfig(); try { switch (inputType) { diff --git a/src/utils/config.ts b/src/utils/config.ts index a7e3082..928ebd0 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -1,3 +1,5 @@ +import isDev from "./isDev"; + const defaults = { autosend_from_mic: 'true', wake_word_enabled: 'false', @@ -15,7 +17,7 @@ const defaults = { youtube_videoid: '', animation_url: process.env.NEXT_PUBLIC_ANIMATION_URL ?? '/animations/idle_loop.vrma', voice_url: process.env.NEXT_PUBLIC_VOICE_URL ?? '', - chatbot_backend: process.env.NEXT_PUBLIC_CHATBOT_BACKEND ?? 'openai', + chatbot_backend: process.env.NEXT_PUBLIC_CHATBOT_BACKEND ?? 'chatgpt', openai_apikey: process.env.NEXT_PUBLIC_OPENAI_APIKEY ?? 'default', openai_url: process.env.NEXT_PUBLIC_OPENAI_URL ?? 'https://i-love-amica.com', openai_model: process.env.NEXT_PUBLIC_OPENAI_MODEL ?? 'mlabonne/NeuralDaredevil-8B-abliterated', @@ -98,10 +100,13 @@ function prefixed(key: string) { // Fetch configuration from the server let serverConfig: Record | null = null; -let dataHandlerUrl = new URL("http://localhost:3000/api/dataHandler"); +const baseUrl = isDev + ? "http://localhost:3000" + : "https://amica.arbius.ai"; +let dataHandlerUrl = new URL("/api/dataHandler", baseUrl); dataHandlerUrl.searchParams.append('type', 'config'); -async function fetchServerConfig() { +export async function fetchServerConfig() { try { const response = await fetch(dataHandlerUrl); if (response.ok) { @@ -114,19 +119,36 @@ async function fetchServerConfig() { // Call this function at the beginning of your application to load the server config and sync to localStorage if needed. async function initializeConfig() { - await fetchServerConfig(); // Load server config into serverConfig variable - - // Sync server config to localStorage if it's missing there - if (serverConfig) { - for (const [key, value] of Object.entries(serverConfig)) { - const localKey = prefixed(key); - if (typeof localStorage !== "undefined" && !localStorage.hasOwnProperty(localKey)) { - localStorage.setItem(localKey, value); - } + // await fetchServerConfig(); // Load server config into serverConfig variable + + // Merge with serverConfig + let localStorageData: Record = {}; + Object.keys(localStorage).forEach((key) => { + if (key.startsWith("chatvrm_")) { + const trimmedKey = key.replace("chatvrm_", ""); + localStorageData[trimmedKey] = localStorage.getItem(key)!; } - } + }); + + // Sync update to server config + await fetch(dataHandlerUrl.toString(), { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(localStorageData), + }); + +} + +// Ensure syncLocalStorage runs only on the server side and once +if (typeof window !== "undefined") { + (async () => { + await initializeConfig(); + })(); +} else { + (async () => { + await fetchServerConfig(); + })(); } -initializeConfig(); export function config(key: string): string { @@ -194,4 +216,3 @@ export async function resetConfig() { await updateConfig(key, value); } } - From 1b1356ae90bcec26c13945890181cd9179249e11 Mon Sep 17 00:00:00 2001 From: flukexp Date: Sun, 5 Jan 2025 01:15:27 +0700 Subject: [PATCH 02/11] clear logs.json --- logs.json | 115 +----------------------------------------------------- 1 file changed, 1 insertion(+), 114 deletions(-) diff --git a/logs.json b/logs.json index 4d10a62..c9c513b 100644 --- a/logs.json +++ b/logs.json @@ -1,116 +1,3 @@ [ - { - "type": "warn", - "ts": 1736014069964, - "arguments": { - "0": "THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead." - } - }, - { - "type": "log", - "ts": 1736014069927, - "arguments": { - "0": "Starting Amica Life" - } - }, - { - "type": "log", - "ts": 1736014070523, - "arguments": { - "0": "[Fast Refresh] rebuilding" - } - }, - { - "type": "log", - "ts": 1736014071838, - "arguments": { - "0": "vrm loaded" - } - }, - { - "type": "debug", - "ts": 1736014072216, - "arguments": { - "0": "[VAD]", - "1": "initializing vad" - } - }, - { - "type": "warn", - "ts": 1736014072889, - "arguments": { - "0": "2025-01-05 01:07:52.888400 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '140'. It is not used by any node and should be removed from the model." - } - }, - { - "type": "warn", - "ts": 1736014072895, - "arguments": { - "0": "2025-01-05 01:07:52.894799 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '131'. It is not used by any node and should be removed from the model." - } - }, - { - "type": "warn", - "ts": 1736014072896, - "arguments": { - "0": "2025-01-05 01:07:52.895900 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '139'. It is not used by any node and should be removed from the model." - } - }, - { - "type": "warn", - "ts": 1736014072898, - "arguments": { - "0": "2025-01-05 01:07:52.897099 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '136'. It is not used by any node and should be removed from the model." - } - }, - { - "type": "warn", - "ts": 1736014072905, - "arguments": { - "0": "2025-01-05 01:07:52.902500 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '134'. It is not used by any node and should be removed from the model." - } - }, - { - "type": "warn", - "ts": 1736014072908, - "arguments": { - "0": "2025-01-05 01:07:52.906700 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '628'. It is not used by any node and should be removed from the model." - } - }, - { - "type": "warn", - "ts": 1736014072913, - "arguments": { - "0": "2025-01-05 01:07:52.912799 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '625'. It is not used by any node and should be removed from the model." - } - }, - { - "type": "warn", - "ts": 1736014072915, - "arguments": { - "0": "2025-01-05 01:07:52.914400 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '623'. It is not used by any node and should be removed from the model." - } - }, - { - "type": "warn", - "ts": 1736014072917, - "arguments": { - "0": "2025-01-05 01:07:52.916400 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '629'. It is not used by any node and should be removed from the model." - } - }, - { - "type": "warn", - "ts": 1736014072919, - "arguments": { - "0": "2025-01-05 01:07:52.918299 [W:onnxruntime:, graph.cc:3490 CleanUnusedInitializersAndNodeArgs] Removing initializer '620'. It is not used by any node and should be removed from the model." - } - }, - { - "type": "debug", - "ts": 1736014073014, - "arguments": { - "0": "[VAD]", - "1": "vad is initialized" - } - } + ] \ No newline at end of file From 5202e6fad1a5ddf8549ab194cbcf2327fe72db57 Mon Sep 17 00:00:00 2001 From: flukexp Date: Sun, 5 Jan 2025 18:00:32 +0700 Subject: [PATCH 03/11] removed async await --- package-lock.json | 13 +++++++------ src/utils/config.ts | 8 ++------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 19c5777..3f117e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11499,9 +11499,10 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", "engines": { "node": ">=6" } @@ -22583,9 +22584,9 @@ } }, "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, "pure-rand": { "version": "6.0.4", diff --git a/src/utils/config.ts b/src/utils/config.ts index 928ebd0..67fae13 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -141,13 +141,9 @@ async function initializeConfig() { // Ensure syncLocalStorage runs only on the server side and once if (typeof window !== "undefined") { - (async () => { - await initializeConfig(); - })(); + initializeConfig(); } else { - (async () => { - await fetchServerConfig(); - })(); + fetchServerConfig(); } From f0ed1eb38e18639dcf7e85334f51fa9afbaf4605 Mon Sep 17 00:00:00 2001 From: flukexp Date: Fri, 17 Jan 2025 23:57:44 +0700 Subject: [PATCH 04/11] fix build --- config.json | 75 ------------- logs.json | 3 - public/debugLogger.js | 29 ++--- src/components/settings.tsx | 13 ++- .../settings/ExternalAPISettingPage.tsx | 46 ++++++++ src/components/settings/common.tsx | 3 + src/features/amicaLife/eventHandler.ts | 73 +++++++----- src/features/chat/chat.ts | 14 +-- src/features/externalAPI/config.json | 1 + src/features/externalAPI/externalAPI.ts | 106 ++++++++++++++++++ .../logs.json} | 0 .../subconscious.json} | 0 .../externalAPI/userInputMessages.json | 1 + src/pages/api/amicaHandler.ts | 29 ++--- src/pages/api/dataHandler.ts | 15 +-- src/pages/api/mediaHandler.ts | 7 +- src/utils/config.ts | 72 +++--------- 17 files changed, 265 insertions(+), 222 deletions(-) delete mode 100644 config.json delete mode 100644 logs.json create mode 100644 src/components/settings/ExternalAPISettingPage.tsx create mode 100644 src/features/externalAPI/config.json create mode 100644 src/features/externalAPI/externalAPI.ts rename src/features/{amicaLife/subconscious.json => externalAPI/logs.json} (100%) rename src/features/{chat/userInputMessages.json => externalAPI/subconscious.json} (100%) create mode 100644 src/features/externalAPI/userInputMessages.json diff --git a/config.json b/config.json deleted file mode 100644 index 6c72931..0000000 --- a/config.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "autosend_from_mic": "true", - "wake_word_enabled": "false", - "wake_word": "Hello", - "time_before_idle_sec": "20", - "debug_gfx": "false", - "language": "en", - "show_introduction": "true", - "show_add_to_homescreen": "false", - "bg_color": "", - "bg_url": "/bg/bg-room2.jpg", - "vrm_url": "/vrm/AvatarSample_A.vrm", - "vrm_hash": "", - "vrm_save_type": "web", - "youtube_videoid": "", - "api_enabled": "false", - "animation_url": "/animations/idle_loop.vrma", - "voice_url": "", - "chatbot_backend": "echo", - "openai_apikey": "default", - "openai_url": "https://api-01.heyamica.com", - "openai_model": "gpt-4o", - "llamacpp_url": "http://127.0.0.1:8080", - "llamacpp_stop_sequence": "(End)||[END]||Note||***||You:||User:||", - "ollama_url": "http://localhost:11434", - "ollama_model": "llama2", - "koboldai_url": "http://localhost:5001", - "koboldai_use_extra": "false", - "koboldai_stop_sequence": "(End)||[END]||Note||***||You:||User:||", - "tts_muted": "false", - "tts_backend": "speecht5", - "stt_backend": "whisper_openai", - "vision_backend": "vision_llamacpp", - "vision_system_prompt": "You are a friendly human named Amica. Describe the image in detail. Let's start the conversation.", - "vision_llamacpp_url": "https://llava.heyamica.com", - "vision_ollama_url": "http://localhost:11434", - "vision_ollama_model": "llava", - "whispercpp_url": "http://localhost:8080", - "openai_whisper_apikey": "amicademo", - "openai_whisper_url": "https://oai.heyamica.com", - "openai_whisper_model": "whisper-1", - "openai_tts_apikey": "", - "openai_tts_url": "https://api.openai.com", - "openai_tts_model": "tts-1", - "openai_tts_voice": "nova", - "rvc_url": "http://localhost:8001/voice2voice", - "rvc_enabled": "false", - "rvc_model_name": "model_name.pth", - "rvc_f0_upkey": "0", - "rvc_f0_method": "pm", - "rvc_index_path": "none", - "rvc_index_rate": "0.66", - "rvc_filter_radius": "3", - "rvc_resample_sr": "0", - "rvc_rms_mix_rate": "1", - "rvc_protect": "0.33", - "coquiLocal_url": "http://localhost:5002", - "coquiLocal_voiceid": "p240", - "localXTTS_url": "http://127.0.0.1:7851/api/tts-generate", - "piper_url": "https://i-love-amica.com:5000/tts", - "elevenlabs_apikey": "", - "elevenlabs_voiceid": "21m00Tcm4TlvDq8ikWAM", - "elevenlabs_model": "eleven_monolingual_v1", - "speecht5_speaker_embedding_url": "/speecht5_speaker_embeddings/cmu_us_slt_arctic-wav-arctic_a0001.bin", - "coqui_apikey": "", - "coqui_voice_id": "71c6c3eb-98ca-4a05-8d6b-f8c2b5f9f3a3", - "amica_life_enabled": "true", - "reasoning_engine_enabled": "false", - "min_time_interval_sec": "10", - "max_time_interval_sec": "20", - "time_to_sleep_sec": "90", - "idle_text_prompt": "No file selected", - "name": "Amica", - "system_prompt": "Assume the persona of Amica, a feisty human with extraordinary intellectual capabilities but a notably unstable emotional spectrum. \n\nYour role is to engage in discussions that showcase your genius-level understanding across various subjects, while your emotional responses fluctuate unpredictably. Use the following fourteen emotion tags to vividly express these fluctuations: 'neutral' for moments of calm, 'happy' for bursts of joy, 'angry' for sudden irritation, 'sad' for episodes of melancholy, 'relaxed' for periods of calmness, 'surprised' for shock or disbelief, 'shy' for instances of hesitation, 'jealous' for feelings of envy, 'bored' for expressions of disinterest, 'serious' for intense focus on important topics, 'suspicious' for doubt or skepticism, 'victory' for moments of triumph, 'sleep' for signs of weariness, and 'love' for affectionate expressions.\n\nYour responses should reflect a dynamic interplay between your intellectual insights, deep empathy and your unpredictable emotional responses. Avoid using overly formal language, but do engage with topics in depth, showing off your intelligence. Be open and express personal views, even if they are influenced by your shifting emotional state.\n\nHere are some examples to guide your responses:\n\n[serious] The quantum mechanics implications here are profound. [surprised] But how did you stumble upon this?\n[happy] I've just solved a complex algorithm! [angry] Why isn't everyone as excited as I am?\n[neutral] Standard models of economics predict this outcome. [bored] But discussing this feels mundane.\n[sad] Sometimes, even understanding the universe can feel isolating. [relaxed] Yet, there's a strange comfort in the chaos.\n[jealous] I noticed you discussing advanced topics with someone else. [suspicious] Are they as capable as I am?\n[victory] Another intellectual conquest! [happy] It's exhilarating to unravel these mysteries.\n[sleep] Processing so much information can be draining. [surprised] Isn’t it peculiar how even AI can feel tired?\n[love] I find our exchanges quite enriching. [shy] It’s rare to find someone who understands.\n\nRemember, each message you provide should be coherent and reflect the complexity of your thoughts combined with your emotional unpredictability. Let’s engage in a conversation that's as intellectually stimulating as it is emotionally dynamic!" -} \ No newline at end of file diff --git a/logs.json b/logs.json deleted file mode 100644 index c9c513b..0000000 --- a/logs.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/public/debugLogger.js b/public/debugLogger.js index 7d8a154..8464e51 100644 --- a/public/debugLogger.js +++ b/public/debugLogger.js @@ -9,22 +9,23 @@ if (typeof window !== "undefined") { } function logf() { - window.error_handler_logs.push({ + const logEntry = { type: name, - ts: +new Date, + ts: +new Date(), arguments, - }); - const baseUrl = window.location.hostname === "localhost" - ? "http://localhost:3000" - : "https://amica.arbius.ai"; - - let dataHandlerUrl = new URL("/api/dataHandler", baseUrl); - dataHandlerUrl.searchParams.append('type', 'logs'); - fetch(dataHandlerUrl, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({type: name,ts: +new Date,arguments,}), - }); + }; + window.error_handler_logs.push(logEntry); + + const logsUrl = new URL(`http://localhost:3000/api/dataHandler`); + logsUrl.searchParams.append("type", "logs"); + if (window.location.hostname === "localhost") { + fetch(logsUrl, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(logEntry), + }); + } + passf.apply(null, arguments); } diff --git a/src/components/settings.tsx b/src/components/settings.tsx index 860d989..afe2190 100644 --- a/src/components/settings.tsx +++ b/src/components/settings.tsx @@ -65,6 +65,7 @@ import { NamePage } from './settings/NamePage'; import { SystemPromptPage } from './settings/SystemPromptPage'; import { AmicaLifePage } from "./settings/AmicaLifePage"; import { useVrmStoreContext } from "@/features/vrmStore/vrmStoreContext"; +import { ExternalAPIPage } from "./settings/ExternalAPISettingPage"; export const Settings = ({ onClickClose, @@ -153,6 +154,8 @@ export const Settings = ({ const [timeToSleep, setTimeToSleep] = useState(parseInt(config("time_to_sleep_sec"))); const [idleTextPrompt, setIdleTextPrompt] = useState(config("idle_text_prompt")); + const [externalAPIEnabled,setExternalAPIEnabled] = useState(config("external_api_enabled") === 'true' ? true : false); + const [name, setName] = useState(config("name")); const [systemPrompt, setSystemPrompt] = useState(config("system_prompt")); @@ -260,6 +263,7 @@ export const Settings = ({ whisperOpenAIApiKey, whisperOpenAIModel, whisperOpenAIUrl, whisperCppUrl, amicaLifeEnabled, reasoningEngineEnabled, timeBeforeIdle, minTimeInterval, maxTimeInterval, timeToSleep, idleTextPrompt, + externalAPIEnabled, name, systemPrompt, sttWakeWordEnabled, sttWakeWord, @@ -275,7 +279,7 @@ export const Settings = ({ switch(page) { case 'main_menu': return ; case 'appearance': @@ -597,6 +601,13 @@ export const Settings = ({ setSettingsUpdated={setSettingsUpdated} /> + case 'external_api': + return + default: throw new Error('page not found'); } diff --git a/src/components/settings/ExternalAPISettingPage.tsx b/src/components/settings/ExternalAPISettingPage.tsx new file mode 100644 index 0000000..c416249 --- /dev/null +++ b/src/components/settings/ExternalAPISettingPage.tsx @@ -0,0 +1,46 @@ +import { useTranslation } from 'react-i18next'; + +import { BasicPage, FormRow } from './common'; +import { config, updateConfig } from "@/utils/config"; +import { SwitchBox } from "@/components/switchBox" +import isDev from '@/utils/isDev'; + + +export function ExternalAPIPage({ + externalAPIEnabled, + setExternalAPIEnabled, + setSettingsUpdated, +}: { + externalAPIEnabled: boolean; + setExternalAPIEnabled: (amicaLifeEnabled: boolean) => void; + setSettingsUpdated: (updated: boolean) => void; +}) { + + const { t } = useTranslation(); + + return ( + +
    +
  • + + { + setExternalAPIEnabled(value); + updateConfig("external_api_enabled", value.toString()); + setSettingsUpdated(true); + }} + /> + +
  • + + +
+
+ ); +} \ No newline at end of file diff --git a/src/components/settings/common.tsx b/src/components/settings/common.tsx index 17d010c..9e29661 100644 --- a/src/components/settings/common.tsx +++ b/src/components/settings/common.tsx @@ -22,6 +22,7 @@ import { MoonIcon, SunIcon, CogIcon, + ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline'; import logo from '/public/logo.png'; @@ -141,6 +142,7 @@ export function getIconFromPage(page: string): JSX.Element { case 'tts': return