refactor: separate voice controls and configurable Realtime connections

This commit is contained in:
Sameh Khamis committed 2026-09-13 21:54:51 -07:00
1 parent 0ba00f4662
commit 1a1cbadf5b
21 files changed
+3126 -2793

No files matched your search

+2 -1
View File
@@ -12,6 +12,7 @@ import { createRealtimeTokenHandler } from './openai/realtime.js';
function openAiRealtimeProxy({
sourceRoot = defaultSourceRoot,
annotationGuidance,
realtime = {},
} = {}) {
function install(middlewares) {
middlewares.use('/api/openai/hud-summary', handleHudSummary);
@@ -23,7 +24,7 @@ function openAiRealtimeProxy({
middlewares.use(
'/api/realtime/token',
createRealtimeTokenHandler({ annotationGuidance }),
createRealtimeTokenHandler({ ...realtime, annotationGuidance }),
);
}
+24 -15
View File
@@ -14,8 +14,15 @@ import {
import { realtimeInstructions } from './instructions.js';
import { GEV_REALTIME_TOOLS } from './tools.js';
function createRealtimeTokenHandler({ annotationGuidance } = {}) {
function createRealtimeTokenHandler({
annotationGuidance,
endpoint = 'https://api.openai.com/v1/realtime/client_secrets',
fetchImpl = (...args) => fetch(...args),
resolveApiKey = () => process.env.OPENAI_API_KEY,
models = {},
} = {}) {
return async (req, res) => {
res.setHeader('Cache-Control', 'no-store');
if (req.method !== 'GET' && req.method !== 'POST') {
res.statusCode = 405;
res.setHeader('Content-Type', 'application/json');
@@ -26,7 +33,7 @@ function createRealtimeTokenHandler({ annotationGuidance } = {}) {
// Opt-in per-IP throttle (GEV_RATELIMIT_OPENAI_PER_MIN). No-op when unset.
if (!enforceOptInRateLimit(openAiRateLimiter(), req, res)) return;
const apiKey = process.env.OPENAI_API_KEY;
const apiKey = resolveApiKey();
if (!apiKey) {
res.statusCode = 503;
res.setHeader('Content-Type', 'application/json');
@@ -52,9 +59,12 @@ function createRealtimeTokenHandler({ annotationGuidance } = {}) {
const tier = resolveVoiceModel(requestedTier).tier;
const model =
tier === 'mini'
? process.env.OPENAI_REALTIME_MODEL_MINI ||
? models.mini ||
process.env.OPENAI_REALTIME_MODEL_MINI ||
OPENAI_REALTIME_MODEL_MINI_DEFAULT
: process.env.OPENAI_REALTIME_MODEL || OPENAI_REALTIME_MODEL_DEFAULT;
: models.standard ||
process.env.OPENAI_REALTIME_MODEL ||
OPENAI_REALTIME_MODEL_DEFAULT;
const voice =
process.env.OPENAI_REALTIME_VOICE || OPENAI_REALTIME_VOICE_DEFAULT;
const effort =
@@ -109,18 +119,17 @@ function createRealtimeTokenHandler({ annotationGuidance } = {}) {
};
try {
const response = await fetch(
'https://api.openai.com/v1/realtime/client_secrets',
{
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'OpenAI-Safety-Identifier': 'gev-local-dev',
},
body: JSON.stringify(sessionConfig),
const response = await fetchImpl(endpoint, {
method: 'POST',
redirect: 'error',
signal: AbortSignal.timeout(30_000),
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'OpenAI-Safety-Identifier': 'gev-local-dev',
},
);
body: JSON.stringify(sessionConfig),
});
const body = await response.text();
res.statusCode = response.status;
res.setHeader(