File size: 2,327 Bytes
e43a4a9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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;
    }
  };
}