UNPKG

llmforge

Version:

One API, every AI model, instant switching. Change from GPT-4 to Gemini to local models with a single config update. LLMForge is the lightweight, TypeScript-first solution for multi-provider AI applications with zero vendor lock-in.

147 lines 4.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageValidator = exports.FileEncoder = exports.ContentBuilder = void 0; class ContentBuilder { constructor() { this.contents = []; } static create() { return new ContentBuilder(); } addTextMessage(text, role = 'user') { this.contents.push({ role, parts: [{ text }], }); return this; } addConversationTurn(userText, modelText) { this.addTextMessage(userText, 'user'); this.addTextMessage(modelText, 'model'); return this; } build() { return [...this.contents]; } clear() { this.contents = []; return this; } getLastContent() { return this.contents[this.contents.length - 1]; } removeLastContent() { this.contents.pop(); return this; } static fromMessages(messages) { return messages.map(msg => ({ role: msg.role, parts: [{ text: msg.text }], })); } static textOnly(text, role = 'user') { return [{ role, parts: [{ text }] }]; } } exports.ContentBuilder = ContentBuilder; class FileEncoder { static async encodeFileToBase64(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => { const result = reader.result; // Remove data URL prefix (e.g., "data:image/jpeg;base64,") const base64 = result.split(',')[1]; resolve(base64); }; reader.onerror = reject; reader.readAsDataURL(file); }); } static async encodeBufferToBase64(buffer) { const bytes = new Uint8Array(buffer); let binary = ''; for (let i = 0; i < bytes.byteLength; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary); } static getMimeTypeFromFile(file) { return file.type || this.getMimeTypeFromExtension(file.name); } static getMimeTypeFromExtension(filename) { const ext = filename.toLowerCase().split('.').pop(); const mimeTypes = { // Images jpg: 'image/jpeg', jpeg: 'image/jpeg', png: 'image/png', gif: 'image/gif', webp: 'image/webp', bmp: 'image/bmp', svg: 'image/svg+xml', // Documents pdf: 'application/pdf', txt: 'text/plain', md: 'text/markdown', html: 'text/html', css: 'text/css', js: 'application/javascript', json: 'application/json', xml: 'application/xml', // Office documents doc: 'application/msword', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', xls: 'application/vnd.ms-excel', xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', ppt: 'application/vnd.ms-powerpoint', pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // Audio/Video mp3: 'audio/mpeg', wav: 'audio/wav', mp4: 'video/mp4', avi: 'video/x-msvideo', mov: 'video/quicktime', }; return mimeTypes[ext || ''] || 'application/octet-stream'; } } exports.FileEncoder = FileEncoder; class MessageValidator { static validateContent(content) { if (!content.parts || content.parts.length === 0) { throw new Error('Content must have at least one part'); } for (const part of content.parts) { if ('text' in part) { if (!part.text || typeof part.text !== 'string') { throw new Error('Text part must have non-empty text string'); } } else if ('inline_data' in part) { if (!part.inline_data.mime_type || !part.inline_data.data) { throw new Error('Inline data part must have mime_type and data'); } } else if ('file_data' in part) { if (!part.file_data.mime_type || !part.file_data.file_uri) { throw new Error('File data part must have mime_type and file_uri'); } } else { throw new Error('Invalid content part type'); } } } static validateContents(contents) { if (!contents || contents.length === 0) { throw new Error('Contents array cannot be empty'); } for (const content of contents) { this.validateContent(content); } } } exports.MessageValidator = MessageValidator; //# sourceMappingURL=ai.builder.js.map