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
JavaScript
;
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;