@juspay/neurolink
Version:
Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio
349 lines • 11.5 kB
JavaScript
/**
* Image Generation Service
*
* Handles AI image generation using NeuroLink SDK with configurable providers
* and models. Supports reference images and PDFs for contextual generation.
*
* @packageDocumentation
* @module @juspay/neurolink/image-gen
* @category ImageGeneration
*
* @example
* ```typescript
* import { ImageGenService } from '@juspay/neurolink';
*
* const service = new ImageGenService();
*
* const result = await service.generate({
* prompt: 'A serene mountain landscape at sunset',
* style: 'photorealistic',
* aspectRatio: '16:9'
* });
*
* if (result.success && result.imageBuffer) {
* fs.writeFileSync('output.png', result.imageBuffer);
* }
* ```
*/
import { withTimeout } from "../utils/errorHandling.js";
import { DEFAULT_IMAGE_GEN_CONFIG } from "../types/index.js";
/**
* NeuroLink instance type (avoiding circular dependencies)
*/
/**
* Image generation service for AI-powered image creation
*
* Uses NeuroLink SDK to generate images with support for:
* - Multiple providers (Vertex AI, OpenAI, etc.)
* - Reference images for style guidance
* - PDF documents for contextual generation
* - Configurable aspect ratios and styles
*
* @example Basic usage
* ```typescript
* const service = new ImageGenService();
* const result = await service.generate({
* prompt: 'A cute robot playing chess'
* });
* ```
*
* @example With custom configuration
* ```typescript
* const service = new ImageGenService({
* defaultProvider: 'openai',
* defaultModel: 'dall-e-3',
* timeout: 60000
* });
* ```
*/
export class ImageGenService {
config;
neurolinkInstance = null;
instanceId;
/**
* Create a new ImageGenService instance
*
* @param config - Optional configuration overrides
*/
constructor(config) {
this.config = {
...DEFAULT_IMAGE_GEN_CONFIG,
...config,
};
this.instanceId = `ImageGenService-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
}
/**
* Get or create the NeuroLink instance
* Uses dynamic import to avoid circular dependencies
*
* @returns NeuroLink instance for image generation
*/
async getNeuroLink() {
if (!this.neurolinkInstance) {
// Dynamically import to avoid circular dependencies
const { NeuroLink } = await import("../neurolink.js");
this.neurolinkInstance = new NeuroLink({
conversationMemory: { enabled: false },
enableOrchestration: false,
});
}
return this.neurolinkInstance;
}
/**
* Generate an image from a text prompt
*
* @param options - Generation options including prompt, style, etc.
* @returns Promise resolving to generation result
*
* @example Simple generation
* ```typescript
* const result = await service.generate({
* prompt: 'A futuristic cityscape'
* });
* ```
*
* @example With reference images
* ```typescript
* const referenceImage = fs.readFileSync('style-reference.jpg');
* const result = await service.generate({
* prompt: 'A portrait in this style',
* images: [referenceImage],
* aspectRatio: '1:1'
* });
* ```
*/
async generate(options) {
const startTime = Date.now();
// Check if service is enabled
if (!this.config.enabled) {
return {
success: false,
error: "Image generation is disabled",
};
}
// Validate prompt
if (!options.prompt || options.prompt.trim().length === 0) {
return {
success: false,
error: "Prompt is required for image generation",
};
}
try {
const neurolink = await this.getNeuroLink();
// Build enhanced prompt with style and negative prompt
let enhancedPrompt = options.prompt;
if (options.style) {
enhancedPrompt = `${options.style} style: ${enhancedPrompt}`;
}
if (options.negativePrompt) {
enhancedPrompt = `${enhancedPrompt}. Avoid: ${options.negativePrompt}`;
}
// Build input with optional reference images/PDFs
const input = { text: enhancedPrompt };
// Process reference images
if (options.images?.length) {
const maxImages = this.config.maxReferenceImages ?? 5;
const imagesToUse = options.images.slice(0, maxImages);
// Convert Buffers to base64 strings if needed
input.images = imagesToUse.map((img) => Buffer.isBuffer(img) ? img.toString("base64") : img);
}
// Process reference PDFs
if (options.pdfFiles?.length) {
const maxPdfs = this.config.maxReferencePdfs ?? 1;
input.pdfFiles = options.pdfFiles.slice(0, maxPdfs);
}
// Determine provider and model
const provider = options.provider ?? this.config.defaultProvider;
const model = options.model ?? this.config.defaultModel;
const region = options.region ?? this.config.defaultRegion;
// Build generation parameters
const generateParams = {
input,
provider,
model,
disableTools: true,
temperature: options.temperature ?? this.config.defaultTemperature ?? 0.75,
timeout: this.config.timeout,
};
// Add region if specified (for Vertex AI)
if (region) {
generateParams.region = region;
}
// Add number of images
const maxImages = this.config.maxImages ?? 4;
const numberOfImages = Math.min(options.numberOfImages ?? 1, maxImages);
generateParams.numberOfImages = numberOfImages;
// Add aspect ratio if specified
if (options.aspectRatio) {
generateParams.aspectRatio = options.aspectRatio;
}
// Call NeuroLink generate with timeout protection
const result = await withTimeout(neurolink.generate(generateParams), this.config.timeout, new Error(`Image generation timed out after ${this.config.timeout}ms`));
// Extract image from result
const imageOutput = this.extractImageFromResult(result);
const generationTimeMs = Date.now() - startTime;
if (imageOutput) {
return {
success: true,
imageBuffer: imageOutput.imageBuffer,
base64: imageOutput.base64,
mimeType: imageOutput.mimeType,
model,
provider,
generationTimeMs,
};
}
return {
success: false,
error: "No image generated",
model,
provider,
generationTimeMs,
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
success: false,
error: `Generation failed: ${errorMessage}`,
generationTimeMs: Date.now() - startTime,
};
}
}
/**
* Extract image data from various result formats
*
* Handles multiple output formats:
* - result.imageOutput?.base64
* - result.images?.[0]
* - data:image URI in content
* - Buffer directly
*
* @param result - Raw result from NeuroLink generate
* @returns Extracted image data or null
*/
extractImageFromResult(result) {
if (!result || typeof result !== "object") {
return null;
}
const res = result;
// Check for imageOutput with base64
const imageOutput = res.imageOutput ?? res.images?.[0];
if (imageOutput && typeof imageOutput === "object") {
const img = imageOutput;
if (typeof img.base64 === "string") {
const base64 = img.base64;
const mimeType = img.mimeType ?? "image/png";
return {
imageBuffer: Buffer.from(base64, "base64"),
base64,
mimeType,
};
}
}
// Check if imageOutput is a Buffer
if (Buffer.isBuffer(imageOutput)) {
const base64 = imageOutput.toString("base64");
return {
imageBuffer: imageOutput,
base64,
mimeType: "image/png",
};
}
// Check for data URI format in content
const content = res.content;
if (typeof content === "string" && content.startsWith("data:image")) {
const match = content.match(/^data:image\/(\w+);base64,(.+)$/);
if (match?.[2]) {
const mimeType = `image/${match[1]}`;
const base64 = match[2];
return {
imageBuffer: Buffer.from(base64, "base64"),
base64,
mimeType,
};
}
}
// Check for raw base64 in content
if (typeof content === "string" && !content.startsWith("data:")) {
// Try to detect if it's base64 encoded image data
try {
const buffer = Buffer.from(content, "base64");
// Check for PNG magic bytes
if (buffer[0] === 0x89 && buffer[1] === 0x50) {
return {
imageBuffer: buffer,
base64: content,
mimeType: "image/png",
};
}
// Check for JPEG magic bytes
if (buffer[0] === 0xff && buffer[1] === 0xd8) {
return {
imageBuffer: buffer,
base64: content,
mimeType: "image/jpeg",
};
}
}
catch {
// Not valid base64, ignore
}
}
return null;
}
/**
* Check if image generation is enabled
*/
isEnabled() {
return this.config.enabled;
}
/**
* Get the default model
*/
getModel() {
return this.config.defaultModel;
}
/**
* Get the default provider
*/
getProvider() {
return this.config.defaultProvider;
}
/**
* Get the service configuration
*/
getConfig() {
return { ...this.config };
}
/**
* Get the service instance ID (for debugging)
*/
getInstanceId() {
return this.instanceId;
}
/**
* Update service configuration
*
* @param config - Partial configuration to merge
*/
updateConfig(config) {
this.config = {
...this.config,
...config,
};
}
/**
* Enable image generation
*/
enable() {
this.config.enabled = true;
}
/**
* Disable image generation
*/
disable() {
this.config.enabled = false;
}
}
//# sourceMappingURL=ImageGenService.js.map