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}/>;
}