import {useState, useRef, useEffect} from 'react'; import useLoginToken from "../Hooks/useLoginToken.tsx"; import { z } from 'zod/v4'; function SessionActive({stopSession} : {stopSession: () => void}) { return } function SessionStopped({startSession} : {startSession: () => void}) { return } function SessionControl( { isSessionActive, startSession, stopSession }: { isSessionActive: boolean, startSession : () => void, stopSession : () => void }) { return (isSessionActive ? : ); } const EphemeralTokenResponse = z.object({ ephemeralToken: z.string(), expiresAt: z.number(), }); export function ChatControl() { const { token } = useLoginToken(); const [isSessionActive, setSessionActive] = useState(false); const [dataChannel, setDataChannel] = useState(null); const audioElement = useRef(null); const peerConnection = useRef(null); async function StartSession() { // Get a session token for OpenAI Realtime API const response = await fetch('ephemeral_token', { method: "GET", headers: { Authorization: `Bearer ${token}asdasd` }, }); if (!response.ok) { throw new Error(response.statusText); } const responseJson:unknown = await response.json(); const parsedToken = EphemeralTokenResponse.parse(responseJson); const ephemeralToken = parsedToken.ephemeralToken; // Create a peer connection const pc = new RTCPeerConnection(); // Set up to play remote audio from the model audioElement.current = document.createElement("audio"); audioElement.current.autoplay = true; pc.ontrack = (e) => { if (audioElement.current !== null) { audioElement.current.srcObject = e.streams[0]; } } // Add local audio track for microphone input in the browser const microphoneStream = await navigator.mediaDevices.getUserMedia({audio: true}); pc.addTrack(microphoneStream.getTracks()[0]); // Set up data channel for sending and receving events const dc = pc.createDataChannel("oai-events"); setDataChannel(dc) // Start the session using the Session Description Protocol (SDP) const offer = await pc.createOffer(); await pc.setLocalDescription(offer); // Start Realtime Session const baseUrl = "https://api.openai.com/v1/realtime"; const model = "gpt-4o-realtime-preview"; const sdpResponse = await fetch(`${baseUrl}?model=${model}`, { method: "POST", body: offer.sdp, headers: { Authorization: `Bearer ${ephemeralToken}`, "Content-Type": "application/sdp", }, }); const answer:RTCSessionDescriptionInit = { type: "answer", sdp: await sdpResponse.text(), }; await pc.setRemoteDescription(answer); peerConnection.current = pc; } function stopSession() { if (dataChannel) { dataChannel.close(); setDataChannel(null); } if (peerConnection.current !== null) { peerConnection.current.close(); peerConnection.current = null; } setSessionActive(false); } useEffect(() => { if (dataChannel) { dataChannel.addEventListener("open", () => { setSessionActive(true); }); } }, [dataChannel]) return void StartSession()} stopSession={stopSession}/>; }