diff --git a/src/App.tsx b/src/App.tsx
index acec25d..803b84c 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -2,6 +2,7 @@ import { Routes, Route, Link } from 'react-router'
import './App.css'
import TemplatePage from './pages/TemplatePage/Template.tsx'
import Home from './pages/Home/Home.tsx'
+import Robot from './pages/Robot/Robot.tsx';
function App(){
return (
@@ -13,6 +14,7 @@ function App(){
} />
} />
+ } />
diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx
index 71f6b96..cb70de0 100644
--- a/src/pages/Home/Home.tsx
+++ b/src/pages/Home/Home.tsx
@@ -11,6 +11,7 @@ function Home() {
+ Robot Interaction →
Template →
diff --git a/src/pages/Robot/Robot.tsx b/src/pages/Robot/Robot.tsx
new file mode 100644
index 0000000..0038dd9
--- /dev/null
+++ b/src/pages/Robot/Robot.tsx
@@ -0,0 +1,94 @@
+import { useState, useEffect, useRef } from 'react'
+
+export default function Robot() {
+ const [message, setMessage] = useState('');
+
+ const [listening, setListening] = useState(false);
+ const [conversation, setConversation] = useState<{"role": "user" | "assistant", "content": string}[]>([])
+ const conversationRef = useRef(null);
+ const [conversationIndex, setConversationIndex] = useState(0);
+
+ const sendMessage = async () => {
+ try {
+ const response = await fetch("http://localhost:8000/message", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ message }),
+ });
+ const data = await response.json();
+ console.log(data);
+ } catch (error) {
+ console.error("Error sending message: ", error);
+ }
+ };
+
+ useEffect(() => {
+ const eventSource = new EventSource("http://localhost:8000/sse");
+
+ eventSource.onmessage = (event) => {
+ try {
+ const data = JSON.parse(event.data);
+ if ("voice_active" in data) setListening(data.voice_active);
+ if ("speech" in data) setConversation(conversation => [...conversation, {"role": "user", "content": data.speech}]);
+ if ("llm_response" in data) setConversation(conversation => [...conversation, {"role": "assistant", "content": data.llm_response}]);
+ } catch {
+ console.log("Unparsable SSE message:", event.data);
+ }
+ };
+
+ return () => {
+ eventSource.close();
+ };
+ }, [conversationIndex]);
+
+ useEffect(() => {
+ if (!conversationRef || !conversationRef.current) return;
+ conversationRef.current.scrollTop = conversationRef.current.scrollHeight;
+ }, [conversation]);
+
+ return (
+ <>
+ Robot interaction
+ Force robot speech
+
+ setMessage(e.target.value)}
+ onKeyDown={(e) => e.key === "Enter" && sendMessage().then(() => setMessage(""))}
+ placeholder="Enter a message"
+ />
+
+
+
+
Conversation
+
Listening {listening ? "🟢" : "🔴"}
+
+ {conversation.map((item, i) => (
+
{item["content"]}
+ ))}
+
+
+
+
+
+
+ >
+ );
+}