modelfusion 0.129.1 → 0.130.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +29 -20
  3. package/core/api/postToApi.cjs +2 -2
  4. package/core/api/postToApi.js +2 -2
  5. package/model-function/generate-image/generateImage.cjs +1 -1
  6. package/model-function/generate-image/generateImage.js +1 -1
  7. package/model-function/generate-text/prompt-template/ContentPart.cjs +1 -9
  8. package/model-function/generate-text/prompt-template/ContentPart.d.ts +3 -4
  9. package/model-function/generate-text/prompt-template/ContentPart.js +0 -7
  10. package/model-function/generate-transcription/TranscriptionModel.d.ts +6 -2
  11. package/model-function/generate-transcription/generateTranscription.cjs +4 -3
  12. package/model-function/generate-transcription/generateTranscription.d.ts +16 -10
  13. package/model-function/generate-transcription/generateTranscription.js +4 -3
  14. package/model-provider/elevenlabs/ElevenLabsSpeechModel.cjs +1 -1
  15. package/model-provider/elevenlabs/ElevenLabsSpeechModel.js +1 -1
  16. package/model-provider/llamacpp/LlamaCppBakLLaVA1PromptTemplate.cjs +5 -2
  17. package/model-provider/llamacpp/LlamaCppBakLLaVA1PromptTemplate.js +6 -3
  18. package/model-provider/lmnt/LmntSpeechModel.cjs +1 -1
  19. package/model-provider/lmnt/LmntSpeechModel.js +1 -1
  20. package/model-provider/ollama/OllamaChatPromptTemplate.cjs +2 -1
  21. package/model-provider/ollama/OllamaChatPromptTemplate.js +3 -2
  22. package/model-provider/openai/OpenAIChatMessage.cjs +2 -2
  23. package/model-provider/openai/OpenAIChatMessage.js +2 -2
  24. package/model-provider/openai/OpenAITranscriptionModel.cjs +10 -7
  25. package/model-provider/openai/OpenAITranscriptionModel.d.ts +10 -7
  26. package/model-provider/openai/OpenAITranscriptionModel.js +10 -7
  27. package/model-provider/whispercpp/WhisperCppTranscriptionModel.cjs +9 -4
  28. package/model-provider/whispercpp/WhisperCppTranscriptionModel.d.ts +10 -7
  29. package/model-provider/whispercpp/WhisperCppTranscriptionModel.js +9 -4
  30. package/package.json +1 -1
  31. package/util/SimpleWebSocket.cjs +15 -8
  32. package/util/SimpleWebSocket.js +15 -8
  33. package/util/audio/AudioMimeType.cjs +2 -0
  34. package/util/audio/AudioMimeType.d.ts +1 -0
  35. package/util/audio/AudioMimeType.js +1 -0
  36. package/util/audio/getAudioFileExtension.cjs +29 -0
  37. package/util/audio/getAudioFileExtension.d.ts +1 -0
  38. package/util/audio/getAudioFileExtension.js +25 -0
  39. package/util/audio/index.cjs +18 -0
  40. package/util/audio/index.d.ts +2 -0
  41. package/util/audio/index.js +2 -0
  42. package/util/detectRuntime.cjs +21 -0
  43. package/util/detectRuntime.d.ts +1 -0
  44. package/util/detectRuntime.js +17 -0
  45. package/util/format/DataContent.cjs +27 -0
  46. package/util/format/DataContent.d.ts +7 -0
  47. package/util/format/DataContent.js +22 -0
  48. package/util/{UInt8Utils.cjs → format/UInt8Utils.cjs} +1 -11
  49. package/util/{UInt8Utils.d.ts → format/UInt8Utils.d.ts} +0 -1
  50. package/util/{UInt8Utils.js → format/UInt8Utils.js} +0 -9
  51. package/util/format/index.cjs +17 -0
  52. package/util/format/index.d.ts +1 -0
  53. package/util/format/index.js +1 -0
  54. package/util/index.cjs +2 -0
  55. package/util/index.d.ts +2 -0
  56. package/util/index.js +2 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.130.1 - 2024-01-22
4
+
5
+ ### Fixed
6
+
7
+ - Duplex speech streaming works in Vercel Edge Functions.
8
+
9
+ ## v0.130.0 - 2024-01-21
10
+
11
+ ### Changed
12
+
13
+ - **breaking change**: updated `generateTranscription` interface. The function now takes a `mimeType` and `audioData` (base64-encoded string, `Uint8Array`, `Buffer` or `ArrayBuffer`). Example:
14
+
15
+ ```ts
16
+ import { generateTranscription, openai } from "modelfusion";
17
+ import fs from "node:fs";
18
+
19
+ const transcription = await generateTranscription({
20
+ model: openai.Transcriber({ model: "whisper-1" }),
21
+ mimeType: "audio/mp3",
22
+ audioData: await fs.promises.readFile("data/test.mp3"),
23
+ });
24
+ ```
25
+
26
+ - Images in instruction and chat prompts can be `Buffer` or `ArrayBuffer` instances (in addition to base64-encoded strings and `Uint8Array` instances).
27
+
3
28
  ## v0.129.0 - 2024-01-20
4
29
 
5
30
  ### Changed
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
  - **Vendor-neutral**: ModelFusion is a non-commercial open source project that is community-driven. You can use it with any supported provider.
18
18
  - **Multi-modal**: ModelFusion supports a wide range of models including text generation, image generation, vision, text-to-speech, speech-to-text, and embedding models.
19
19
  - **Type inference and validation**: ModelFusion infers TypeScript types wherever possible and validates model responses.
20
- - **Observability and logging**: ModelFusion provides an observer framework and out-of-the-box logging support.
20
+ - **Observability and logging**: ModelFusion provides an observer framework and logging support.
21
21
  - **Resilience and robustness**: ModelFusion ensures seamless operation through automatic retries, throttling, and error handling mechanisms.
22
22
  - **Built for production**: ModelFusion is fully tree-shakeable, can be used in serverless environments, and only uses a minimal set of dependencies.
23
23
 
@@ -89,13 +89,16 @@ import { readFileSync } from "fs";
89
89
  const image = readFileSync("./image.png");
90
90
 
91
91
  const textStream = await streamText({
92
- model: openai.ChatTextGenerator({ model: "gpt-4-vision-preview" }),
93
- prompt: [
94
- openai.ChatMessage.user([
95
- { type: "text", text: "Describe the image in detail:" },
92
+ model: openai
93
+ .ChatTextGenerator({ model: "gpt-4-vision-preview" })
94
+ .withInstructionPrompt(),
95
+
96
+ prompt: {
97
+ instruction: [
98
+ { type: "text", text: "Describe the image in detail." },
96
99
  { type: "image", image, mimeType: "image/png" },
97
- ]),
98
- ],
100
+ ],
101
+ },
99
102
  });
100
103
 
101
104
  for await (const textPart of textStream) {
@@ -269,13 +272,12 @@ Transcribe speech (audio) data into text. Also called speech-to-text (STT).
269
272
 
270
273
  ```ts
271
274
  import { generateTranscription, openai } from "modelfusion";
275
+ import fs from "node:fs";
272
276
 
273
277
  const transcription = await generateTranscription({
274
278
  model: openai.Transcriber({ model: "whisper-1" }),
275
- data: {
276
- type: "mp3",
277
- data: await fs.promises.readFile("data/test.mp3"),
278
- },
279
+ mimeType: "audio/mp3",
280
+ audioData: await fs.promises.readFile("data/test.mp3"),
279
281
  });
280
282
  ```
281
283
 
@@ -510,14 +512,16 @@ const textStream = await streamText({
510
512
  You an use prompt templates with image models as well, e.g. to use a basic text prompt. It is available as a shorthand method:
511
513
 
512
514
  ```ts
513
- const image = await generateImage(
514
- stability
515
+ const image = await generateImage({
516
+ model: stability
515
517
  .ImageGenerator({
516
518
  //...
517
519
  })
518
520
  .withTextPrompt(),
519
- "the wicked witch of the west in the style of early 19th century painting"
520
- );
521
+
522
+ prompt:
523
+ "the wicked witch of the west in the style of early 19th century painting",
524
+ });
521
525
  ```
522
526
 
523
527
  | Prompt Template | Text Prompt |
@@ -551,14 +555,18 @@ for (const choice of (rawResponse as OpenAICompletionResponse).choices) {
551
555
 
552
556
  ### Logging and Observability
553
557
 
554
- ModelFusion provides an [observer framework](https://modelfusion.dev/guide/util/observer) and [out-of-the-box logging support](https://modelfusion.dev/guide/util/logging). You can easily trace runs and call hierarchies, and you can add your own observers.
558
+ ModelFusion provides an [observer framework](https://modelfusion.dev/guide/util/observer) and [logging support](https://modelfusion.dev/guide/util/logging). You can easily trace runs and call hierarchies, and you can add your own observers.
555
559
 
556
- #### Global Logging Example
560
+ #### Enabling Logging on a Function Call
557
561
 
558
562
  ```ts
559
- import { modelfusion } from "modelfusion";
563
+ import { generateText, openai } from "modelfusion";
560
564
 
561
- modelfusion.setLogFormat("detailed-object"); // log full events
565
+ const text = await generateText({
566
+ model: openai.CompletionTextGenerator({ model: "gpt-3.5-turbo-instruct" }),
567
+ prompt: "Write a short story about a robot learning to love:\n\n",
568
+ logging: "detailed-object",
569
+ });
562
570
  ```
563
571
 
564
572
  ## Documentation
@@ -637,12 +645,13 @@ Ask questions about a PDF document and get answers from the document.
637
645
 
638
646
  ### [Next.js / ModelFusion Demos](https://github.com/lgrammel/modelfusion/tree/main/examples/nextjs)
639
647
 
640
- > _Next.js app_, _image generation_, _transcription_, _OpenAI_, _Stability AI_
648
+ > _Next.js app_, _image generation_, _transcription_, _structure streaming_, _OpenAI_, _Stability AI_, _Ollama_
641
649
 
642
650
  Examples of using ModelFusion with Next.js 14 (App Router):
643
651
 
644
652
  - image generation
645
653
  - voice recording & transcription
654
+ - structure streaming (client-side)
646
655
 
647
656
  ### [Duplex Speech Streaming (using Vite/React & ModelFusion Server/Fastify)](https://github.com/lgrammel/modelfusion/tree/main/examples/speech-streaming-vite-react-fastify)
648
657
 
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.postToApi = exports.postJsonToApi = exports.createAudioMpegResponseHandler = exports.createTextResponseHandler = exports.createJsonResponseHandler = exports.createTextErrorResponseHandler = exports.createJsonErrorResponseHandler = void 0;
4
- const UInt8Utils_js_1 = require("../../util/UInt8Utils.cjs");
4
+ const DataContent_js_1 = require("../../util/format/DataContent.cjs");
5
5
  const parseJSON_js_1 = require("../schema/parseJSON.cjs");
6
6
  const ApiCallError_js_1 = require("./ApiCallError.cjs");
7
7
  const createJsonErrorResponseHandler = ({ errorSchema, errorToMessage, isRetryable, }) => async ({ response, url, requestBodyValues }) => {
@@ -87,7 +87,7 @@ const createAudioMpegResponseHandler = () => async ({ response, url, requestBody
87
87
  requestBodyValues,
88
88
  });
89
89
  }
90
- return (0, UInt8Utils_js_1.toUint8Array)(await response.arrayBuffer());
90
+ return (0, DataContent_js_1.convertDataContentToUint8Array)(await response.arrayBuffer());
91
91
  };
92
92
  exports.createAudioMpegResponseHandler = createAudioMpegResponseHandler;
93
93
  const postJsonToApi = async ({ url, headers, body, failedResponseHandler, successfulResponseHandler, abortSignal, }) => (0, exports.postToApi)({
@@ -1,4 +1,4 @@
1
- import { toUint8Array } from "../../util/UInt8Utils.js";
1
+ import { convertDataContentToUint8Array } from "../../util/format/DataContent.js";
2
2
  import { parseJSON, safeParseJSON } from "../schema/parseJSON.js";
3
3
  import { ApiCallError } from "./ApiCallError.js";
4
4
  export const createJsonErrorResponseHandler = ({ errorSchema, errorToMessage, isRetryable, }) => async ({ response, url, requestBodyValues }) => {
@@ -80,7 +80,7 @@ export const createAudioMpegResponseHandler = () => async ({ response, url, requ
80
80
  requestBodyValues,
81
81
  });
82
82
  }
83
- return toUint8Array(await response.arrayBuffer());
83
+ return convertDataContentToUint8Array(await response.arrayBuffer());
84
84
  };
85
85
  export const postJsonToApi = async ({ url, headers, body, failedResponseHandler, successfulResponseHandler, abortSignal, }) => postToApi({
86
86
  url,
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateImage = void 0;
4
- const UInt8Utils_js_1 = require("../../util/UInt8Utils.cjs");
4
+ const UInt8Utils_js_1 = require("../../util/format/UInt8Utils.cjs");
5
5
  const executeStandardCall_js_1 = require("../executeStandardCall.cjs");
6
6
  async function generateImage({ model, prompt, fullResponse, ...options }) {
7
7
  const callResponse = await (0, executeStandardCall_js_1.executeStandardCall)({
@@ -1,4 +1,4 @@
1
- import { base64ToUint8Array } from "../../util/UInt8Utils.js";
1
+ import { base64ToUint8Array } from "../../util/format/UInt8Utils.js";
2
2
  import { executeStandardCall } from "../executeStandardCall.js";
3
3
  export async function generateImage({ model, prompt, fullResponse, ...options }) {
4
4
  const callResponse = await executeStandardCall({
@@ -1,15 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateContentIsString = exports.getImageAsBase64 = void 0;
4
- const UInt8Utils_js_1 = require("../../../util/UInt8Utils.cjs");
3
+ exports.validateContentIsString = void 0;
5
4
  const InvalidPromptError_js_1 = require("./InvalidPromptError.cjs");
6
- function getImageAsBase64(image) {
7
- if (typeof image === "string") {
8
- return image;
9
- }
10
- return (0, UInt8Utils_js_1.uint8ArrayToBase64)(image);
11
- }
12
- exports.getImageAsBase64 = getImageAsBase64;
13
5
  function validateContentIsString(content, prompt) {
14
6
  if (typeof content !== "string") {
15
7
  throw new InvalidPromptError_js_1.InvalidPromptError("Only text prompts are are supported by this prompt template.", prompt);
@@ -1,4 +1,4 @@
1
- /// <reference types="node" />
1
+ import { DataContent } from "../../../util/format/DataContent.js";
2
2
  export interface TextPart {
3
3
  type: "text";
4
4
  /**
@@ -9,9 +9,9 @@ export interface TextPart {
9
9
  export interface ImagePart {
10
10
  type: "image";
11
11
  /**
12
- * Image data. Can either be a base64-encoded string, a Uint8Array, or a Buffer.
12
+ * Image data. Can either be a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer.
13
13
  */
14
- image: string | Uint8Array | Buffer;
14
+ image: DataContent;
15
15
  /**
16
16
  * Optional mime type of the image.
17
17
  */
@@ -28,5 +28,4 @@ export interface ToolResponsePart {
28
28
  id: string;
29
29
  response: unknown;
30
30
  }
31
- export declare function getImageAsBase64(image: string | Uint8Array | Buffer): string;
32
31
  export declare function validateContentIsString(content: string | unknown, prompt: unknown): string;
@@ -1,11 +1,4 @@
1
- import { uint8ArrayToBase64 } from "../../../util/UInt8Utils.js";
2
1
  import { InvalidPromptError } from "./InvalidPromptError.js";
3
- export function getImageAsBase64(image) {
4
- if (typeof image === "string") {
5
- return image;
6
- }
7
- return uint8ArrayToBase64(image);
8
- }
9
2
  export function validateContentIsString(content, prompt) {
10
3
  if (typeof content !== "string") {
11
4
  throw new InvalidPromptError("Only text prompts are are supported by this prompt template.", prompt);
@@ -1,9 +1,13 @@
1
+ import { DataContent } from "../../util/format/DataContent.js";
1
2
  import { FunctionCallOptions } from "../../core/FunctionOptions.js";
2
3
  import { Model, ModelSettings } from "../Model.js";
3
4
  export interface TranscriptionModelSettings extends ModelSettings {
4
5
  }
5
- export interface TranscriptionModel<DATA, SETTINGS extends TranscriptionModelSettings = TranscriptionModelSettings> extends Model<SETTINGS> {
6
- doTranscribe: (data: DATA, options: FunctionCallOptions) => PromiseLike<{
6
+ export interface TranscriptionModel<SETTINGS extends TranscriptionModelSettings = TranscriptionModelSettings> extends Model<SETTINGS> {
7
+ doTranscribe: (input: {
8
+ mimeType: string;
9
+ audioData: DataContent;
10
+ }, options: FunctionCallOptions) => PromiseLike<{
7
11
  rawResponse: unknown;
8
12
  transcription: string;
9
13
  }>;
@@ -2,14 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateTranscription = void 0;
4
4
  const executeStandardCall_js_1 = require("../executeStandardCall.cjs");
5
- async function generateTranscription({ model, data, fullResponse, ...options }) {
5
+ async function generateTranscription({ model, audioData, mimeType, fullResponse, ...options }) {
6
+ const input = { mimeType, audioData };
6
7
  const callResponse = await (0, executeStandardCall_js_1.executeStandardCall)({
7
8
  functionType: "generate-transcription",
8
- input: data,
9
+ input,
9
10
  model,
10
11
  options,
11
12
  generateResponse: async (options) => {
12
- const result = await model.doTranscribe(data, options);
13
+ const result = await model.doTranscribe(input, options);
13
14
  return {
14
15
  rawResponse: result.rawResponse,
15
16
  extractedValue: result.transcription,
@@ -1,4 +1,6 @@
1
1
  import { FunctionOptions } from "../../core/FunctionOptions.js";
2
+ import { AudioMimeType } from "../../util/audio/AudioMimeType.js";
3
+ import { DataContent } from "../../util/format/DataContent.js";
2
4
  import { ModelCallMetadata } from "../ModelCallMetadata.js";
3
5
  import { TranscriptionModel, TranscriptionModelSettings } from "./TranscriptionModel.js";
4
6
  /**
@@ -7,26 +9,30 @@ import { TranscriptionModel, TranscriptionModelSettings } from "./TranscriptionM
7
9
  * @see https://modelfusion.dev/guide/function/generate-transcription
8
10
  *
9
11
  * @example
10
- * const data = await fs.promises.readFile("data/test.mp3");
12
+ * const audioData = await fs.promises.readFile("data/test.mp3");
11
13
  *
12
14
  * const transcription = await generateTranscription({
13
15
  * model: openai.Transcriber({ model: "whisper-1" }),
14
- * data: { type: "mp3", data }
16
+ * mimeType: "audio/mp3",
17
+ * audioData,
15
18
  * });
16
19
  *
17
- * @param {TranscriptionModel<DATA, TranscriptionModelSettings>} model - The model to use for transcription.
18
- * @param {DATA} data - The data to transcribe.
20
+ * @param {TranscriptionModel<DATA, TranscriptionModelSettings>} options.model - The model to use for transcription.
21
+ * @param {AudioMimeType} options.model - The MIME type of the audio data.
22
+ * @param {DataContent} options.model - The audio data to transcribe. Can be a base64-encoded string, a Uint8Array, or a Buffer.
19
23
  *
20
24
  * @returns {Promise<string>} A promise that resolves to the transcribed text.
21
25
  */
22
- export declare function generateTranscription<DATA>(args: {
23
- model: TranscriptionModel<DATA, TranscriptionModelSettings>;
24
- data: DATA;
26
+ export declare function generateTranscription(args: {
27
+ model: TranscriptionModel<TranscriptionModelSettings>;
28
+ mimeType: AudioMimeType | (string & {});
29
+ audioData: DataContent;
25
30
  fullResponse?: false;
26
31
  } & FunctionOptions): Promise<string>;
27
- export declare function generateTranscription<DATA>(args: {
28
- model: TranscriptionModel<DATA, TranscriptionModelSettings>;
29
- data: DATA;
32
+ export declare function generateTranscription(args: {
33
+ model: TranscriptionModel<TranscriptionModelSettings>;
34
+ mimeType: AudioMimeType | (string & {});
35
+ audioData: DataContent;
30
36
  fullResponse: true;
31
37
  } & FunctionOptions): Promise<{
32
38
  value: string;
@@ -1,12 +1,13 @@
1
1
  import { executeStandardCall } from "../executeStandardCall.js";
2
- export async function generateTranscription({ model, data, fullResponse, ...options }) {
2
+ export async function generateTranscription({ model, audioData, mimeType, fullResponse, ...options }) {
3
+ const input = { mimeType, audioData };
3
4
  const callResponse = await executeStandardCall({
4
5
  functionType: "generate-transcription",
5
- input: data,
6
+ input,
6
7
  model,
7
8
  options,
8
9
  generateResponse: async (options) => {
9
- const result = await model.doTranscribe(data, options);
10
+ const result = await model.doTranscribe(input, options);
10
11
  return {
11
12
  rawResponse: result.rawResponse,
12
13
  extractedValue: result.transcription,
@@ -9,7 +9,7 @@ const parseJSON_js_1 = require("../../core/schema/parseJSON.cjs");
9
9
  const AbstractModel_js_1 = require("../../model-function/AbstractModel.cjs");
10
10
  const AsyncQueue_js_1 = require("../../util/AsyncQueue.cjs");
11
11
  const SimpleWebSocket_js_1 = require("../../util/SimpleWebSocket.cjs");
12
- const UInt8Utils_js_1 = require("../../util/UInt8Utils.cjs");
12
+ const UInt8Utils_js_1 = require("../../util/format/UInt8Utils.cjs");
13
13
  const ElevenLabsApiConfiguration_js_1 = require("./ElevenLabsApiConfiguration.cjs");
14
14
  const elevenLabsModels = [
15
15
  "eleven_multilingual_v2",
@@ -6,7 +6,7 @@ import { safeParseJSON } from "../../core/schema/parseJSON.js";
6
6
  import { AbstractModel } from "../../model-function/AbstractModel.js";
7
7
  import { AsyncQueue } from "../../util/AsyncQueue.js";
8
8
  import { createSimpleWebSocket } from "../../util/SimpleWebSocket.js";
9
- import { base64ToUint8Array } from "../../util/UInt8Utils.js";
9
+ import { base64ToUint8Array } from "../../util/format/UInt8Utils.js";
10
10
  import { ElevenLabsApiConfiguration } from "./ElevenLabsApiConfiguration.js";
11
11
  const elevenLabsModels = [
12
12
  "eleven_multilingual_v2",
@@ -4,6 +4,7 @@ exports.chat = exports.instruction = exports.text = void 0;
4
4
  const ContentPart_js_1 = require("../../model-function/generate-text/prompt-template/ContentPart.cjs");
5
5
  const InvalidPromptError_js_1 = require("../../model-function/generate-text/prompt-template/InvalidPromptError.cjs");
6
6
  const TextPromptTemplate_js_1 = require("../../model-function/generate-text/prompt-template/TextPromptTemplate.cjs");
7
+ const DataContent_js_1 = require("../../util/format/DataContent.cjs");
7
8
  // default Vicuna 1 system message
8
9
  const DEFAULT_SYSTEM_MESSAGE = "A chat between a curious user and an artificial intelligence assistant. " +
9
10
  "The assistant gives helpful, detailed, and polite answers to the user's questions.";
@@ -46,7 +47,8 @@ function instruction() {
46
47
  }
47
48
  case "image": {
48
49
  text += `[img-${imageCounter}]`;
49
- images[imageCounter.toString()] = (0, ContentPart_js_1.getImageAsBase64)(content.image);
50
+ images[imageCounter.toString()] =
51
+ (0, DataContent_js_1.convertDataContentToBase64String)(content.image);
50
52
  imageCounter++;
51
53
  break;
52
54
  }
@@ -85,7 +87,8 @@ function chat() {
85
87
  }
86
88
  case "image": {
87
89
  text += `[img-${imageCounter}]`;
88
- images[imageCounter.toString()] = (0, ContentPart_js_1.getImageAsBase64)(part.image);
90
+ images[imageCounter.toString()] =
91
+ (0, DataContent_js_1.convertDataContentToBase64String)(part.image);
89
92
  imageCounter++;
90
93
  break;
91
94
  }
@@ -1,6 +1,7 @@
1
- import { getImageAsBase64, validateContentIsString, } from "../../model-function/generate-text/prompt-template/ContentPart.js";
1
+ import { validateContentIsString } from "../../model-function/generate-text/prompt-template/ContentPart.js";
2
2
  import { InvalidPromptError } from "../../model-function/generate-text/prompt-template/InvalidPromptError.js";
3
3
  import { text as vicunaText } from "../../model-function/generate-text/prompt-template/TextPromptTemplate.js";
4
+ import { convertDataContentToBase64String } from "../../util/format/DataContent.js";
4
5
  // default Vicuna 1 system message
5
6
  const DEFAULT_SYSTEM_MESSAGE = "A chat between a curious user and an artificial intelligence assistant. " +
6
7
  "The assistant gives helpful, detailed, and polite answers to the user's questions.";
@@ -42,7 +43,8 @@ export function instruction() {
42
43
  }
43
44
  case "image": {
44
45
  text += `[img-${imageCounter}]`;
45
- images[imageCounter.toString()] = getImageAsBase64(content.image);
46
+ images[imageCounter.toString()] =
47
+ convertDataContentToBase64String(content.image);
46
48
  imageCounter++;
47
49
  break;
48
50
  }
@@ -80,7 +82,8 @@ export function chat() {
80
82
  }
81
83
  case "image": {
82
84
  text += `[img-${imageCounter}]`;
83
- images[imageCounter.toString()] = getImageAsBase64(part.image);
85
+ images[imageCounter.toString()] =
86
+ convertDataContentToBase64String(part.image);
84
87
  imageCounter++;
85
88
  break;
86
89
  }
@@ -6,7 +6,7 @@ const callWithRetryAndThrottle_js_1 = require("../../core/api/callWithRetryAndTh
6
6
  const postToApi_js_1 = require("../../core/api/postToApi.cjs");
7
7
  const ZodSchema_js_1 = require("../../core/schema/ZodSchema.cjs");
8
8
  const AbstractModel_js_1 = require("../../model-function/AbstractModel.cjs");
9
- const UInt8Utils_js_1 = require("../../util/UInt8Utils.cjs");
9
+ const UInt8Utils_js_1 = require("../../util/format/UInt8Utils.cjs");
10
10
  const LmntApiConfiguration_js_1 = require("./LmntApiConfiguration.cjs");
11
11
  /**
12
12
  * Synthesize speech using the LMNT API.
@@ -3,7 +3,7 @@ import { callWithRetryAndThrottle } from "../../core/api/callWithRetryAndThrottl
3
3
  import { createJsonResponseHandler, createTextErrorResponseHandler, postToApi, } from "../../core/api/postToApi.js";
4
4
  import { zodSchema } from "../../core/schema/ZodSchema.js";
5
5
  import { AbstractModel } from "../../model-function/AbstractModel.js";
6
- import { base64ToUint8Array } from "../../util/UInt8Utils.js";
6
+ import { base64ToUint8Array } from "../../util/format/UInt8Utils.js";
7
7
  import { LmntApiConfiguration } from "./LmntApiConfiguration.js";
8
8
  /**
9
9
  * Synthesize speech using the LMNT API.
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.chat = exports.instruction = exports.text = exports.identity = void 0;
4
4
  const ContentPart_js_1 = require("../../model-function/generate-text/prompt-template/ContentPart.cjs");
5
5
  const InvalidPromptError_js_1 = require("../../model-function/generate-text/prompt-template/InvalidPromptError.cjs");
6
+ const DataContent_js_1 = require("../../util/format/DataContent.cjs");
6
7
  /**
7
8
  * OllamaChatPrompt identity chat format.
8
9
  */
@@ -95,7 +96,7 @@ function extractUserContent(input) {
95
96
  content += part.text;
96
97
  }
97
98
  else {
98
- images.push((0, ContentPart_js_1.getImageAsBase64)(part.image));
99
+ images.push((0, DataContent_js_1.convertDataContentToBase64String)(part.image));
99
100
  }
100
101
  }
101
102
  return { content, images };
@@ -1,5 +1,6 @@
1
- import { getImageAsBase64, validateContentIsString, } from "../../model-function/generate-text/prompt-template/ContentPart.js";
1
+ import { validateContentIsString } from "../../model-function/generate-text/prompt-template/ContentPart.js";
2
2
  import { InvalidPromptError } from "../../model-function/generate-text/prompt-template/InvalidPromptError.js";
3
+ import { convertDataContentToBase64String } from "../../util/format/DataContent.js";
3
4
  /**
4
5
  * OllamaChatPrompt identity chat format.
5
6
  */
@@ -88,7 +89,7 @@ function extractUserContent(input) {
88
89
  content += part.text;
89
90
  }
90
91
  else {
91
- images.push(getImageAsBase64(part.image));
92
+ images.push(convertDataContentToBase64String(part.image));
92
93
  }
93
94
  }
94
95
  return { content, images };
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OpenAIChatMessage = void 0;
4
- const ContentPart_js_1 = require("../../model-function/generate-text/prompt-template/ContentPart.cjs");
4
+ const DataContent_js_1 = require("../../util/format/DataContent.cjs");
5
5
  exports.OpenAIChatMessage = {
6
6
  /**
7
7
  * Creates a system chat message.
@@ -25,7 +25,7 @@ exports.OpenAIChatMessage = {
25
25
  case "image": {
26
26
  return {
27
27
  type: "image_url",
28
- image_url: `data:${part.mimeType ?? "image/jpeg"};base64,${(0, ContentPart_js_1.getImageAsBase64)(part.image)}`,
28
+ image_url: `data:${part.mimeType ?? "image/jpeg"};base64,${(0, DataContent_js_1.convertDataContentToBase64String)(part.image)}`,
29
29
  };
30
30
  }
31
31
  }
@@ -1,4 +1,4 @@
1
- import { getImageAsBase64, } from "../../model-function/generate-text/prompt-template/ContentPart.js";
1
+ import { convertDataContentToBase64String } from "../../util/format/DataContent.js";
2
2
  export const OpenAIChatMessage = {
3
3
  /**
4
4
  * Creates a system chat message.
@@ -22,7 +22,7 @@ export const OpenAIChatMessage = {
22
22
  case "image": {
23
23
  return {
24
24
  type: "image_url",
25
- image_url: `data:${part.mimeType ?? "image/jpeg"};base64,${getImageAsBase64(part.image)}`,
25
+ image_url: `data:${part.mimeType ?? "image/jpeg"};base64,${convertDataContentToBase64String(part.image)}`,
26
26
  };
27
27
  }
28
28
  }
@@ -6,6 +6,8 @@ const callWithRetryAndThrottle_js_1 = require("../../core/api/callWithRetryAndTh
6
6
  const postToApi_js_1 = require("../../core/api/postToApi.cjs");
7
7
  const ZodSchema_js_1 = require("../../core/schema/ZodSchema.cjs");
8
8
  const AbstractModel_js_1 = require("../../model-function/AbstractModel.cjs");
9
+ const getAudioFileExtension_js_1 = require("../../util/audio/getAudioFileExtension.cjs");
10
+ const DataContent_js_1 = require("../../util/format/DataContent.cjs");
9
11
  const OpenAIApiConfiguration_js_1 = require("./OpenAIApiConfiguration.cjs");
10
12
  const OpenAIError_js_1 = require("./OpenAIError.cjs");
11
13
  /**
@@ -54,25 +56,26 @@ class OpenAITranscriptionModel extends AbstractModel_js_1.AbstractModel {
54
56
  get modelName() {
55
57
  return this.settings.model;
56
58
  }
57
- async doTranscribe(data, options) {
58
- const rawResponse = await this.callAPI(data, options, {
59
- responseFormat: exports.OpenAITranscriptionResponseFormat.verboseJson,
60
- });
59
+ async doTranscribe({ audioData, mimeType, }, options) {
60
+ const rawResponse = await this.callAPI({
61
+ fileExtension: (0, getAudioFileExtension_js_1.getAudioFileExtension)(mimeType),
62
+ audioData: (0, DataContent_js_1.convertDataContentToUint8Array)(audioData),
63
+ }, options, { responseFormat: exports.OpenAITranscriptionResponseFormat.verboseJson });
61
64
  return {
62
65
  rawResponse,
63
66
  transcription: rawResponse.text,
64
67
  };
65
68
  }
66
- async callAPI(data, callOptions, options) {
69
+ async callAPI(input, callOptions, options) {
67
70
  const api = this.settings.api ?? new OpenAIApiConfiguration_js_1.OpenAIApiConfiguration();
68
71
  const abortSignal = callOptions?.run?.abortSignal;
69
72
  return (0, callWithRetryAndThrottle_js_1.callWithRetryAndThrottle)({
70
73
  retry: api.retry,
71
74
  throttle: api.throttle,
72
75
  call: async () => {
73
- const fileName = `audio.${data.type}`;
76
+ const fileName = `audio.${input.fileExtension}`;
74
77
  const formData = new FormData();
75
- formData.append("file", new Blob([data.data]), fileName);
78
+ formData.append("file", new Blob([input.audioData]), fileName);
76
79
  formData.append("model", this.settings.model);
77
80
  if (this.settings.prompt != null) {
78
81
  formData.append("prompt", this.settings.prompt);
@@ -4,6 +4,7 @@ import { ApiConfiguration } from "../../core/api/ApiConfiguration.js";
4
4
  import { ResponseHandler } from "../../core/api/postToApi.js";
5
5
  import { AbstractModel } from "../../model-function/AbstractModel.js";
6
6
  import { TranscriptionModel, TranscriptionModelSettings } from "../../model-function/generate-transcription/TranscriptionModel.js";
7
+ import { DataContent } from "../../util/format/DataContent.js";
7
8
  /**
8
9
  * @see https://openai.com/pricing
9
10
  */
@@ -40,10 +41,6 @@ export interface OpenAITranscriptionModelSettings extends TranscriptionModelSett
40
41
  */
41
42
  prompt?: string;
42
43
  }
43
- export type OpenAITranscriptionInput = {
44
- type: "flac" | "m4a" | "mp3" | "mp4" | "mpeg" | "mpga" | "ogg" | "wav" | "webm";
45
- data: Uint8Array;
46
- };
47
44
  /**
48
45
  * Create a transcription model that calls the OpenAI transcription API.
49
46
  *
@@ -60,11 +57,14 @@ export type OpenAITranscriptionInput = {
60
57
  * }
61
58
  * );
62
59
  */
63
- export declare class OpenAITranscriptionModel extends AbstractModel<OpenAITranscriptionModelSettings> implements TranscriptionModel<OpenAITranscriptionInput, OpenAITranscriptionModelSettings> {
60
+ export declare class OpenAITranscriptionModel extends AbstractModel<OpenAITranscriptionModelSettings> implements TranscriptionModel<OpenAITranscriptionModelSettings> {
64
61
  constructor(settings: OpenAITranscriptionModelSettings);
65
62
  readonly provider: "openai";
66
63
  get modelName(): "whisper-1";
67
- doTranscribe(data: OpenAITranscriptionInput, options: FunctionCallOptions): Promise<{
64
+ doTranscribe({ audioData, mimeType, }: {
65
+ audioData: DataContent;
66
+ mimeType: string;
67
+ }, options: FunctionCallOptions): Promise<{
68
68
  rawResponse: {
69
69
  text: string;
70
70
  duration: number;
@@ -86,7 +86,10 @@ export declare class OpenAITranscriptionModel extends AbstractModel<OpenAITransc
86
86
  };
87
87
  transcription: string;
88
88
  }>;
89
- callAPI<RESULT>(data: OpenAITranscriptionInput, callOptions: FunctionCallOptions, options: {
89
+ callAPI<RESULT>(input: {
90
+ fileExtension: string;
91
+ audioData: Uint8Array;
92
+ }, callOptions: FunctionCallOptions, options: {
90
93
  responseFormat: OpenAITranscriptionResponseFormatType<RESULT>;
91
94
  }): Promise<RESULT>;
92
95
  get settingsForEvent(): Partial<OpenAITranscriptionModelSettings>;
@@ -3,6 +3,8 @@ import { callWithRetryAndThrottle } from "../../core/api/callWithRetryAndThrottl
3
3
  import { createJsonResponseHandler, createTextResponseHandler, postToApi, } from "../../core/api/postToApi.js";
4
4
  import { zodSchema } from "../../core/schema/ZodSchema.js";
5
5
  import { AbstractModel } from "../../model-function/AbstractModel.js";
6
+ import { getAudioFileExtension } from "../../util/audio/getAudioFileExtension.js";
7
+ import { convertDataContentToUint8Array, } from "../../util/format/DataContent.js";
6
8
  import { OpenAIApiConfiguration } from "./OpenAIApiConfiguration.js";
7
9
  import { failedOpenAICallResponseHandler } from "./OpenAIError.js";
8
10
  /**
@@ -50,25 +52,26 @@ export class OpenAITranscriptionModel extends AbstractModel {
50
52
  get modelName() {
51
53
  return this.settings.model;
52
54
  }
53
- async doTranscribe(data, options) {
54
- const rawResponse = await this.callAPI(data, options, {
55
- responseFormat: OpenAITranscriptionResponseFormat.verboseJson,
56
- });
55
+ async doTranscribe({ audioData, mimeType, }, options) {
56
+ const rawResponse = await this.callAPI({
57
+ fileExtension: getAudioFileExtension(mimeType),
58
+ audioData: convertDataContentToUint8Array(audioData),
59
+ }, options, { responseFormat: OpenAITranscriptionResponseFormat.verboseJson });
57
60
  return {
58
61
  rawResponse,
59
62
  transcription: rawResponse.text,
60
63
  };
61
64
  }
62
- async callAPI(data, callOptions, options) {
65
+ async callAPI(input, callOptions, options) {
63
66
  const api = this.settings.api ?? new OpenAIApiConfiguration();
64
67
  const abortSignal = callOptions?.run?.abortSignal;
65
68
  return callWithRetryAndThrottle({
66
69
  retry: api.retry,
67
70
  throttle: api.throttle,
68
71
  call: async () => {
69
- const fileName = `audio.${data.type}`;
72
+ const fileName = `audio.${input.fileExtension}`;
70
73
  const formData = new FormData();
71
- formData.append("file", new Blob([data.data]), fileName);
74
+ formData.append("file", new Blob([input.audioData]), fileName);
72
75
  formData.append("model", this.settings.model);
73
76
  if (this.settings.prompt != null) {
74
77
  formData.append("prompt", this.settings.prompt);
@@ -8,6 +8,8 @@ const postToApi_js_1 = require("../../core/api/postToApi.cjs");
8
8
  const ZodSchema_js_1 = require("../../core/schema/ZodSchema.cjs");
9
9
  const parseJSON_js_1 = require("../../core/schema/parseJSON.cjs");
10
10
  const AbstractModel_js_1 = require("../../model-function/AbstractModel.cjs");
11
+ const getAudioFileExtension_js_1 = require("../../util/audio/getAudioFileExtension.cjs");
12
+ const DataContent_js_1 = require("../../util/format/DataContent.cjs");
11
13
  const WhisperCppApiConfiguration_js_1 = require("./WhisperCppApiConfiguration.cjs");
12
14
  class WhisperCppTranscriptionModel extends AbstractModel_js_1.AbstractModel {
13
15
  constructor(settings) {
@@ -25,14 +27,17 @@ class WhisperCppTranscriptionModel extends AbstractModel_js_1.AbstractModel {
25
27
  value: null
26
28
  });
27
29
  }
28
- async doTranscribe(data, options) {
29
- const rawResponse = await this.callAPI(data, options);
30
+ async doTranscribe({ audioData, mimeType, }, options) {
31
+ const rawResponse = await this.callAPI({
32
+ fileExtension: (0, getAudioFileExtension_js_1.getAudioFileExtension)(mimeType),
33
+ audioData: (0, DataContent_js_1.convertDataContentToUint8Array)(audioData),
34
+ }, options);
30
35
  return {
31
36
  rawResponse,
32
37
  transcription: rawResponse.text,
33
38
  };
34
39
  }
35
- async callAPI(data, callOptions) {
40
+ async callAPI(input, callOptions) {
36
41
  const { temperature } = this.settings;
37
42
  const api = this.settings.api ?? new WhisperCppApiConfiguration_js_1.WhisperCppApiConfiguration();
38
43
  const abortSignal = callOptions.run?.abortSignal;
@@ -41,7 +46,7 @@ class WhisperCppTranscriptionModel extends AbstractModel_js_1.AbstractModel {
41
46
  throttle: api.throttle,
42
47
  call: async () => {
43
48
  const formData = new FormData();
44
- formData.append("file", new Blob([data.data]), `audio.${data.type}`);
49
+ formData.append("file", new Blob([input.audioData]), `audio.${input.fileExtension}`);
45
50
  formData.append("response_format", "json");
46
51
  if (temperature != null) {
47
52
  formData.append("temperature", temperature.toString());
@@ -2,25 +2,28 @@ import { FunctionCallOptions } from "../../core/FunctionOptions.js";
2
2
  import { ApiConfiguration } from "../../core/api/ApiConfiguration.js";
3
3
  import { AbstractModel } from "../../model-function/AbstractModel.js";
4
4
  import { TranscriptionModel, TranscriptionModelSettings } from "../../model-function/generate-transcription/TranscriptionModel.js";
5
+ import { DataContent } from "../../util/format/DataContent.js";
5
6
  export interface WhisperCppTranscriptionModelSettings extends TranscriptionModelSettings {
6
7
  api?: ApiConfiguration;
7
8
  temperature?: number;
8
9
  }
9
- export type WhisperCppTranscriptionInput = {
10
- type: "wav";
11
- data: Uint8Array;
12
- };
13
- export declare class WhisperCppTranscriptionModel extends AbstractModel<WhisperCppTranscriptionModelSettings> implements TranscriptionModel<WhisperCppTranscriptionInput, WhisperCppTranscriptionModelSettings> {
10
+ export declare class WhisperCppTranscriptionModel extends AbstractModel<WhisperCppTranscriptionModelSettings> implements TranscriptionModel<WhisperCppTranscriptionModelSettings> {
14
11
  constructor(settings: WhisperCppTranscriptionModelSettings);
15
12
  readonly provider: "whispercpp";
16
13
  readonly modelName: null;
17
- doTranscribe(data: WhisperCppTranscriptionInput, options: FunctionCallOptions): Promise<{
14
+ doTranscribe({ audioData, mimeType, }: {
15
+ audioData: DataContent;
16
+ mimeType: string;
17
+ }, options: FunctionCallOptions): Promise<{
18
18
  rawResponse: {
19
19
  text: string;
20
20
  };
21
21
  transcription: string;
22
22
  }>;
23
- callAPI(data: WhisperCppTranscriptionInput, callOptions: FunctionCallOptions): Promise<{
23
+ callAPI(input: {
24
+ fileExtension: string;
25
+ audioData: Uint8Array;
26
+ }, callOptions: FunctionCallOptions): Promise<{
24
27
  text: string;
25
28
  }>;
26
29
  get settingsForEvent(): Partial<WhisperCppTranscriptionModelSettings>;
@@ -5,6 +5,8 @@ import { postToApi } from "../../core/api/postToApi.js";
5
5
  import { zodSchema } from "../../core/schema/ZodSchema.js";
6
6
  import { safeParseJSON } from "../../core/schema/parseJSON.js";
7
7
  import { AbstractModel } from "../../model-function/AbstractModel.js";
8
+ import { getAudioFileExtension } from "../../util/audio/getAudioFileExtension.js";
9
+ import { convertDataContentToUint8Array, } from "../../util/format/DataContent.js";
8
10
  import { WhisperCppApiConfiguration } from "./WhisperCppApiConfiguration.js";
9
11
  export class WhisperCppTranscriptionModel extends AbstractModel {
10
12
  constructor(settings) {
@@ -22,14 +24,17 @@ export class WhisperCppTranscriptionModel extends AbstractModel {
22
24
  value: null
23
25
  });
24
26
  }
25
- async doTranscribe(data, options) {
26
- const rawResponse = await this.callAPI(data, options);
27
+ async doTranscribe({ audioData, mimeType, }, options) {
28
+ const rawResponse = await this.callAPI({
29
+ fileExtension: getAudioFileExtension(mimeType),
30
+ audioData: convertDataContentToUint8Array(audioData),
31
+ }, options);
27
32
  return {
28
33
  rawResponse,
29
34
  transcription: rawResponse.text,
30
35
  };
31
36
  }
32
- async callAPI(data, callOptions) {
37
+ async callAPI(input, callOptions) {
33
38
  const { temperature } = this.settings;
34
39
  const api = this.settings.api ?? new WhisperCppApiConfiguration();
35
40
  const abortSignal = callOptions.run?.abortSignal;
@@ -38,7 +43,7 @@ export class WhisperCppTranscriptionModel extends AbstractModel {
38
43
  throttle: api.throttle,
39
44
  call: async () => {
40
45
  const formData = new FormData();
41
- formData.append("file", new Blob([data.data]), `audio.${data.type}`);
46
+ formData.append("file", new Blob([input.audioData]), `audio.${input.fileExtension}`);
42
47
  formData.append("response_format", "json");
43
48
  if (temperature != null) {
44
49
  formData.append("temperature", temperature.toString());
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "modelfusion",
3
3
  "description": "The TypeScript library for building AI applications.",
4
- "version": "0.129.1",
4
+ "version": "0.130.1",
5
5
  "author": "Lars Grammel",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -24,18 +24,25 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.createSimpleWebSocket = void 0;
27
+ const Runtime = __importStar(require("./detectRuntime.cjs"));
27
28
  /**
28
29
  * Creates a simplified websocket connection. This function works in both Node.js and browser.
29
30
  */
30
31
  async function createSimpleWebSocket(url) {
31
- if (typeof window === "undefined") {
32
- // Use ws library in Node.js:
33
- const { default: WebSocket } = await Promise.resolve().then(() => __importStar(require("ws")));
34
- return new WebSocket(url);
35
- }
36
- else {
37
- // Use native WebSocket in browser:
38
- return new WebSocket(url);
32
+ switch (Runtime.detectRuntime()) {
33
+ case "vercel-edge":
34
+ case "cloudflare-workers":
35
+ case "browser": {
36
+ return new WebSocket(url);
37
+ }
38
+ case "node": {
39
+ // Use ws library (for Node.js):
40
+ const { default: WebSocket } = await Promise.resolve().then(() => __importStar(require("ws")));
41
+ return new WebSocket(url);
42
+ }
43
+ default: {
44
+ throw new Error("Unknown runtime");
45
+ }
39
46
  }
40
47
  }
41
48
  exports.createSimpleWebSocket = createSimpleWebSocket;
@@ -1,14 +1,21 @@
1
+ import * as Runtime from "./detectRuntime.js";
1
2
  /**
2
3
  * Creates a simplified websocket connection. This function works in both Node.js and browser.
3
4
  */
4
5
  export async function createSimpleWebSocket(url) {
5
- if (typeof window === "undefined") {
6
- // Use ws library in Node.js:
7
- const { default: WebSocket } = await import("ws");
8
- return new WebSocket(url);
9
- }
10
- else {
11
- // Use native WebSocket in browser:
12
- return new WebSocket(url);
6
+ switch (Runtime.detectRuntime()) {
7
+ case "vercel-edge":
8
+ case "cloudflare-workers":
9
+ case "browser": {
10
+ return new WebSocket(url);
11
+ }
12
+ case "node": {
13
+ // Use ws library (for Node.js):
14
+ const { default: WebSocket } = await import("ws");
15
+ return new WebSocket(url);
16
+ }
17
+ default: {
18
+ throw new Error("Unknown runtime");
19
+ }
13
20
  }
14
21
  }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export type AudioMimeType = "audio/webm" | "audio/mp3" | "audio/wav" | "audio/mp4" | "audio/mpeg" | "audio/mpga" | "audio/ogg" | "audio/oga" | "audio/flac" | "audio/m4a";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAudioFileExtension = void 0;
4
+ function getAudioFileExtension(mimeType) {
5
+ const normalizedMimeType = mimeType.split(";")[0].toLowerCase();
6
+ switch (normalizedMimeType) {
7
+ case "audio/webm":
8
+ return "webm";
9
+ case "audio/mp3":
10
+ return "mp3";
11
+ case "audio/wav":
12
+ return "wav";
13
+ case "audio/mp4":
14
+ return "mp4";
15
+ case "audio/mpeg":
16
+ case "audio/mpga":
17
+ return "mpeg";
18
+ case "audio/ogg":
19
+ case "audio/oga":
20
+ return "ogg";
21
+ case "audio/flac":
22
+ return "flac";
23
+ case "audio/m4a":
24
+ return "m4a";
25
+ default:
26
+ throw new Error(`Unsupported audio format: ${mimeType}`);
27
+ }
28
+ }
29
+ exports.getAudioFileExtension = getAudioFileExtension;
@@ -0,0 +1 @@
1
+ export declare function getAudioFileExtension(mimeType: string): "mp3" | "flac" | "webm" | "wav" | "mp4" | "mpeg" | "ogg" | "m4a";
@@ -0,0 +1,25 @@
1
+ export function getAudioFileExtension(mimeType) {
2
+ const normalizedMimeType = mimeType.split(";")[0].toLowerCase();
3
+ switch (normalizedMimeType) {
4
+ case "audio/webm":
5
+ return "webm";
6
+ case "audio/mp3":
7
+ return "mp3";
8
+ case "audio/wav":
9
+ return "wav";
10
+ case "audio/mp4":
11
+ return "mp4";
12
+ case "audio/mpeg":
13
+ case "audio/mpga":
14
+ return "mpeg";
15
+ case "audio/ogg":
16
+ case "audio/oga":
17
+ return "ogg";
18
+ case "audio/flac":
19
+ return "flac";
20
+ case "audio/m4a":
21
+ return "m4a";
22
+ default:
23
+ throw new Error(`Unsupported audio format: ${mimeType}`);
24
+ }
25
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./AudioMimeType.cjs"), exports);
18
+ __exportStar(require("./getAudioFileExtension.cjs"), exports);
@@ -0,0 +1,2 @@
1
+ export * from "./AudioMimeType.js";
2
+ export * from "./getAudioFileExtension.js";
@@ -0,0 +1,2 @@
1
+ export * from "./AudioMimeType.js";
2
+ export * from "./getAudioFileExtension.js";
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectRuntime = void 0;
4
+ function detectRuntime() {
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ const globalThisAny = globalThis;
7
+ if (globalThisAny.EdgeRuntime) {
8
+ return "vercel-edge";
9
+ }
10
+ if (globalThis.navigator?.userAgent === "Cloudflare-Workers") {
11
+ return "cloudflare-workers";
12
+ }
13
+ if (globalThis.process?.release?.name === "node") {
14
+ return "node";
15
+ }
16
+ if (globalThis.window) {
17
+ return "browser";
18
+ }
19
+ return null;
20
+ }
21
+ exports.detectRuntime = detectRuntime;
@@ -0,0 +1 @@
1
+ export declare function detectRuntime(): "vercel-edge" | "cloudflare-workers" | "node" | "browser" | null;
@@ -0,0 +1,17 @@
1
+ export function detectRuntime() {
2
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3
+ const globalThisAny = globalThis;
4
+ if (globalThisAny.EdgeRuntime) {
5
+ return "vercel-edge";
6
+ }
7
+ if (globalThis.navigator?.userAgent === "Cloudflare-Workers") {
8
+ return "cloudflare-workers";
9
+ }
10
+ if (globalThis.process?.release?.name === "node") {
11
+ return "node";
12
+ }
13
+ if (globalThis.window) {
14
+ return "browser";
15
+ }
16
+ return null;
17
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertDataContentToUint8Array = exports.convertDataContentToBase64String = void 0;
4
+ const UInt8Utils_js_1 = require("./UInt8Utils.cjs");
5
+ function convertDataContentToBase64String(content) {
6
+ if (typeof content === "string") {
7
+ return content;
8
+ }
9
+ if (content instanceof ArrayBuffer) {
10
+ return (0, UInt8Utils_js_1.uint8ArrayToBase64)(new Uint8Array(content));
11
+ }
12
+ return (0, UInt8Utils_js_1.uint8ArrayToBase64)(content);
13
+ }
14
+ exports.convertDataContentToBase64String = convertDataContentToBase64String;
15
+ function convertDataContentToUint8Array(content) {
16
+ if (content instanceof Uint8Array) {
17
+ return content;
18
+ }
19
+ if (typeof content === "string") {
20
+ return (0, UInt8Utils_js_1.base64ToUint8Array)(content);
21
+ }
22
+ if (content instanceof ArrayBuffer) {
23
+ return new Uint8Array(content);
24
+ }
25
+ throw new Error(`Invalid data content. Expected a string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.`);
26
+ }
27
+ exports.convertDataContentToUint8Array = convertDataContentToUint8Array;
@@ -0,0 +1,7 @@
1
+ /// <reference types="node" />
2
+ /**
3
+ * Data content. Can either be a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer.
4
+ */
5
+ export type DataContent = string | Uint8Array | ArrayBuffer | Buffer;
6
+ export declare function convertDataContentToBase64String(content: DataContent): string;
7
+ export declare function convertDataContentToUint8Array(content: DataContent): Uint8Array;
@@ -0,0 +1,22 @@
1
+ import { base64ToUint8Array, uint8ArrayToBase64 } from "./UInt8Utils.js";
2
+ export function convertDataContentToBase64String(content) {
3
+ if (typeof content === "string") {
4
+ return content;
5
+ }
6
+ if (content instanceof ArrayBuffer) {
7
+ return uint8ArrayToBase64(new Uint8Array(content));
8
+ }
9
+ return uint8ArrayToBase64(content);
10
+ }
11
+ export function convertDataContentToUint8Array(content) {
12
+ if (content instanceof Uint8Array) {
13
+ return content;
14
+ }
15
+ if (typeof content === "string") {
16
+ return base64ToUint8Array(content);
17
+ }
18
+ if (content instanceof ArrayBuffer) {
19
+ return new Uint8Array(content);
20
+ }
21
+ throw new Error(`Invalid data content. Expected a string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.`);
22
+ }
@@ -11,18 +11,8 @@
11
11
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.uint8ArrayToBase64 = exports.base64ToUint8Array = exports.toUint8Array = void 0;
14
+ exports.uint8ArrayToBase64 = exports.base64ToUint8Array = void 0;
15
15
  // copied from: https://github.com/sindresorhus/uint8array-extras/blob/main/index.js
16
- function toUint8Array(value) {
17
- if (value instanceof ArrayBuffer) {
18
- return new Uint8Array(value);
19
- }
20
- if (ArrayBuffer.isView(value)) {
21
- return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
22
- }
23
- throw new TypeError(`Unsupported value, got \`${typeof value}\`.`);
24
- }
25
- exports.toUint8Array = toUint8Array;
26
16
  function base64ToUint8Array(base64String) {
27
17
  return Uint8Array.from(globalThis.atob(base64UrlToBase64(base64String)), (x) => x.codePointAt(0));
28
18
  }
@@ -1,3 +1,2 @@
1
- export declare function toUint8Array(value: unknown): Uint8Array;
2
1
  export declare function base64ToUint8Array(base64String: string): Uint8Array;
3
2
  export declare function uint8ArrayToBase64(array: Uint8Array): string;
@@ -10,15 +10,6 @@
10
10
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11
11
  */
12
12
  // copied from: https://github.com/sindresorhus/uint8array-extras/blob/main/index.js
13
- export function toUint8Array(value) {
14
- if (value instanceof ArrayBuffer) {
15
- return new Uint8Array(value);
16
- }
17
- if (ArrayBuffer.isView(value)) {
18
- return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
19
- }
20
- throw new TypeError(`Unsupported value, got \`${typeof value}\`.`);
21
- }
22
13
  export function base64ToUint8Array(base64String) {
23
14
  return Uint8Array.from(globalThis.atob(base64UrlToBase64(base64String)), (x) => x.codePointAt(0));
24
15
  }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./DataContent.cjs"), exports);
@@ -0,0 +1 @@
1
+ export * from "./DataContent.js";
@@ -0,0 +1 @@
1
+ export * from "./DataContent.js";
package/util/index.cjs CHANGED
@@ -15,6 +15,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./AsyncQueue.cjs"), exports);
18
+ __exportStar(require("./audio/index.cjs"), exports);
18
19
  __exportStar(require("./cosineSimilarity.cjs"), exports);
19
20
  __exportStar(require("./delay.cjs"), exports);
21
+ __exportStar(require("./format/index.cjs"), exports);
20
22
  __exportStar(require("./streaming/index.cjs"), exports);
package/util/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from "./AsyncQueue.js";
2
+ export * from "./audio/index.js";
2
3
  export * from "./cosineSimilarity.js";
3
4
  export * from "./delay.js";
5
+ export * from "./format/index.js";
4
6
  export * from "./streaming/index.js";
package/util/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from "./AsyncQueue.js";
2
+ export * from "./audio/index.js";
2
3
  export * from "./cosineSimilarity.js";
3
4
  export * from "./delay.js";
5
+ export * from "./format/index.js";
4
6
  export * from "./streaming/index.js";