@gluneau/n8n-nodes-venice
Version:
Venice.ai integration for n8n
396 lines • 15.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.VeniceImage = void 0;
class VeniceImage {
description = {
displayName: 'Venice Image Generation',
name: 'veniceImageGeneration',
icon: 'file:veniceImage.svg',
group: ['transform'],
version: 1,
description: 'Generate and manipulate images with Venice.ai',
defaults: {
name: 'Venice Image',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'veniceApi',
required: true,
},
],
subtitle: 'Venice',
requestDefaults: {
baseURL: 'https://api.venice.ai/api/v1',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
properties: [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Generate',
value: 'generate',
description: 'Generate a new image from a text prompt',
action: 'Generate a new image from a text prompt',
},
{
name: 'Upscale',
value: 'upscale',
description: 'Upscale or enhance an existing image',
action: 'Upscale or enhance an existing image',
},
],
default: 'generate',
},
{
displayName: 'Model',
name: 'model',
type: 'string',
default: 'venice-sd35',
description: 'The model to use for image generation',
displayOptions: {
show: {
operation: ['generate'],
},
},
required: true,
},
{
displayName: 'Prompt',
name: 'prompt',
type: 'string',
typeOptions: {
rows: 4,
},
default: '',
description: 'A description of what you want to generate',
displayOptions: {
show: {
operation: ['generate'],
},
},
required: true,
},
{
displayName: 'Image',
name: 'image',
type: 'string',
default: '',
description: 'Base64-encoded image to upscale or a URL',
displayOptions: {
show: {
operation: ['upscale'],
},
},
required: true,
},
{
displayName: 'Scale',
name: 'scale',
type: 'number',
typeOptions: {
minValue: 1,
maxValue: 4,
},
default: 2,
description: 'The scale factor for upscaling (1-4)',
displayOptions: {
show: {
operation: ['upscale'],
},
},
},
{
displayName: 'Generation Options',
name: 'generationOptions',
type: 'collection',
displayOptions: {
show: {
operation: ['generate'],
},
},
placeholder: 'Add Option',
default: {},
options: [
{
displayName: 'Width',
name: 'width',
type: 'number',
typeOptions: {
minValue: 64,
maxValue: 1280,
},
default: 1024,
description: 'Width of the generated image',
},
{
displayName: 'Height',
name: 'height',
type: 'number',
typeOptions: {
minValue: 64,
maxValue: 1280,
},
default: 1024,
description: 'Height of the generated image',
},
{
displayName: 'CFG Scale',
name: 'cfg_scale',
type: 'number',
typeOptions: {
minValue: 0.1,
maxValue: 20,
},
default: 7.5,
description: 'How strictly the image should adhere to the prompt',
},
{
displayName: 'Format',
name: 'format',
type: 'options',
options: [
{
name: 'JPEG',
value: 'jpeg',
},
{
name: 'PNG',
value: 'png',
},
{
name: 'WebP',
value: 'webp',
},
],
default: 'webp',
description: 'The image format to return',
},
{
displayName: 'Hide Watermark',
name: 'hide_watermark',
type: 'boolean',
default: false,
description: 'Whether to hide the Venice watermark (may not be honored for all content)',
},
{
displayName: 'Negative Prompt',
name: 'negative_prompt',
type: 'string',
typeOptions: {
rows: 3,
},
default: '',
description: 'Features to exclude from the image',
},
{
displayName: 'Return Binary',
name: 'return_binary',
type: 'boolean',
default: false,
description: 'Whether to return binary image data instead of base64',
},
{
displayName: 'Safe Mode',
name: 'safe_mode',
type: 'boolean',
default: true,
description: 'Whether to blur images classified as having adult content',
},
{
displayName: 'Seed',
name: 'seed',
type: 'number',
default: 0,
description: 'Random seed for generation (0 for random)',
},
{
displayName: 'Steps',
name: 'steps',
type: 'number',
typeOptions: {
minValue: 1,
maxValue: 30,
},
default: 20,
description: 'Number of diffusion steps (higher = more detailed but slower)',
},
{
displayName: 'Style Preset',
name: 'style_preset',
type: 'string',
default: '',
description: 'An image style to apply (e.g., "3D Model", "Analog Film", "Anime")',
},
],
},
{
displayName: 'Upscale Options',
name: 'upscaleOptions',
type: 'collection',
displayOptions: {
show: {
operation: ['upscale'],
},
},
placeholder: 'Add Option',
default: {},
options: [
{
displayName: 'Enhance',
name: 'enhance',
type: 'boolean',
default: false,
description: 'Whether to enhance the image during upscaling',
},
{
displayName: 'Enhance Creativity',
name: 'enhanceCreativity',
type: 'number',
typeOptions: {
minValue: 0,
maxValue: 1,
},
default: 0.5,
description: 'How creative the AI should be when enhancing (0-1)',
},
{
displayName: 'Enhance Prompt',
name: 'enhancePrompt',
type: 'string',
default: '',
description: 'Style to apply during enhancement (e.g., "gold", "marble")',
},
{
displayName: 'Replication',
name: 'replication',
type: 'number',
typeOptions: {
minValue: 0,
maxValue: 1,
},
default: 0.35,
description: 'How strongly lines and noise in the base image are preserved',
},
],
},
],
};
async execute() {
const items = this.getInputData();
const returnData = [];
for (let i = 0; i < items.length; i++) {
try {
const operation = this.getNodeParameter('operation', i);
if (operation === 'generate') {
const model = this.getNodeParameter('model', i);
const prompt = this.getNodeParameter('prompt', i);
const options = this.getNodeParameter('generationOptions', i, {});
const body = {
model,
prompt,
};
Object.assign(body, options);
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'veniceApi', {
method: 'POST',
url: '/image/generate',
body,
json: true,
encoding: options.return_binary ? 'arraybuffer' : undefined,
returnFullResponse: options.return_binary ? true : undefined,
});
if (options.return_binary) {
const newItem = {
json: {},
binary: {},
};
const contentType = response.headers['content-type'];
let fileExtension = 'webp';
if (contentType === 'image/jpeg')
fileExtension = 'jpg';
else if (contentType === 'image/png')
fileExtension = 'png';
else if (options.format) {
if (options.format === 'jpeg')
fileExtension = 'jpg';
else if (options.format === 'png')
fileExtension = 'png';
else if (options.format === 'webp')
fileExtension = 'webp';
}
const fileName = `venice_image_${Date.now()}.${fileExtension}`;
newItem.binary.data = await this.helpers.prepareBinaryData(response.body, fileName, contentType);
newItem.json = {
success: true,
fileName,
fileExtension,
contentType,
size: response.body.length,
};
returnData.push(newItem);
}
else {
returnData.push({ json: response });
}
}
else if (operation === 'upscale') {
const image = this.getNodeParameter('image', i);
const scale = this.getNodeParameter('scale', i);
const options = this.getNodeParameter('upscaleOptions', i, {});
const body = {
image,
scale,
};
Object.assign(body, options);
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'veniceApi', {
method: 'POST',
url: '/image/upscale',
body,
json: true,
encoding: 'arraybuffer',
returnFullResponse: true,
});
const newItem = {
json: {},
binary: {},
};
const contentType = response.headers['content-type'];
let fileExtension = 'png';
if (contentType === 'image/jpeg')
fileExtension = 'jpg';
else if (contentType === 'image/webp')
fileExtension = 'webp';
const fileName = `venice_upscaled_${Date.now()}.${fileExtension}`;
newItem.binary.data = await this.helpers.prepareBinaryData(response.body, fileName, contentType);
newItem.json = {
success: true,
fileName,
fileExtension,
contentType,
size: response.body.length,
scale,
};
returnData.push(newItem);
}
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({ json: { error: error.message } });
continue;
}
throw error;
}
}
return [returnData];
}
}
exports.VeniceImage = VeniceImage;
//# sourceMappingURL=VeniceImage.node.js.map