Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
61d5961
Leonardo AI components
sergio-eliot-rodriguez Sep 13, 2025
1f0e5b4
added unzoom image action
sergio-eliot-rodriguez Sep 13, 2025
43c2645
fixing link errors
sergio-eliot-rodriguez Sep 13, 2025
185b2cd
more lint fixes
sergio-eliot-rodriguez Sep 13, 2025
b52e6af
Merging pull request #18359
jocarino Sep 14, 2025
768d13e
Merging pull request #18361
michelle0927 Sep 14, 2025
cab79a5
Google Sheets - update row refresh fields (#18369)
andrewjschuang Sep 15, 2025
ab578e6
Pipedrive - fix app name (#18370)
andrewjschuang Sep 15, 2025
47cc79a
Pipedrive - pipelineId integer (#18372)
andrewjschuang Sep 15, 2025
39af3b6
Adding app scaffolding for lightspeed_ecom_c_series
danhsiung Sep 15, 2025
53176bc
Adding app scaffolding for financial_data
danhsiung Sep 15, 2025
48338b7
Adding app scaffolding for microsoft_authenticator
danhsiung Sep 16, 2025
cdbc17b
Merging pull request #18345
michelle0927 Sep 16, 2025
4ea8c2e
Merging pull request #18368
michelle0927 Sep 16, 2025
0c0e183
Coinbase Developer Platform - New Wallet Event (#18342)
michelle0927 Sep 16, 2025
8268c0e
Hubspot - update search-crm (#18360)
michelle0927 Sep 16, 2025
d5c554d
Merging pull request #18347
michelle0927 Sep 17, 2025
07aa960
Adding app scaffolding for rundeck
danhsiung Sep 17, 2025
cef1e1b
Merging pull request #18378
luancazarine Sep 17, 2025
3cb8df5
Merging pull request #18382
michelle0927 Sep 17, 2025
6f23e27
Merging pull request #18323
lcaresia Sep 17, 2025
e35feaf
Merging pull request #18377
lcaresia Sep 17, 2025
874a7cf
Merging pull request #18376
lcaresia Sep 17, 2025
f381c67
Adding app scaffolding for etrusted
danhsiung Sep 17, 2025
d11624e
Adding app scaffolding for intelliflo_office
danhsiung Sep 17, 2025
dc3964a
Adding app scaffolding for thoughtspot
danhsiung Sep 17, 2025
bbde963
Adding app scaffolding for kordiam
danhsiung Sep 17, 2025
fc90f7b
Adding app scaffolding for ticketsauce
danhsiung Sep 17, 2025
961dd55
trustpilot fixes (#18152)
Afstkla Sep 17, 2025
e838ebe
Adding app scaffolding for peekalink
danhsiung Sep 17, 2025
85bd98a
18314 twilio (#18350)
luancazarine Sep 17, 2025
2dfb941
Updating LinkedIn API version (#18399)
GTFalcao Sep 17, 2025
ffa140c
Merging pull request #18394
michelle0927 Sep 18, 2025
1884cf0
Databricks API - Jobs action components (#18371)
jcortes Sep 18, 2025
4e0aa1d
Notion property building improvements (#18381)
michelle0927 Sep 18, 2025
5a236a9
Google Business - add debug log (#18407)
andrewjschuang Sep 18, 2025
52c9a94
Notion API Key - update @pipedream/notion version (#18409)
michelle0927 Sep 18, 2025
5e65398
Adding app scaffolding for reduct_video
danhsiung Sep 18, 2025
7073397
Adding app scaffolding for shopware
danhsiung Sep 19, 2025
61539b7
Adding app scaffolding for instamojo
danhsiung Sep 19, 2025
2863b95
Hubspot - bug fix to sources w/ property changes (#18379)
michelle0927 Sep 19, 2025
d15d706
Google sheets type fix (#18411)
GTFalcao Sep 20, 2025
1721bbf
Merging pull request #18393
michelle0927 Sep 21, 2025
0185460
Merging pull request #18408
michelle0927 Sep 21, 2025
72c48a3
Merging pull request #18419
michelle0927 Sep 21, 2025
8b4f66c
Changes per PR Review
sergio-eliot-rodriguez Sep 21, 2025
3260986
Removes leonardo_ai_actions.mdc not indented for merging
sergio-eliot-rodriguez Sep 21, 2025
7a6774b
synced lockfile after install
sergio-eliot-rodriguez Sep 21, 2025
d2d0b88
fully lock form-data for leonardo_ai
sergio-eliot-rodriguez Sep 22, 2025
c04c193
lockfile conflict seems fixed
sergio-eliot-rodriguez Sep 22, 2025
b5f7dce
conflict solving
sergio-eliot-rodriguez Sep 22, 2025
1d35b09
lint fixes
sergio-eliot-rodriguez Sep 22, 2025
18e7669
Chipped down Readme, implemented async options in gen motion
sergio-eliot-rodriguez Sep 23, 2025
6765ddc
Merge remote-tracking branch 'upstream/master' into leonardo_components
sergio-eliot-rodriguez Sep 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions components/leonardo_ai/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Leonardo AI

[Leonardo AI](https://leonardo.ai) is an AI-powered image generation platform that allows you to create stunning images, videos, and 3D models using advanced machine learning models.

## Authentication

To use this component, you'll need to:

1. Sign up for a Leonardo AI account at [leonardo.ai](https://leonardo.ai)
2. Navigate to the API section in your account settings
3. Create an API key
4. Use this API key when connecting the Leonardo AI app in Pipedream

## Actions

### Generate Image
Creates new images from text prompts using Leonardo AI's image generation models.

**Key Features:**
- Customizable image dimensions (256x256 to 1024x1024)
- Multiple model support
- Adjustable guidance scale and inference steps
- Batch generation (1-4 images)
- Seed support for reproducible results

### Generate Motion
Creates motion videos from static images using Leonardo AI's SVD Motion Generation.

**Key Features:**
- Converts static images to motion videos
- Adjustable motion strength
- Seed support for reproducible results

### Unzoom Image
Creates unzoom variations of existing images, expanding the scene beyond the original frame.

**Key Features:**
- Zoom out effect on existing images
- Adjustable zoom level
- Works with generated or uploaded images

### Upload Image
Uploads images to Leonardo AI for use in generations and variations.

**Key Features:**
- Support for image URLs
- Optional image naming
- Integration with other Leonardo AI actions

### Upscale Image
Increases the resolution of images using Leonardo AI's Universal Upscaler.

**Key Features:**
- Multiple upscaling modes (Universal Upscaler, Real-ESRGAN)
- 2x and 4x scale factors
- High-quality image enhancement

## Usage Examples

### Basic Image Generation
```javascript
// Generate a simple image
{
"prompt": "A beautiful sunset over mountains",
"width": 512,
"height": 512,
"numImages": 1
}
```

### Advanced Image Generation
```javascript
// Generate with specific model and settings
{
"prompt": "A cyberpunk cityscape at night",
"modelId": "6bef9f1b-29cb-40c7-b9df-32b51c1f67d3",
"width": 1024,
"height": 1024,
"numImages": 2,
"guidanceScale": "10",
"numInferenceSteps": 30,
"seed": 12345
}
```

### Motion Generation
```javascript
// Create motion from an image
{
"imageId": "generated-image-id-here",
"motionStrength": "0.7",
"seed": 54321
}
```

## API Reference

For detailed information about Leonardo AI's API, visit the [official documentation](https://docs.leonardo.ai/reference).

## Rate Limits

Leonardo AI has the following rate limits:
- Total requests: 1,000 per minute
- Image generation requests: 100 per minute
- Concurrent image generation jobs: 10
- Concurrent model training jobs: 5

## Support

For support with this component or Leonardo AI's API, please refer to:
- [Leonardo AI Documentation](https://docs.leonardo.ai)
- [Leonardo AI Community](https://community.leonardo.ai)
- [Pipedream Support](https://pipedream.com/support)
116 changes: 116 additions & 0 deletions components/leonardo_ai/actions/generate-image/generate-image.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import app from "../../leonardo_ai.app.mjs";

export default {
key: "leonardo_ai-generate-image",
name: "Generate Image",
description: "Generates new images using Leonardo AI's image generation API.",
version: "0.0.5",
type: "action",
props: {
app,
prompt: {
type: "string",
label: "Prompt",
description: "The text prompt describing the image you want to generate.",
},
modelId: {
type: "string",
label: "Model",
description: "The model to use for generation. Leave empty to use the default model.",
async options() {
const models = await this.app.getPlatformModels({});
return models.map((model) => ({
label: model.name || model.id,
value: model.id,
}));
},
optional: true,
},
width: {
type: "integer",
label: "Width",
description: "Width of the generated image in pixels.",
default: 512,
min: 256,
max: 1024,
},
height: {
type: "integer",
label: "Height",
description: "Height of the generated image in pixels.",
default: 512,
min: 256,
max: 1024,
},
numImages: {
type: "integer",
label: "Number of Images",
description: "Number of images to generate (1-4).",
default: 1,
min: 1,
max: 4,
},
guidanceScale: {
type: "string",
label: "Guidance Scale",
description: "How closely the model should follow the prompt. Must be between 1 and 20. Higher values = more adherence to prompt.",
optional: true,
},
numInferenceSteps: {
type: "integer",
label: "Inference Steps",
description: "Number of denoising steps. More steps = higher quality but slower generation.",
default: 20,
min: 10,
max: 50,
optional: true,
},
seed: {
type: "integer",
label: "Seed",
description: "Random seed for reproducible generation. Leave empty for random generation.",
optional: true,
},
},
async run({ $ }) {
const {
prompt,
modelId,
width,
height,
numImages,
guidanceScale,
numInferenceSteps,
seed,
} = this;

const data = {
prompt,
width,
height,
num_images: numImages,
};

if (modelId) {
data.modelId = modelId;
}
if (guidanceScale) {
data.guidance_scale = parseFloat(guidanceScale);
}
if (numInferenceSteps) {
data.num_inference_steps = numInferenceSteps;
}
if (seed) {
data.seed = seed;
}

const response = await this.app.post({
$,
path: "/generations",
data,
});

$.export("$summary", `Successfully generated ${numImages} image(s) with prompt: "${prompt}"`);
return response;
},
};
76 changes: 76 additions & 0 deletions components/leonardo_ai/actions/generate-motion/generate-motion.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import app from "../../leonardo_ai.app.mjs";

export default {
key: "leonardo_ai-generate-motion",
name: "Generate Motion",
description: "Generates a motion (video) from the provided image using Leonardo AI's SVD Motion Generation API.",
version: "0.0.4",
type: "action",
props: {
app,
imageId: {
type: "string",
label: "Image ID",
description: "The ID of the image to generate motion from. This should be a previously generated or uploaded image ID.",
},
Comment on lines 11 to 64
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance we can use async options here to list available images?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This was is tricky because it needs merging two different types of image entities. I'll give a shot.

Copy link
Collaborator Author

@sergio-eliot-rodriguez sergio-eliot-rodriguez Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked—there’s no way to retrieve previously uploaded images. But we could scope async options to only list generated images using this endpoint. Thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to list some options than none at all, so go for it. The description should make this clear though, something like The ID of the image to generate motion from. You can select a previously generated image, or pass the ID of a previously uploaded image.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, an async options method was implemented for imageId showing options for image generations and description was modified accordingly.

motionStrength: {
type: "integer",
label: "Motion Strength",
description: "The motion strength for the video generation.",
optional: true,
},
isPublic: {
type: "boolean",
label: "Is Public",
description: "Whether the generation is public or not.",
optional: true,
},
isInitImage: {
type: "boolean",
label: "Is Init Image",
description: "If it is an init image uploaded by the user.",
optional: true,
},
isVariation: {
type: "boolean",
label: "Is Variation",
description: "If it is a variation image.",
optional: true,
},
},
async run({ $ }) {
const {
imageId,
motionStrength,
isPublic,
isInitImage,
isVariation,
} = this;

const data = {
imageId,
};

if (motionStrength !== undefined) {
data.motionStrength = motionStrength;
}
if (isPublic !== undefined) {
data.isPublic = isPublic;
}
if (isInitImage !== undefined) {
data.isInitImage = isInitImage;
}
if (isVariation !== undefined) {
data.isVariation = isVariation;
}

const response = await this.app.post({
$,
path: "/generations-motion-svd",
data,
});

$.export("$summary", `Successfully generated motion from image ID: ${imageId}`);
return response;
},
};
26 changes: 26 additions & 0 deletions components/leonardo_ai/actions/leonardo_ai_actions.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
alwaysApply: true
---
leonardo-ai
URLs
https://docs.leonardo.ai/reference
Actions
generate-motion
Prompt
Generates a motion (video) from the provided image (any type).

generate-image
Prompt
Generates new images.

unzoom-image
Prompt
Creates an unzoom variation for a generated or variation image.

upload-image
Prompt
Uploads a new image.

upscale-image
Prompt
Creates a high-resolution upscale (Universal Upscaler) of the provided image (any type).
43 changes: 43 additions & 0 deletions components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import app from "../../leonardo_ai.app.mjs";

export default {
key: "leonardo_ai-unzoom-image",
name: "Unzoom Image",
description: "Creates an unzoom variation for a generated or variation image using Leonardo AI's unzoom API.",
version: "0.0.2",
type: "action",
props: {
app,
imageId: {
type: "string",
label: "Image ID",
description: "The ID of the image to create an unzoom variation for. This should be a previously generated or variation image ID.",
},
isVariation: {
type: "boolean",
label: "Is Variation",
description: "Whether the image is a variation image.",
default: false,
},
},
async run({ $ }) {
const {
imageId,
isVariation,
} = this;

const data = {
id: imageId,
isVariation,
};

const response = await this.app.post({
$,
path: "/variations/unzoom",
data,
});

$.export("$summary", `Successfully created unzoom variation for image ID: ${imageId}`);
return response;
},
};
Loading
Loading