parent
a894548c78
commit
742a52d293
10 changed files with 353 additions and 141 deletions
Binary file not shown.
Binary file not shown.
@ -0,0 +1,124 @@ |
||||
import { createContext, useContext, useRef, useState } from "react"; |
||||
import { sendChatMessage } from "./chat"; |
||||
import { textToSpeech } from "./tts"; |
||||
|
||||
const chatContext=createContext(); |
||||
|
||||
export const Status= { |
||||
IDLE: 'idle', |
||||
|
||||
PROCESSING_TEXT: 'processing', |
||||
PROCESSING_AUDIO: 'processing_audio', |
||||
|
||||
AUDIO_ENDED: 'audio_ended', |
||||
|
||||
ERROR: 'error', |
||||
SUCCESS: 'success' |
||||
}; |
||||
|
||||
export function ChatProvider({children}){ |
||||
|
||||
const [history, setHistory] = useState([]); |
||||
const [status, setStatus] = useState(Status.IDLE); |
||||
|
||||
const [audioOutput, setAudioOutput] = useState(true); |
||||
|
||||
const refAudio=useRef(); |
||||
|
||||
|
||||
|
||||
function addMessage(message) { |
||||
setHistory(prev => [...prev, message]); |
||||
} |
||||
function reset() { |
||||
setHistory([]); |
||||
if(refAudio.current) { |
||||
refAudio.current.pause(); // Stop any currently playing audio |
||||
refAudio.current = null; // Reset the audio reference |
||||
} |
||||
} |
||||
|
||||
function sendMessage(message, force_no_audio=false) { |
||||
console.log('Sending chat message:', message); |
||||
setStatus(Status.PROCESSING_TEXT); |
||||
|
||||
let historyCopy = [...history]; |
||||
if(message && message.trim() !== '') { |
||||
historyCopy=[...historyCopy, { role: 'user', content: message }]; |
||||
addMessage({ |
||||
role: 'user', |
||||
content: message |
||||
}); |
||||
} |
||||
|
||||
sendChatMessage(historyCopy).then(response => { |
||||
|
||||
|
||||
addMessage({ |
||||
role: 'assistant', |
||||
content: response.output_text, |
||||
prompt: response.prompt |
||||
}); |
||||
|
||||
|
||||
if(response.output_text && (!force_no_audio && audioOutput)){ |
||||
setStatus(Status.PROCESSING_AUDIO); |
||||
textToSpeech(response.output_text).then(audioUrl => { |
||||
setStatus(Status.SUCCESS); |
||||
|
||||
|
||||
if(refAudio.current) { |
||||
refAudio.current.pause(); // Stop any currently playing audio |
||||
} |
||||
|
||||
// play the audio |
||||
const audio = new Audio(audioUrl); |
||||
audio.play().catch(error => { |
||||
console.error("Audio playback error:", error); |
||||
setStatus(Status.ERROR); |
||||
}); |
||||
|
||||
audio.onended = () => { |
||||
setStatus(Status.AUDIO_ENDED); |
||||
} |
||||
|
||||
refAudio.current = audio; // Store the new audio reference |
||||
|
||||
}); |
||||
}else{ |
||||
setStatus(Status.SUCCESS); |
||||
} |
||||
|
||||
}).catch(error => { |
||||
console.error("Chat error:", error); |
||||
setStatus(Status.ERROR); |
||||
}); |
||||
|
||||
|
||||
} |
||||
|
||||
|
||||
return ( |
||||
<chatContext.Provider value={{ |
||||
history, status, setStatus, reset, sendMessage, setAudioOutput, audioOutput, |
||||
stop: () => { |
||||
if(refAudio.current) { |
||||
refAudio.current.pause(); // Stop any currently playing audio |
||||
refAudio.current = null; // Reset the audio reference |
||||
} |
||||
setStatus(Status.IDLE); |
||||
} |
||||
}}> |
||||
{children} |
||||
</chatContext.Provider> |
||||
); |
||||
} |
||||
|
||||
|
||||
export function useChat(){ |
||||
const context=useContext(chatContext); |
||||
if(!context){ |
||||
throw new Error("useChat must be used within a ChatProvider"); |
||||
} |
||||
return context; |
||||
} |
||||
Loading…
Reference in new issue