import { Readable } from "node:stream"; async function relayError(response, res) { const contentType = response.headers.get("content-type") ?? "application/json"; const rawBody = await response.text(); res.status(response.status); res.setHeader("content-type", contentType); res.send(rawBody); } export function createChatController({ openAiService, requestNormalizationService, responseNormalizationService }) { return async function chatController(req, res, next) { try { const { normalizedBody, responseContext } = await requestNormalizationService.normalize(req.body); const upstreamResponse = await openAiService.createChatCompletion(normalizedBody); if (!upstreamResponse.ok) { await relayError(upstreamResponse, res); return; } if (normalizedBody.stream) { res.status(upstreamResponse.status); res.setHeader("content-type", upstreamResponse.headers.get("content-type") ?? "text/event-stream"); Readable.fromWeb(upstreamResponse.body).pipe(res); return; } const responseJson = await upstreamResponse.json(); const publicBaseUrl = `${req.protocol}://${req.get("host")}`; const normalizedResponse = responseNormalizationService.normalize(responseJson, { publicBaseUrl, audioFormat: responseContext.audioFormat, exposeMediaUrls: responseContext.exposeMediaUrls }); res.status(upstreamResponse.status).json(normalizedResponse); } catch (error) { next(error); } }; }