UNPKG

jorel

Version:

A unified wrapper for working with LLMs from multiple providers, including streams, images, documents & automatic tool use.

174 lines (173 loc) 6.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ImageContent = void 0; const file_type_1 = require("file-type"); const fs_1 = require("fs"); const shared_1 = require("../shared"); const utils_1 = require("./utils"); /** * Simplifies handling of images handed to JorEl. Instances of this class can be * created from a variety of sources, and can be passed directly to JorEl. */ class ImageContent { constructor(source, metadata) { this._source = source; this.metadata = metadata; } /** * Instantiates an image from a data URL * @param dataUrl - The data URL of the image * @param metadata - Metadata to attach to the image */ static fromDataUrl(dataUrl, metadata = {}) { const [mimeType, base64] = dataUrl.split(/[:;,]/).slice(1, 3); return new ImageContent({ type: "base64", data: base64, mimeType, }, metadata); } static async fromUrl(url, mimeType, downloadMedia = true, metadata) { if (!downloadMedia) return new ImageContent({ type: "url", url, mimeType: mimeType || "" }, metadata); const buffer = await (0, utils_1.fetchFileAsBuffer)(url, mimeType); return new ImageContent({ type: "buffer", buffer: buffer.buffer, mimeType: buffer.mimeType, }, metadata); } /** * Instantiates an array of images from an array of URLs * @param urls - Array of URLs * @param metadata - Metadata to attach to the images */ static async fromUrls(urls, metadata) { return Promise.all(urls.map((url) => ImageContent.fromUrl(url, undefined, undefined, metadata))); } /** * Instantiates an image from an existing buffer * @param buffer - Buffer containing the image data * @param mimeType - (optional) MIME type of the image * @param metadata - Metadata to attach to the image * @throws Error - Error if the MIME type cannot be detected */ static async fromBuffer(buffer, mimeType, metadata) { const type = mimeType || (await (0, file_type_1.fileTypeFromBuffer)(buffer))?.mime; if (!type) { throw new Error("Unsupported image type. Unable to detect MIME type from the buffer."); } return new ImageContent({ type: "buffer", buffer, mimeType: type }, metadata); } /** * Instantiates an image from a file path * @param filePath - Path to the image file * @param mimeType - (optional) MIME type of the image * @param metadata - Metadata to attach to the image * @throws Error - Error if the file cannot be read */ static async fromFile(filePath, mimeType, metadata) { try { const buffer = await fs_1.promises.readFile(filePath); return ImageContent.fromBuffer(buffer, mimeType, metadata); } catch (e) { const message = e instanceof Error ? e.message : typeof e === "string" ? e : "Unknown error"; throw new Error(`Failed to read file: ${filePath}, error: ${message}`); } } /** * Instantiates an array of images from an array of file paths * @param files - Array of file paths * @param mimeType - (optional) MIME type of the images * @param metadata - Metadata to attach to the images */ static async fromFiles(files, mimeType, metadata) { return Promise.all(files.map((file) => ImageContent.fromFile(file, mimeType, metadata))); } /** * Returns the image as a buffer * @returns The image buffer and its MIME type */ async toBuffer() { if (this._source.type === "buffer") { return { buffer: this._source.buffer, mimeType: this._source.mimeType }; } else if (this._source.type === "base64") { return { buffer: Buffer.from(this._source.data, "base64"), mimeType: this._source.mimeType, }; } else { return (0, utils_1.fetchFileAsBuffer)(this._source.url, this._source.mimeType); } } /** * Returns the image as a Uint8Array * @returns The image as a Uint8Array */ async toUint8Array() { const { buffer } = await this.toBuffer(); return new Uint8Array(buffer); } /** * Returns the image as a base64 string * @returns The image data and its MIME type */ async toBase64() { if (this._source.type === "base64") { return { data: this._source.data, mimeType: this._source.mimeType }; } else if (this._source.type === "buffer") { return { data: this._source.buffer.toString("base64"), mimeType: this._source.mimeType, }; } else { const buffer = await (0, utils_1.fetchFileAsBuffer)(this._source.url, this._source.mimeType); return { data: buffer.buffer.toString("base64"), mimeType: buffer.mimeType, }; } } /** * Returns the image as a data URL * @returns The image data URL */ async toDataUrl() { const { data, mimeType } = await this.toBase64(); return `data:${mimeType};base64,${data}`; } async toMessageContent(downloadUrls = false) { if (this._source.type === "url" && !downloadUrls) { return { type: "imageUrl", url: this._source.url, metadata: this.metadata }; } const { data, mimeType } = await this.toBase64(); return (0, shared_1.shallowFilterUndefined)({ type: "imageData", data: `data:${mimeType};base64,${data}`, mimeType, metadata: this.metadata, }); } /** * Returns a string representation of the ImageContent instance * @returns A string describing the image source */ toString() { switch (this._source.type) { case "buffer": return `ImageContent (buffer, MIME type: ${this._source.mimeType}, ${this._source.buffer.length} bytes)`; case "base64": return `ImageContent (base64, MIME type: ${this._source.mimeType}, ${this._source.data.length} bytes)`; case "url": return `ImageContent (URL: ${this._source.url}, MIME type: ${this._source.mimeType})`; default: return "ImageContent (unknown source)"; } } } exports.ImageContent = ImageContent;