| import { Buffer } from "node:buffer"; | |
| import { isDataUrl, parseDataUrl } from "../utils/dataUrl.js"; | |
| import { audioMimeType, extensionFromMimeType } from "../utils/mediaTypes.js"; | |
| function mediaUrl(publicBaseUrl, mediaId) { | |
| return `${publicBaseUrl}/v1/media/${mediaId}`; | |
| } | |
| export function createResponseNormalizationService({ mediaStore }) { | |
| return { | |
| normalize(body, { publicBaseUrl, audioFormat = "mp3", exposeMediaUrls = true } = {}) { | |
| if (!body || !exposeMediaUrls) { | |
| return body; | |
| } | |
| const normalized = structuredClone(body); | |
| const proxyMedia = []; | |
| for (const [choiceIndex, choice] of (normalized.choices ?? []).entries()) { | |
| const message = choice?.message; | |
| if (!message) { | |
| continue; | |
| } | |
| if (message.audio?.data) { | |
| const format = message.audio.format ?? audioFormat; | |
| const media = mediaStore.save({ | |
| buffer: Buffer.from(message.audio.data, "base64"), | |
| mimeType: audioMimeType(format), | |
| extension: format | |
| }); | |
| message.audio.format = format; | |
| message.audio.url = mediaUrl(publicBaseUrl, media.id); | |
| proxyMedia.push({ | |
| choice: choiceIndex, | |
| type: "audio", | |
| url: message.audio.url | |
| }); | |
| } | |
| if (!Array.isArray(message.content)) { | |
| continue; | |
| } | |
| for (const [partIndex, part] of message.content.entries()) { | |
| const imageUrl = part?.image_url?.url; | |
| if (!isDataUrl(imageUrl)) { | |
| continue; | |
| } | |
| const parsed = parseDataUrl(imageUrl); | |
| if (!parsed) { | |
| continue; | |
| } | |
| const media = mediaStore.save({ | |
| buffer: Buffer.from(parsed.base64, "base64"), | |
| mimeType: parsed.mimeType, | |
| extension: extensionFromMimeType(parsed.mimeType) | |
| }); | |
| part.image_url.proxy_url = mediaUrl(publicBaseUrl, media.id); | |
| proxyMedia.push({ | |
| choice: choiceIndex, | |
| part: partIndex, | |
| type: "image", | |
| url: part.image_url.proxy_url | |
| }); | |
| } | |
| } | |
| if (proxyMedia.length > 0) { | |
| normalized.proxy = { | |
| media: proxyMedia | |
| }; | |
| } | |
| return normalized; | |
| } | |
| }; | |
| } | |