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