-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Leonardo components #18362
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Leonardo components #18362
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
WalkthroughAdds a Leonardo AI component: documentation, five new actions (generate-image, generate-motion, unzoom-image, upload-image, upscale-image), a refactored app client with generic request helpers and upload helpers, and package.json dependency and version updates; removes legacy authKeys. No triggers added. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Action as Generate Image Action
participant App as Leonardo App Client
participant API as Leonardo REST API
User->>Action: Provide prompt, modelId, dimensions, options
Action->>App: _makeRequest(method: POST, path: /generations, data)
App->>API: POST /generations (with headers from _getHeaders)
API-->>App: Generation response
App-->>Action: Response
Action-->>User: Export summary + API response
sequenceDiagram
autonumber
actor User
participant Upload as Upload Image Action
participant App as Leonardo App Client
participant API as Leonardo REST API
participant Storage as Presigned Storage
User->>Upload: filePath, extension
Upload->>App: getUploadInitImage({ extension })
App->>API: POST /upload/init
API-->>App: { uploadUrl, fields, uploadInitImage }
App-->>Upload: upload init data
Upload->>Storage: POST multipart (fields then file stream) to uploadUrl
Storage-->>Upload: uploadResult (HTTP 200/201)
Upload-->>User: Export summary + { uploadInitImage, uploadResult }
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal). Please share your feedback with us on this Discord post. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Thank you so much for submitting this! We've added it to our backlog to review, and our team has been notified. |
Thanks for submitting this PR! When we review PRs, we follow the Pipedream component guidelines. If you're not familiar, here's a quick checklist:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (18)
components/leonardo_ai/package.json (1)
4-4
: Description overpromises 3D support not implemented in this PRNo 3D actions shipped here. Tighten scope to images and motion to avoid misleading users.
- "description": "Pipedream Leonardo AI Components - Generate images, videos, and 3D models with AI", + "description": "Pipedream Leonardo AI Components - Generate images and motion with AI",components/leonardo_ai/leonardo_ai.app.mjs (2)
59-65
: Platform models response shape: add fallbackDocs often return
platform_models
(or adata
wrapper). Add fallbacks to prevent empty results.- return data.custom_models || []; + return data.custom_models + || data.platform_models + || data.data + || [];
96-103
: Large uploads: set maxBodyLengthS3-style presigned uploads can exceed default Axios limits.
const response = await axios($, { url, method: "POST", data: formData, headers: { ...formData.getHeaders(), }, + maxBodyLength: Infinity, });
components/leonardo_ai/actions/upscale-image/upscale-image.mjs (1)
9-16
: Expose optional upscale params (mode/scale) behind propsDocs mention multiple upscaling modes and 2x/4x. Consider optional props to pass through without breaking current behavior.
props: { app, imageId: { type: "string", label: "Image ID", description: "The ID of the image to upscale. This should be a previously generated or uploaded image ID.", }, + scale: { + type: "integer", + label: "Scale", + description: "Upscale factor", + options: [2, 4], + optional: true, + }, + mode: { + type: "string", + label: "Mode", + options: ["universal", "real-esrgan"], + optional: true, + }, }, async run({ $ }) { const { imageId } = this; const data = { id: imageId, + ...(this.scale ? { scale: this.scale } : {}), + ...(this.mode ? { mode: this.mode } : {}), };Also applies to: 20-28
components/leonardo_ai/actions/upload-image/upload-image.mjs (6)
2-2
: Remove unused import
axios
is not used in this action.-import { axios } from "@pipedream/platform";
34-34
: Drop stray console.logAvoid noisy logs in actions.
- console.log(extension);
36-37
: Robust base64 data URI handlingSupport case-insensitive media subtypes and raw base64 strings.
- const base64Data = file.replace(/^data:image\/[a-z]+;base64,/, ''); + const base64Data = file.replace(/^data:(?:image\/[a-z0-9.+-]+);base64,/i, "");
40-44
: Minor: simplify MIME mappingTighten jpg→jpeg mapping.
- const fileObject = { - buffer: buffer, - name: `image.${extension}`, - type: `image/${extension === 'jpg' ? 'jpeg' : extension}`, - }; + const mime = extension === "jpg" ? "jpeg" : extension; + const fileObject = { buffer, name: `image.${extension}`, type: `image/${mime}` };
52-55
: Defensive parsing of presigned fieldsSome APIs return
fields
as an object. Handle both cases.- const { uploadInitImage } = uploadResponse; - const fields = JSON.parse(uploadInitImage.fields); - const uploadUrl = uploadInitImage.url; + const { uploadInitImage } = uploadResponse; + const uploadUrl = uploadInitImage.url; + const fields = typeof uploadInitImage.fields === "string" + ? JSON.parse(uploadInitImage.fields) + : uploadInitImage.fields;
16-21
: ESLint: object properties on new linesFormat option objects per lint rules.
- { label: "PNG", value: "png" }, - { label: "JPG", value: "jpg" }, - { label: "JPEG", value: "jpeg" }, - { label: "WebP", value: "webp" }, + { + label: "PNG", + value: "png", + }, + { + label: "JPG", + value: "jpg", + }, + { + label: "JPEG", + value: "jpeg", + }, + { + label: "WebP", + value: "webp", + },components/leonardo_ai/README.md (3)
53-57
: Upscale capabilities overstatedCurrent action doesn’t expose modes or scale factors. Adjust docs or add props.
**Key Features:** -- Multiple upscaling modes (Universal Upscaler, Real-ESRGAN) -- 2x and 4x scale factors -- High-quality image enhancement +- High-quality image enhancement of an existing image ID
96-99
: Link to specific endpoint docsPoint to endpoint pages for the actions added.
-For detailed information about Leonardo AI's API, visit the [official documentation](https://docs.leonardo.ai/reference). +For detailed information about Leonardo AI's API, visit the [official documentation](https://docs.leonardo.ai/reference), including Generations, Variations, Motion, and Upload endpoints.
1-114
: Confirmed endpoints in official docs — minor README example fixes recommendedOfficial docs (docs.leonardo.ai) document these endpoints and example request bodies: POST /generations, POST /generations-motion-svd, POST /variations/unzoom, POST /variations/upscale, POST /init-image (presigned upload init), and GET /platformModels. Action: update README examples in components/leonardo_ai/README.md (lines 1–114) to exactly match the official request-body shapes and types (e.g., use numeric types for numeric params like guidanceScale, motionStrength, numImages/numInferenceSteps/seed and ensure field names match the docs).
components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (1)
29-32
: SendisVariation
only when true to avoid unnecessary payload fields.Slightly cleaner and avoids surprising APIs that treat falsey flags differently.
- const data = { - id: imageId, - isVariation, - }; + const data = { id: imageId }; + if (isVariation) data.isVariation = true;components/leonardo_ai/actions/generate-motion/generate-motion.mjs (2)
16-21
: Add bounds formotionStrength
.Expose UI hints (min/max) to prevent invalid requests and guide users.
motionStrength: { type: "integer", label: "Motion Strength", - description: "The motion strength for the video generation.", + description: "The motion strength for the video generation.", + min: 1, + max: 10, optional: true, },
22-27
: Consider defaultingisPublic
to false.Prevents accidental public generations if the API defaults differ from expectations.
isPublic: { type: "boolean", label: "Is Public", description: "Whether the generation is public or not.", - optional: true, + optional: true, + default: false, },components/leonardo_ai/actions/generate-image/generate-image.mjs (2)
39-39
: Fix lint: trailing space on thelabel
line.This is breaking the PR checks.
- label: "Height", + label: "Height",
97-99
: Validate and guardguidanceScale
to avoid sendingNaN
or out-of-range values.Parses safely and enforces the documented 1–20 range.
- if (guidanceScale) { - data.guidance_scale = parseFloat(guidanceScale); - } + if (guidanceScale !== undefined && guidanceScale !== "") { + const gs = parseFloat(guidanceScale); + if (Number.isNaN(gs)) { + throw new Error("Guidance Scale must be a number between 1 and 20."); + } + if (gs < 1 || gs > 20) { + throw new Error("Guidance Scale must be between 1 and 20."); + } + data.guidance_scale = gs; + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
components/leonardo_ai/README.md
(1 hunks)components/leonardo_ai/actions/generate-image/generate-image.mjs
(1 hunks)components/leonardo_ai/actions/generate-motion/generate-motion.mjs
(1 hunks)components/leonardo_ai/actions/leonardo_ai_actions.mdc
(1 hunks)components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs
(1 hunks)components/leonardo_ai/actions/upload-image/upload-image.mjs
(1 hunks)components/leonardo_ai/actions/upscale-image/upscale-image.mjs
(1 hunks)components/leonardo_ai/leonardo_ai.app.mjs
(1 hunks)components/leonardo_ai/package.json
(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
components/leonardo_ai/actions/generate-motion/generate-motion.mjs (4)
components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (2)
data
(29-32)response
(34-38)components/leonardo_ai/actions/generate-image/generate-image.mjs (2)
data
(87-92)response
(107-111)components/leonardo_ai/actions/upscale-image/upscale-image.mjs (2)
data
(20-22)response
(24-28)components/leonardo_ai/leonardo_ai.app.mjs (3)
data
(60-63)data
(67-73)response
(96-103)
components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (4)
components/leonardo_ai/actions/generate-image/generate-image.mjs (2)
data
(87-92)response
(107-111)components/leonardo_ai/actions/generate-motion/generate-motion.mjs (2)
data
(50-52)response
(67-71)components/leonardo_ai/actions/upscale-image/upscale-image.mjs (2)
data
(20-22)response
(24-28)components/leonardo_ai/leonardo_ai.app.mjs (3)
data
(60-63)data
(67-73)response
(96-103)
components/leonardo_ai/actions/upscale-image/upscale-image.mjs (4)
components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (2)
data
(29-32)response
(34-38)components/leonardo_ai/actions/generate-image/generate-image.mjs (2)
data
(87-92)response
(107-111)components/leonardo_ai/actions/generate-motion/generate-motion.mjs (2)
data
(50-52)response
(67-71)components/leonardo_ai/leonardo_ai.app.mjs (3)
data
(60-63)data
(67-73)response
(96-103)
components/leonardo_ai/actions/generate-image/generate-image.mjs (1)
components/leonardo_ai/leonardo_ai.app.mjs (3)
data
(60-63)data
(67-73)response
(96-103)
components/leonardo_ai/leonardo_ai.app.mjs (5)
components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (2)
data
(29-32)response
(34-38)components/leonardo_ai/actions/generate-image/generate-image.mjs (2)
data
(87-92)response
(107-111)components/leonardo_ai/actions/generate-motion/generate-motion.mjs (2)
data
(50-52)response
(67-71)components/leonardo_ai/actions/upscale-image/upscale-image.mjs (2)
data
(20-22)response
(24-28)components/leonardo_ai/actions/upload-image/upload-image.mjs (1)
fields
(53-53)
🪛 GitHub Actions: Pull Request Checks
components/leonardo_ai/README.md
[warning] File ignored because of a matching ignore pattern. Use '--no-ignore' to disable file ignore settings or use '--no-warn-ignored' to suppress this warning. Command: pnpm exec eslint components/leonardo_ai/README.md components/leonardo_ai/actions/generate-image/generate-image.mjs components/leonardo_ai/actions/generate-motion/generate-motion.mjs components/leonardo_ai/actions/leonardo_ai_actions.mdc components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs components/leonardo_ai/actions/upload-image/upload-image.mjs components/leonardo_ai/actions/upscale-image/upscale-image.mjs components/leonardo_ai/leonardo_ai.app.mjs components/leonardo_ai/package.json
components/leonardo_ai/actions/generate-image/generate-image.mjs
[error] 39-39: Trailing spaces not allowed (no-trailing-spaces). Command: pnpm exec eslint components/leonardo_ai/README.md components/leonardo_ai/actions/generate-image/generate-image.mjs components/leonardo_ai/actions/generate-motion/generate-motion.mjs components/leonardo_ai/actions/leonardo_ai_actions.mdc components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs components/leonardo_ai/actions/upload-image/upload-image.mjs components/leonardo_ai/actions/upscale-image/upscale-image.mjs components/leonardo_ai/leonardo_ai.app.mjs components/leonardo_ai/package.json
🪛 GitHub Check: Lint Code Base
components/leonardo_ai/actions/generate-image/generate-image.mjs
[failure] 39-39:
Trailing spaces not allowed
components/leonardo_ai/actions/upload-image/upload-image.mjs
[failure] 19-19:
Object properties must go on a new line
[failure] 19-19:
Expected a line break after this opening brace
[failure] 18-18:
Expected a line break before this closing brace
[failure] 18-18:
Object properties must go on a new line
[failure] 18-18:
Expected a line break after this opening brace
[failure] 17-17:
Expected a line break before this closing brace
[failure] 17-17:
Object properties must go on a new line
[failure] 17-17:
Expected a line break after this opening brace
[failure] 2-2:
'axios' is defined but never used
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Publish TypeScript components
- GitHub Check: Verify TypeScript components
- GitHub Check: pnpm publish
🔇 Additional comments (9)
components/leonardo_ai/package.json (2)
17-17
: License alignment with repoConfirm this package’s MIT license matches the monorepo’s overall license and publishing intent.
Would you like me to update this to match the repo’s root license if different?
18-20
: Publishing config: verify intent to publish to npmIf this package isn't meant for npm, remove
publishConfig
to avoid accidental publishes.- "publishConfig": { - "access": "public" - }, + // "publishConfig": { "access": "public" },components/leonardo_ai/leonardo_ai.app.mjs (2)
66-75
: Return shape vs. action expectation
getUploadInitImage
returnsdata
, while the action destructures{ uploadInitImage }
. Ensure shapes match.Option A (return just the object expected by actions):
- const data = await this.post({ $, path: "/init-image", data: { extension } }); - return data; + const data = await this.post({ $, path: "/init-image", data: { extension } }); + return data.uploadInitImage ?? data;If API differs, update the action accordingly.
9-11
: Endpoints naming/paths: confirmed against Leonardo API docsAll listed endpoints exist; docs/examples for request/response shapes:
- GET /platformModels — List platform models. Doc: https://github.com/Leonardo-Interactive/leonardo-ts-sdk/blob/main/docs/sdks/models/README.md?utm_source=openai
- POST /init-image — Upload init image (returns presigned upload fields + initImageId). Doc: https://docs.leonardo.ai/reference/uploadinitimage?utm_source=openai
- POST /variations/upscale — Universal Upscaler (upscale variations). Doc: https://docs.leonardo.ai/docs/image-variations-with-universal-upscaler?utm_source=openai
- POST /variations/unzoom — Unzoom job (sdUnzoomJob response). Doc: https://leonardo.apidog.io/api-8962897?utm_source=openai
- POST /generations-motion-svd — Motion generation (Motion 1.0). Doc: https://docs.leonardo.ai/docs/generate-motion-using-uploaded-images?utm_source=openai
- POST /generations — Create image generations (Alchemy). Doc: https://docs.leonardo.ai/docs/generate-images-using-alchemy?utm_source=openai
File: components/leonardo_ai/leonardo_ai.app.mjs — lines 9–11, 59–70, 106.
components/leonardo_ai/actions/upscale-image/upscale-image.mjs (1)
24-31
: LGTM for basic upscale callStraightforward call with summary export looks good.
components/leonardo_ai/actions/upload-image/upload-image.mjs (1)
46-55
: Return shape coupling with app methodThis action assumes
getUploadInitImage
returns{ uploadInitImage }
. Confirm API response or harmonize app method to return that shape.I can align both sides once we confirm the API payload.
components/leonardo_ai/README.md (1)
19-25
: Generate Image features may be inaccurateDocs list guidance scale, inference steps, seed, model selection, but the action snippet shows only prompt/size/count. Align docs with actual props.
I can update the README once the action’s final prop set is confirmed.
components/leonardo_ai/actions/leonardo_ai_actions.mdc (1)
1-26
: Catalog entries look good and match the implemented actions.No functional concerns from this static metadata.
components/leonardo_ai/actions/generate-motion/generate-motion.mjs (1)
67-71
: Confirmed: endpoint and payload are correct.POST https://cloud.leonardo.ai/api/rest/v1/generations-motion-svd accepts JSON fields imageId, motionStrength, isPublic, isInitImage, and isVariation — use the imageId from "Get Single Generation" (not the generationId).
components/leonardo_ai/actions/generate-image/generate-image.mjs
Outdated
Show resolved
Hide resolved
_getHeaders() { | ||
return { | ||
"Content-Type": "application/json", | ||
"Authorization": `Bearer ${this.$auth.api_key}`, | ||
"Accept": "application/json", | ||
}; | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid forcing Content-Type globally
Setting Content-Type: application/json
for all verbs complicates non‑JSON requests. Let POST/PUT set it when needed.
- _getHeaders() {
+ _getHeaders() {
return {
- "Content-Type": "application/json",
"Authorization": `Bearer ${this.$auth.api_key}`,
"Accept": "application/json",
};
},
+ _jsonHeaders() {
+ return { "Content-Type": "application/json" };
+ },
And in post(...)
:
- method: "POST",
- data,
+ method: "POST",
+ data,
+ headers: { ...this._jsonHeaders() },
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
_getHeaders() { | |
return { | |
"Content-Type": "application/json", | |
"Authorization": `Bearer ${this.$auth.api_key}`, | |
"Accept": "application/json", | |
}; | |
}, | |
_getHeaders() { | |
return { | |
"Authorization": `Bearer ${this.$auth.api_key}`, | |
"Accept": "application/json", | |
}; | |
}, | |
_jsonHeaders() { | |
return { "Content-Type": "application/json" }; | |
}, |
🤖 Prompt for AI Agents
In components/leonardo_ai/leonardo_ai.app.mjs around lines 12 to 18, the helper
_getHeaders() force-sets "Content-Type: application/json" for all requests which
breaks non-JSON verbs; remove "Content-Type" from the global headers returned by
_getHeaders(), keep Authorization and Accept, and ensure request-specific
methods (e.g., post and put) add "Content-Type: application/json" only when
sending a JSON body; also make those methods merge any caller-supplied headers
so they do not get overwritten and only set the content-type if not already
provided.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (2)
components/leonardo_ai/leonardo_ai.app.mjs (2)
12-18
: Don't set Content-Type globally; add JSON-specific helper insteadForcing Content-Type: application/json on all requests breaks multipart/form-data and other non‑JSON calls. Define JSON headers separately.
_getHeaders() { - return { - "Content-Type": "application/json", - "Authorization": `Bearer ${this.$auth.api_key}`, - "Accept": "application/json", - }; + return { + "Authorization": `Bearer ${this.$auth.api_key}`, + "Accept": "application/json", + }; }, + _jsonHeaders() { + return { "Content-Type": "application/json" }; + },
22-27
: Caller headers are overwritten; merge them so callers can set per‑request headersAs written, opts.headers are dropped. Merge defaults with user headers, letting user values override.
- return axios($, { - ...opts, - url: `${this._baseUrl()}${path}`, - headers: this._getHeaders(), - }); + const { headers: userHeaders, ...rest } = opts || {}; + return axios($, { + ...rest, + url: `${this._baseUrl()}${path}`, + headers: { + ...this._getHeaders(), + ...(userHeaders || {}), + }, + });
🧹 Nitpick comments (4)
components/leonardo_ai/leonardo_ai.app.mjs (2)
28-37
: Ensure JSON POSTs set Content-Type only when neededWith Content-Type removed from global headers, set it here and still allow caller override.
async post({ $ = this, path, data, ...opts }) { return this._makeRequest({ $, path, method: "POST", data, + headers: { + ...this._jsonHeaders(), + ...(opts?.headers || {}), + }, ...opts, }); },
103-110
: Large uploads: raise limits and set a sensible timeoutPrevent axios from choking on bigger files and avoid hanging requests.
const response = await axios($, { url, method: "POST", data: formData, headers: { ...formData.getHeaders(), }, + maxBodyLength: Infinity, + maxContentLength: Infinity, + timeout: 60000, });components/leonardo_ai/actions/upload-image/upload-image.mjs (2)
46-46
: Drop debug logAvoid noisy console output in actions.
- console.log(extension);
67-70
: Handle both string and object forms of fieldsSome APIs return fields as an object already. Be tolerant to both.
- const fields = JSON.parse(uploadInitImage.fields); + const fields = typeof uploadInitImage.fields === "string" + ? JSON.parse(uploadInitImage.fields) + : uploadInitImage.fields;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
components/leonardo_ai/actions/generate-image/generate-image.mjs
(1 hunks)components/leonardo_ai/actions/upload-image/upload-image.mjs
(1 hunks)components/leonardo_ai/leonardo_ai.app.mjs
(1 hunks)components/leonardo_ai/package.json
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- components/leonardo_ai/package.json
- components/leonardo_ai/actions/generate-image/generate-image.mjs
🧰 Additional context used
🧬 Code graph analysis (1)
components/leonardo_ai/leonardo_ai.app.mjs (5)
components/leonardo_ai/actions/generate-image/generate-image.mjs (2)
data
(87-92)response
(107-111)components/leonardo_ai/actions/generate-motion/generate-motion.mjs (2)
data
(50-52)response
(67-71)components/leonardo_ai/actions/upscale-image/upscale-image.mjs (2)
data
(20-22)response
(24-28)components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (2)
data
(29-32)response
(34-38)components/leonardo_ai/actions/upload-image/upload-image.mjs (1)
fields
(68-68)
🪛 GitHub Check: Lint Code Base
components/leonardo_ai/actions/upload-image/upload-image.mjs
[failure] 57-57:
Expected indentation of 10 spaces but found 8
[failure] 56-56:
Trailing spaces not allowed
[failure] 49-49:
Strings must use doublequote
[failure] 48-48:
Strings must use doublequote
[failure] 31-31:
Missing trailing comma
[failure] 31-31:
Trailing spaces not allowed
[failure] 27-27:
Missing trailing comma
[failure] 23-23:
Missing trailing comma
[failure] 19-19:
Missing trailing comma
[failure] 2-2:
'axios' is defined but never used
🪛 GitHub Actions: Pull Request Checks
components/leonardo_ai/actions/upload-image/upload-image.mjs
[error] 2-2: ESLint: 'axios' is defined but never used. (no-unused-vars)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Verify TypeScript components
- GitHub Check: pnpm publish
- GitHub Check: Publish TypeScript components
🔇 Additional comments (1)
components/leonardo_ai/leonardo_ai.app.mjs (1)
59-65
: Verify response shape from /platformModelsReturning data.custom_models may be incorrect depending on API. Confirm actual field and provide resilient fallback.
- return data.custom_models || []; + return data?.custom_models ?? data?.models ?? data?.platformModels ?? [];If you want, I can cross-check the latest Leonardo API docs and update accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @sergio-eliot-rodriguez , I've left some comments for you to check out. Some of them apply to multiple components, make sure they're all following the same standards.
components/leonardo_ai/actions/generate-image/generate-image.mjs
Outdated
Show resolved
Hide resolved
components/leonardo_ai/actions/generate-image/generate-image.mjs
Outdated
Show resolved
Hide resolved
async uploadFileToPresignedUrl({ | ||
$, url, fields, file, | ||
}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can reuse the base request method just fine, as long as you don't overwrite the headers there. Have a look at similar components that use form-data requests. Normally you build the FormData object within the action itself instead of here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sergio-eliot-rodriguez can you refactor this one to use _makeRequest
? Or is there something that prevents it in this specific case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Needed some abstractions because of the formdata object and the preseigned url needed to be pass as is and is different from the usual api url. It is refactored now.
* fix: pagination prop and params struct * fix: no need for paginate here * chore: update version * chore: cleanup * chore: update package * feat: allow raw response * chore: bump package * fix: buffer response instead * Update components/google_drive/actions/download-file/download-file.mjs Co-authored-by: Jorge Cortes <[email protected]> * versions * pnpm-lock.yaml * pnpm-lock.yaml * pnpm-lock.yaml * feat: add content selector * chore: bump package * fix: comments * chore: bump versions * chore: fix versions * fixes: QA fixes * feat: add cursor to req * package.json --------- Co-authored-by: joao <[email protected]> Co-authored-by: joaocoform <[email protected]> Co-authored-by: Jorge Cortes <[email protected]> Co-authored-by: Michelle Bergeron <[email protected]> Co-authored-by: Luan Cazarine <[email protected]>
* update siteId prop * pnpm-lock.yaml * package.json version
* change prop order and refresh fields * bump package.json
* use pipedriveApp instead of app * bump package.json
* pipelineId - integer * bump versions
* updates * versions * versions
* updates * remove console.log * versions
* new component * pnpm-lock.yaml * updates * updates
* update search-crm * limit results to one page * update version * package.json version
* widget props * fix version
* Update Taiga component with new actions and sources - Bump version to 0.1.0 in package.json and add dependency on @pipedream/platform. - Introduce new actions for creating, updating, and deleting issues, tasks, and user stories. - Add sources for tracking changes and deletions of issues and tasks. - Implement utility functions for parsing and cleaning objects in common/utils.mjs. - Enhance prop definitions for better integration with Taiga API. * pnpm update * Refactor Taiga actions to utilize parseObject utility - Added parseObject utility for tags, watchers, and points in update-issue, update-task, and update-userstory actions. - Removed the update-project action as it is no longer needed. - Enhanced base source to include secret key validation for webhook security.
* add testSources prop * pnpm-lock.yaml * fix
* Added actions * Added actions * Added actions
* Added actions * Update components/weaviate/actions/create-class/create-class.mjs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: Luan Cazarine <[email protected]> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* validate property types * versions
* add debug log * bump versions
* update @pipedream/notion dependency version * pnpm-lock.yaml
* updates * versions
* Fixing worksheetId prop type from string to integer * Version bumps --------- Co-authored-by: Leo Vu <[email protected]>
* new components * remove console.log * versions * update
* 403 error message * versions * update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
components/leonardo_ai/leonardo_ai.app.mjs (1)
62-69
: Allow large multipart uploads.For presigned S3 POSTs, axios needs relaxed limits for big files.
const response = await axios($, { url, method: "POST", data: formData, headers: { ...formData.getHeaders(), }, + maxContentLength: Infinity, + maxBodyLength: Infinity, });components/leonardo_ai/actions/upload-image/upload-image.mjs (1)
65-73
: Make fields parsing resilient (string or object).Leonardo/S3 responses sometimes return
fields
as an object. Guard against double‑parse.- const { uploadInitImage } = uploadResponse; - const fields = JSON.parse(uploadInitImage.fields); + const { uploadInitImage } = uploadResponse; + const fields = typeof uploadInitImage.fields === "string" + ? JSON.parse(uploadInitImage.fields) + : uploadInitImage.fields;components/leonardo_ai/actions/generate-motion/generate-motion.mjs (1)
22-39
: Consider adding optional callback URL.If the endpoint supports a callback, expose
callbackUrl
to help users chain workflows without polling.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
components/leonardo_ai/README.md
(1 hunks)components/leonardo_ai/actions/generate-image/generate-image.mjs
(1 hunks)components/leonardo_ai/actions/generate-motion/generate-motion.mjs
(1 hunks)components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs
(1 hunks)components/leonardo_ai/actions/upload-image/upload-image.mjs
(1 hunks)components/leonardo_ai/actions/upscale-image/upscale-image.mjs
(1 hunks)components/leonardo_ai/leonardo_ai.app.mjs
(1 hunks)components/leonardo_ai/package.json
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- components/leonardo_ai/actions/upscale-image/upscale-image.mjs
- components/leonardo_ai/package.json
- components/leonardo_ai/README.md
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#18362
File: components/leonardo_ai/README.md:45-49
Timestamp: 2025-09-15T22:01:17.593Z
Learning: In Leonardo AI components (and likely other Pipedream components), prefer using info alert props on the component itself rather than detailed "Key Features" sections in README files for action documentation.
📚 Learning: 2025-09-15T22:01:11.472Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#18362
File: components/leonardo_ai/actions/generate-image/generate-image.mjs:103-105
Timestamp: 2025-09-15T22:01:11.472Z
Learning: In Pipedream components, pipedream/platform's axios implementation automatically excludes undefined values from HTTP requests, so there's no need to manually check for truthiness before including properties in request payloads.
Applied to files:
components/leonardo_ai/leonardo_ai.app.mjs
components/leonardo_ai/actions/upload-image/upload-image.mjs
components/leonardo_ai/actions/generate-image/generate-image.mjs
📚 Learning: 2025-01-29T22:59:38.825Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#15436
File: components/printful/printful.app.mjs:55-63
Timestamp: 2025-01-29T22:59:38.825Z
Learning: Console.log statements should be removed before merging PRs to maintain code quality and prevent potential security risks from exposing sensitive information in logs.
Applied to files:
components/leonardo_ai/actions/upload-image/upload-image.mjs
🧬 Code graph analysis (4)
components/leonardo_ai/leonardo_ai.app.mjs (5)
components/leonardo_ai/actions/generate-image/generate-image.mjs (2)
data
(90-99)response
(101-106)components/leonardo_ai/actions/generate-motion/generate-motion.mjs (2)
data
(50-56)response
(58-63)components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (2)
data
(29-32)response
(34-39)components/leonardo_ai/actions/upscale-image/upscale-image.mjs (2)
data
(20-22)response
(24-29)components/leonardo_ai/actions/upload-image/upload-image.mjs (1)
formData
(67-67)
components/leonardo_ai/actions/generate-motion/generate-motion.mjs (4)
components/leonardo_ai/actions/generate-image/generate-image.mjs (2)
data
(90-99)response
(101-106)components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (2)
data
(29-32)response
(34-39)components/leonardo_ai/actions/upscale-image/upscale-image.mjs (2)
data
(20-22)response
(24-29)components/leonardo_ai/leonardo_ai.app.mjs (3)
data
(40-43)data
(49-56)response
(62-69)
components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (4)
components/leonardo_ai/actions/generate-image/generate-image.mjs (2)
data
(90-99)response
(101-106)components/leonardo_ai/actions/generate-motion/generate-motion.mjs (2)
data
(50-56)response
(58-63)components/leonardo_ai/actions/upscale-image/upscale-image.mjs (2)
data
(20-22)response
(24-29)components/leonardo_ai/leonardo_ai.app.mjs (3)
data
(40-43)data
(49-56)response
(62-69)
components/leonardo_ai/actions/generate-image/generate-image.mjs (1)
components/leonardo_ai/leonardo_ai.app.mjs (3)
data
(40-43)data
(49-56)response
(62-69)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Lint Code Base
- GitHub Check: Publish TypeScript components
- GitHub Check: pnpm publish
- GitHub Check: Verify TypeScript components
🔇 Additional comments (7)
components/leonardo_ai/leonardo_ai.app.mjs (2)
12-18
: Don’t set Content-Type globally; set JSON only when appropriate.Global
"Content-Type": "application/json"
breaks/burdens non‑JSON requests. Add JSON content type only for JSON bodies; keep_getHeaders()
lean. Also, add a sane timeout and avoid clobbering user-provided content-type.@@ _getHeaders() { return { - "Content-Type": "application/json", "Authorization": `Bearer ${this.$auth.api_key}`, "Accept": "application/json", }; }, @@ async _makeRequest({ $ = this, method = "GET", path, data, ...opts }) { const { headers: userHeaders, ...rest } = opts; - const config = { + const baseHeaders = { + ...this._getHeaders(), + ...(userHeaders || {}), + }; + // Add JSON content-type only when sending a plain JSON body and the caller didn't set one + const needsJson = + ["POST","PUT","PATCH"].includes(String(method).toUpperCase()) && + data !== undefined && + !(data && typeof data.getHeaders === "function") && + !Object.keys(baseHeaders).some((h) => h.toLowerCase() === "content-type"); + const headers = needsJson + ? { "Content-Type": "application/json", ...baseHeaders } + : baseHeaders; + + const config = { method, ...rest, url: `${this._baseUrl()}${path}`, - headers: { - ...this._getHeaders(), - ...(userHeaders || {}), - }, + headers, data, + timeout: 30000, }; return await axios($, config); },Also applies to: 19-38
39-45
: Verify response shape from /platformModels.You return
data.custom_models || []
. If the API returns a different key (e.g.,platformModels
), this will silently return an empty list.Would you confirm the exact response shape and adjust accordingly?
components/leonardo_ai/actions/upload-image/upload-image.mjs (2)
80-86
: LGTM overall.Two‑step presigned flow, field ordering, and FormData construction look correct.
54-57
: Don't pass this.syncDir — helper has a single-arg signature. getFileStreamAndMetadata is declared as getFileStreamAndMetadata(pathOrUrl: string) in platform/lib/file-stream.ts:43 and does not accept a second parameter; to forward this.syncDir you must change that helper and update all callers (e.g. components/leonardo_ai/actions/upload-image/upload-image.mjs:57).Likely an incorrect or invalid review comment.
components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (1)
34-39
: LGTM.Clean payload mapping and summary. Defaults sensible.
components/leonardo_ai/actions/generate-image/generate-image.mjs (1)
101-106
: LGTM otherwise.Payload mapping and options source look consistent with the app client.
components/leonardo_ai/actions/generate-motion/generate-motion.mjs (1)
41-56
: Validate mutually-exclusive flags; defer motionStrength range enforcement until API-confirmed.Docs show motionStrength is an integer but no published min/max — enforce isInitImage XOR isVariation now; confirm numeric bounds with the API/support before enforcing a range.
File: components/leonardo_ai/actions/generate-motion/generate-motion.mjs Lines: 41-56
async run({ $ }) { const { imageId, motionStrength, isPublic, isInitImage, isVariation, } = this; + if (isInitImage && isVariation) { + throw new Error("Choose either 'Is Init Image' or 'Is Variation', not both."); + } + // TODO: enforce allowed range once confirmed (e.g., 1–10) + // if (motionStrength !== undefined && (motionStrength < 1 || motionStrength > 10)) { + // throw new Error("Motion Strength must be between 1 and 10."); + // }
async run({ $ }) { | ||
const { | ||
prompt, | ||
modelId, | ||
width, | ||
height, | ||
numImages, | ||
guidanceScale, | ||
numInferenceSteps, | ||
seed, | ||
} = this; | ||
|
||
const data = { | ||
prompt, | ||
width, | ||
height, | ||
num_images: numImages, | ||
modelId, | ||
guidance_scale: guidanceScale, | ||
num_inference_steps: numInferenceSteps, | ||
seed: seed | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enforce image count vs. size constraint before calling the API.
Leonardo limits num_images
to 1–4 when either dimension > 768. Validate to prevent API errors.
async run({ $ }) {
const {
prompt,
modelId,
width,
height,
numImages,
guidanceScale,
numInferenceSteps,
seed,
} = this;
+ if ((width > 768 || height > 768) && numImages > 4) {
+ throw new Error("When width or height exceeds 768, Number of Images must be 1–4.");
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async run({ $ }) { | |
const { | |
prompt, | |
modelId, | |
width, | |
height, | |
numImages, | |
guidanceScale, | |
numInferenceSteps, | |
seed, | |
} = this; | |
const data = { | |
prompt, | |
width, | |
height, | |
num_images: numImages, | |
modelId, | |
guidance_scale: guidanceScale, | |
num_inference_steps: numInferenceSteps, | |
seed: seed | |
}; | |
async run({ $ }) { | |
const { | |
prompt, | |
modelId, | |
width, | |
height, | |
numImages, | |
guidanceScale, | |
numInferenceSteps, | |
seed, | |
} = this; | |
if ((width > 768 || height > 768) && numImages > 4) { | |
throw new Error("When width or height exceeds 768, Number of Images must be 1–4."); | |
} | |
const data = { | |
prompt, | |
width, | |
height, | |
num_images: numImages, | |
modelId, | |
guidance_scale: guidanceScale, | |
num_inference_steps: numInferenceSteps, | |
seed: seed | |
}; |
🤖 Prompt for AI Agents
In components/leonardo_ai/actions/generate-image/generate-image.mjs around lines
78 to 99, add validation before constructing the data payload to enforce
Leonardo's constraint: if either width or height is > 768 then ensure numImages
is between 1 and 4; if not, throw a clear error (or return a rejected Promise)
indicating "numImages must be between 1 and 4 when width or height exceeds 768".
Perform this check early (before building the data object) so the API call is
never attempted with invalid parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
components/leonardo_ai/leonardo_ai.app.mjs (1)
29-40
: Add a sane default timeout to outgoing requestsAvoid hanging executions on network stalls.
const config = { method, ...rest, url: `${this._baseUrl()}${path}`, + timeout: 60_000, headers: { ...this._getHeaders(), ...(userHeaders || {}), }, data, };
components/leonardo_ai/actions/generate-image/generate-image.mjs (1)
20-26
: Ensure models list populates after app fixOnce
getPlatformModels()
returnsplatformModels
, this options() should work. If the endpoint is unavailable, consider try/catch and return [] to keep the UI usable.async options() { - const models = await this.app.getPlatformModels(); + let models = []; + try { + models = await this.app.getPlatformModels(); + } catch { + return []; + } return models.map((model) => ({ label: model.name || model.id, value: model.id, })); },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
components/leonardo_ai/actions/generate-image/generate-image.mjs
(1 hunks)components/leonardo_ai/actions/generate-motion/generate-motion.mjs
(1 hunks)components/leonardo_ai/actions/upload-image/upload-image.mjs
(1 hunks)components/leonardo_ai/leonardo_ai.app.mjs
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- components/leonardo_ai/actions/generate-motion/generate-motion.mjs
- components/leonardo_ai/actions/upload-image/upload-image.mjs
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#18362
File: components/leonardo_ai/README.md:45-49
Timestamp: 2025-09-15T22:01:17.593Z
Learning: In Leonardo AI components (and likely other Pipedream components), prefer using info alert props on the component itself rather than detailed "Key Features" sections in README files for action documentation.
📚 Learning: 2025-09-15T22:01:11.472Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#18362
File: components/leonardo_ai/actions/generate-image/generate-image.mjs:103-105
Timestamp: 2025-09-15T22:01:11.472Z
Learning: In Pipedream components, pipedream/platform's axios implementation automatically excludes undefined values from HTTP requests, so there's no need to manually check for truthiness before including properties in request payloads.
Applied to files:
components/leonardo_ai/actions/generate-image/generate-image.mjs
components/leonardo_ai/leonardo_ai.app.mjs
🧬 Code graph analysis (2)
components/leonardo_ai/actions/generate-image/generate-image.mjs (1)
components/leonardo_ai/leonardo_ai.app.mjs (3)
data
(42-45)data
(51-58)response
(64-71)
components/leonardo_ai/leonardo_ai.app.mjs (5)
components/leonardo_ai/actions/generate-image/generate-image.mjs (2)
data
(90-99)response
(101-106)components/leonardo_ai/actions/generate-motion/generate-motion.mjs (2)
data
(50-56)response
(58-63)components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (2)
data
(29-32)response
(34-39)components/leonardo_ai/actions/upscale-image/upscale-image.mjs (2)
data
(20-22)response
(24-29)components/leonardo_ai/actions/upload-image/upload-image.mjs (1)
formData
(67-67)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: pnpm publish
- GitHub Check: Verify TypeScript components
- GitHub Check: Publish TypeScript components
- GitHub Check: Lint Code Base
🔇 Additional comments (3)
components/leonardo_ai/leonardo_ai.app.mjs (2)
11-17
: Don’t force Content-Type globally; set JSON CT conditionally in _makeRequestKeep Authorization/Accept in defaults and only add
Content-Type: application/json
for non-FormData POST/PUT/PATCH when callers haven’t provided a CT header. This avoids breaking non‑JSON requests and keeps callers in control.@@ _getHeaders() { return { - "Content-Type": "application/json", "Authorization": `Bearer ${this.$auth.api_key}`, "Accept": "application/json", }; }, @@ const config = { method, ...rest, url: `${this._baseUrl()}${path}`, - headers: { - ...this._getHeaders(), - ...(userHeaders || {}), - }, + headers: { + ...this._getHeaders(), + // Add JSON CT only when appropriate and not overridden by caller + ...((["POST","PUT","PATCH"].includes(String(method).toUpperCase()) + && data + && typeof data?.getHeaders !== "function" + && !(userHeaders?.["Content-Type"] || userHeaders?.["content-type"])) + ? { "Content-Type": "application/json" } + : {}), + ...(userHeaders || {}), + }, data, };Also applies to: 29-38
61-71
: No change required — Nodeform-data
is usedcomponents/leonardo_ai/actions/upload-image/upload-image.mjs imports FormData from "form-data" (import at line 2) and constructs
new FormData()
(line 67), soformData.getHeaders()
is valid in components/leonardo_ai/leonardo_ai.app.mjs.Likely an incorrect or invalid review comment.
components/leonardo_ai/actions/generate-image/generate-image.mjs (1)
29-44
: Enforce multiples-of-8 and correct generation limits
- File: components/leonardo_ai/actions/generate-image/generate-image.mjs (lines 29–44): validate width%8===0 and height%8===0 and update field descriptions to state "must be multiple of 8".
- If this action calls the Create Generation endpoint: change max to 1024 and enforce range 32–1024 (divisible by 8). If it also supports Canvas/Inpainting, document that canvas may allow up to 1536×1536 and gate that path separately.
- Enforce num_images rules: default 4; allow 1–8 normally; restrict to 1–4 when width>768 or height>768.
numImages: { | ||
type: "integer", | ||
label: "Number of Images", | ||
description: "Number of images to generate (1-8). If either width or height is over 768, must be between 1 and 4.", | ||
default: 1, | ||
min: 1, | ||
max: 8, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate size vs. image count before calling the API
Enforce “if width or height > 768, numImages must be 1–4” to prevent API errors.
async run({ $ }) {
const {
prompt,
modelId,
width,
height,
numImages,
guidanceScale,
numInferenceSteps,
seed,
} = this;
+ if ((width > 768 || height > 768) && numImages > 4) {
+ throw new Error("When Width or Height exceeds 768, Number of Images must be between 1 and 4.");
+ }
Also applies to: 78-88
🤖 Prompt for AI Agents
In components/leonardo_ai/actions/generate-image/generate-image.mjs around lines
45-52 (and also apply to 78-88), the current schema allows numImages up to 8
regardless of width/height; add validation before calling the API that checks if
either width or height is greater than 768, and if so enforce numImages is
between 1 and 4 (otherwise allow 1–8). Implement this by reading the width and
height inputs, and if either >768 and numImages is outside 1–4, throw/return a
validation error (or clamp/adjust per project convention) with a clear message;
apply the same validation logic in the other block at lines 78-88.
async getPlatformModels() { | ||
const data = await this._makeRequest({ | ||
method: "GET", | ||
path: "/platformModels", | ||
}); | ||
return data.custom_models || []; | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: getPlatformModels returns wrong field; options() will be empty
/platformModels
responds with the platform models list, not custom_models
. Returning the wrong property empties the Model dropdown.
- return data.custom_models || [];
+ return data.platformModels || data.platform_models || [];
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async getPlatformModels() { | |
const data = await this._makeRequest({ | |
method: "GET", | |
path: "/platformModels", | |
}); | |
return data.custom_models || []; | |
}, | |
async getPlatformModels() { | |
const data = await this._makeRequest({ | |
method: "GET", | |
path: "/platformModels", | |
}); | |
return data.platformModels || data.platform_models || []; | |
}, |
🤖 Prompt for AI Agents
In components/leonardo_ai/leonardo_ai.app.mjs around lines 41 to 47, the
getPlatformModels function returns data.custom_models which is the wrong
property and causes the Model dropdown to be empty; update the return to use the
actual response field (e.g., return data.platform_models || [] or the correct
camelCase variant returned by the API) so the method returns the platform models
list, and add a defensive fallback to an empty array.
hey @GTFalcao would you mind giving another shot to reviewing the PR and advise on whether to implement async option to imageID field that woulld cover only a subset of the entire image IDs that could be used for components? the reason being is because I think we can only list generated images id, but not variation nor init images ids. Thanks! |
Hey @sergio-eliot-rodriguez amazing work! This is almost ready to be shipped. I've marked almost all the comments as resolved, please check the ones that aren't resolved yet. Also personally I would chip down the AI-generated readme to just the key info and links, no specifics on each component's features and all that. It's not a bad thing, we just don't usually add this because it's a piece of information that can get outdated quite easily. If we want to give example values for props, we should do that in their description. And if we need to give additional key information about a component, we can add an alert prop of the "info" type which serves this exact purpose. |
Merged lastest upstream/master into my working branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
components/leonardo_ai/README.md
(1 hunks)components/leonardo_ai/actions/generate-motion/generate-motion.mjs
(1 hunks)components/leonardo_ai/leonardo_ai.app.mjs
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- components/leonardo_ai/README.md
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#18362
File: components/leonardo_ai/README.md:45-49
Timestamp: 2025-09-15T22:01:17.593Z
Learning: In Leonardo AI components (and likely other Pipedream components), prefer using info alert props on the component itself rather than detailed "Key Features" sections in README files for action documentation.
📚 Learning: 2025-09-15T22:01:11.472Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#18362
File: components/leonardo_ai/actions/generate-image/generate-image.mjs:103-105
Timestamp: 2025-09-15T22:01:11.472Z
Learning: In Pipedream components, pipedream/platform's axios implementation automatically excludes undefined values from HTTP requests, so there's no need to manually check for truthiness before including properties in request payloads.
Applied to files:
components/leonardo_ai/leonardo_ai.app.mjs
🧬 Code graph analysis (2)
components/leonardo_ai/leonardo_ai.app.mjs (5)
components/leonardo_ai/actions/generate-motion/generate-motion.mjs (3)
data
(99-105)response
(107-112)userId
(21-21)components/leonardo_ai/actions/unzoom-image/unzoom-image.mjs (2)
data
(29-32)response
(34-39)components/leonardo_ai/actions/generate-image/generate-image.mjs (2)
data
(90-99)response
(101-106)components/leonardo_ai/actions/upscale-image/upscale-image.mjs (2)
data
(20-22)response
(24-29)components/leonardo_ai/actions/upload-image/upload-image.mjs (1)
formData
(67-67)
components/leonardo_ai/actions/generate-motion/generate-motion.mjs (1)
components/leonardo_ai/leonardo_ai.app.mjs (4)
data
(53-56)data
(62-69)data
(87-91)data
(97-105)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: pnpm publish
- GitHub Check: Publish TypeScript components
- GitHub Check: Lint Code Base
- GitHub Check: Verify TypeScript components
🔇 Additional comments (7)
components/leonardo_ai/leonardo_ai.app.mjs (5)
52-58
: Duplicate comment: Bug already identified - getPlatformModels returns wrong fieldBased on the past review comments, this issue has already been identified. The API documentation shows the response structure includes
custom_models
in a nested data object, but the platform models endpoint returns a list of public Platform Models. The current implementation returnsdata.custom_models
, which appears to be incorrect for platform models.
11-17
: Duplicate comment: Content-Type header forcing issue already identifiedThis exact issue was already flagged in past reviews - forcing
Content-Type: application/json
globally breaks non-JSON requests like file uploads.
18-51
: Excellent header merging implementation!The refactored
_makeRequest
method properly addresses the previous header merging issues. It correctly:
- Merges caller-provided headers with defaults
- Handles external URLs (presigned URLs) by skipping default headers
- Preserves the original
opts
object integrity- Provides clean separation between internal API calls and external requests
72-85
: File upload implementation looks good!The
uploadFileToPresignedUrl
method correctly:
- Uses external URL mode (bypasses default headers)
- Leverages
formData.getHeaders()
for proper multipart headers- Routes through the improved
_makeRequest
with proper header mergingThis addresses the previous concerns about file upload handling.
94-107
: Verify the params parameter handling in _makeRequestThe
getGenerationsByUserId
method passesparams
for query parameters, but the_makeRequest
method doesn't explicitly handle theparams
field - it only handlesdata
for request body.components/leonardo_ai/actions/generate-motion/generate-motion.mjs (2)
15-63
: Excellent async options implementation!The
imageId
prop implements a sophisticated async options pattern that:
- Properly handles pagination with
prevContext
and offset tracking- Gracefully extracts userId from the API response structure
- Creates meaningful option labels combining image ID and generation ID
- Implements proper pagination control with
hasMore
logic- Handles empty/missing data scenarios defensively
This addresses the previous feedback about providing async options for image selection.
90-116
: LGTM - Clean implementation!The
run
method follows good practices:
- Proper destructuring of props
- Clean data object construction (leveraging Pipedream's automatic undefined exclusion)
- Correct API endpoint usage (
/generations-motion-svd
)- Meaningful success message
- Returns the full API response
$: this, | ||
}); | ||
// Extract userId from the response structure | ||
const userId = userInfo.user_details?.[0]?.user?.id || userInfo.id; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Potential issue with userId extraction fallback
The userId extraction uses userInfo.user_details?.[0]?.user?.id || userInfo.id
as fallback. This might work, but without knowing the exact API response structure, the fallback to userInfo.id
could be incorrect if the user info response doesn't have a top-level id
field.
Let me verify the actual response structure from the /me
endpoint:
🌐 Web query:
Leonardo AI API /me endpoint response structure getUserInfo
💡 Result:
Example response (GET /api/rest/v1/me — getUserInfo) — sample JSON structure:
{
"user_details": [
{
"user": {
"id": "string",
"username": "string"
},
"tokenRenewalDate": "string",
"paidTokens": 0,
"subscriptionTokens": 0,
"subscriptionGptTokens": 0,
"subscriptionModelTokens": 0,
"apiConcurrencySlots": 0,
"apiPaidTokens": 0,
"apiSubscriptionTokens": 0,
"apiPlanTokenRenewalDate": "string"
}
]
}
Notes: this matches the documented sample for the /me (Get user information) endpoint. For full, authoritative docs and any updates see the Leonardo API documentation. [1][2]
Sources:
[1] API listing / Get user information (example response).
[2] Leonardo.ai API documentation overview.
Fix userId extraction — don't fallback to a non-existent top-level id
The /me response places the id at user_details[0].user.id
(no top-level id
), so userInfo.id
will be undefined; update the code to rely on userInfo.user_details?.[0]?.user?.id
and add explicit handling/error if missing — components/leonardo_ai/actions/generate-motion/generate-motion.mjs:21
🤖 Prompt for AI Agents
In components/leonardo_ai/actions/generate-motion/generate-motion.mjs around
line 21, the code falls back to a non-existent top-level userInfo.id; change the
extraction to rely solely on userInfo.user_details?.[0]?.user?.id and add
explicit handling when that value is missing (throw or return a clear error/log
and avoid proceeding), so the function either uses the nested id or fails fast
with a descriptive message when user id is not present.
@GTFalcao i think i addressed the pending conversations to be resolved. looking fwd to your review! thanks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update @sergio-eliot-rodriguez , looks good to me! Moving it forward
Resolves #8992
Implemented Leonardo AI components expressed by user and later specified in #8992, namely actions
generate-motion
generate-image
unzoom-image
upload-image
upscale-image
Summary by CodeRabbit
New Features
Documentation
Refactor
Chores