Skip to content

New Components - letzai #16567

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

Merged
merged 4 commits into from
May 9, 2025
Merged

New Components - letzai #16567

merged 4 commits into from
May 9, 2025

Conversation

luancazarine
Copy link
Collaborator

@luancazarine luancazarine commented May 6, 2025

Resolves #16541.

Summary by CodeRabbit

  • New Features
    • Added actions to create new images and image edits (inpainting or outpainting) using LetzAI.
    • Introduced an action to retrieve information about a specific image by ID.
    • Added event sources to emit events when new images or image edits are created in LetzAI.
  • Improvements
    • Enhanced LetzAI integration with detailed configuration options and improved API support.
    • Added selection options for generation mode, system version, and editing mode.
  • Other
    • Included sample event data for easier testing and setup.

@luancazarine luancazarine added the ai-assisted Content generated by AI, with human refinement and modification label May 6, 2025
Copy link

vercel bot commented May 6, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

3 Skipped Deployments
Name Status Preview Comments Updated (UTC)
docs-v2 ⬜️ Ignored (Inspect) Visit Preview May 7, 2025 1:14pm
pipedream-docs ⬜️ Ignored (Inspect) May 7, 2025 1:14pm
pipedream-docs-redirect-do-not-edit ⬜️ Ignored (Inspect) May 7, 2025 1:14pm

Copy link
Contributor

coderabbitai bot commented May 6, 2025

Walkthrough

This update introduces a comprehensive LetzAI integration, adding new actions for image creation, image information retrieval, and image editing (inpainting/outpainting), as well as new polling sources for detecting newly created images and image edits. Supporting modules for constants, utilities, and event test data are also included, along with a full-featured LetzAI API client.

Changes

File(s) Change Summary
components/letzai/letzai.app.mjs Implements the LetzAI API client with detailed prop definitions, API methods for images and edits, and a pagination utility.
components/letzai/actions/create-new-image/create-new-image.mjs Adds the "Create New Image" action for generating images from prompts with multiple options.
components/letzai/actions/get-image-information/get-image-information.mjs Adds the "Get Image Information" action to fetch image details by ID.
components/letzai/actions/create-image-edit/create-image-edit.mjs Adds the "Create Image Edit" action for inpainting or outpainting existing images.
components/letzai/sources/common/base.mjs Adds a polling source base class for incremental event emission using LetzAI API pagination.
components/letzai/sources/new-image/new-image.mjs
components/letzai/sources/new-image-edit/new-image-edit.mjs
Adds polling sources for new images and new image edits, each using the common base and providing summary and event logic.
components/letzai/sources/new-image/test-event.mjs
components/letzai/sources/new-image-edit/test-event.mjs
Adds detailed mock event data for new image and image edit sources.
components/letzai/common/constants.mjs Adds shared constants for configuration options (modes, system versions, etc.).
components/letzai/common/utils.mjs Adds a utility function for robust JSON/object parsing.
components/letzai/package.json Updates package version and adds a dependency on @pipedream/platform.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Action
    participant LetzAI API

    User->>Action: Trigger (e.g., create-new-image)
    Action->>LetzAI API: API request (e.g., POST /images)
    LetzAI API-->>Action: Response (image info)
    Action-->>User: Summary/result

    Note over Action,LetzAI API: Similar flow for get-image-information and create-image-edit
Loading
sequenceDiagram
    participant Source (Polling)
    participant LetzAI API
    participant User

    loop Every interval
        Source->>LetzAI API: List (images or image edits)
        LetzAI API-->>Source: Page of items
        Source->>User: Emit new events for unseen items
    end
Loading

Assessment against linked issues

Objective Addressed Explanation
Add polling source: new-image (emit on new image creation) (#16541)
Add polling source: new-image-edit (emit on new image edit creation) (#16541)
Add action: create-new-image (with prompt and optional parameters) (#16541)
Add action: get-image-information (by image ID) (#16541)
Add action: create-image-edit (with required/optional parameters for inpainting/outpainting) (#16541)

Poem

A hop and a skip, LetzAI’s now here,
With images new and edits so clear.
Polling for changes, events in the air,
Prompts and IDs handled with flair.
Rabbits rejoice, the code’s a delight—
Creating and fetching, all through the night!
🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

components/letzai/actions/create-image-edit/create-image-edit.mjs

Oops! Something went wrong! :(

ESLint: 8.57.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs
at packageResolve (node:internal/modules/esm/resolve:839:9)
at moduleResolve (node:internal/modules/esm/resolve:908:18)
at defaultResolve (node:internal/modules/esm/resolve:1038:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:557:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:525:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:246:38)
at ModuleJob._link (node:internal/modules/esm/module_job:126:49)

components/letzai/actions/create-new-image/create-new-image.mjs

Oops! Something went wrong! :(

ESLint: 8.57.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs
at packageResolve (node:internal/modules/esm/resolve:839:9)
at moduleResolve (node:internal/modules/esm/resolve:908:18)
at defaultResolve (node:internal/modules/esm/resolve:1038:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:557:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:525:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:246:38)
at ModuleJob._link (node:internal/modules/esm/module_job:126:49)

components/letzai/actions/get-image-information/get-image-information.mjs

Oops! Something went wrong! :(

ESLint: 8.57.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs
at packageResolve (node:internal/modules/esm/resolve:839:9)
at moduleResolve (node:internal/modules/esm/resolve:908:18)
at defaultResolve (node:internal/modules/esm/resolve:1038:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:557:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:525:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:246:38)
at ModuleJob._link (node:internal/modules/esm/module_job:126:49)

  • 8 others
✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Sources
 - New Image
 - New Image Edit

Actions
 - Create New Image
 - Get Image Information
 - Create Image Edit
@luancazarine luancazarine marked this pull request as ready for review May 7, 2025 16:02
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (6)
components/letzai/common/utils.mjs (1)

1-24: Well-structured utility function for JSON parsing

The parseObject function provides a robust way to safely parse JSON strings into JavaScript objects while handling different input types and potential errors. This is especially useful for processing user inputs or API responses where JSON may be serialized as strings.

A few suggestions for improvement:

Consider adding JSDoc comments to better document the function's purpose, parameters, and return types:

+/**
+ * Attempts to parse JSON strings into JavaScript objects
+ * @param {any} obj - The object to parse (can be a string, array, or any other type)
+ * @returns {any} - The parsed object, the original string if parsing fails, or the original value if not a string
+ */
export const parseObject = (obj) => {
  if (!obj) return undefined;

The function handles nested arrays appropriately but not nested objects. If the API may return objects with nested JSON strings as values, you might want to consider a recursive approach:

  if (typeof obj === "string") {
    try {
      return JSON.parse(obj);
    } catch (e) {
      return obj;
    }
  }
+  if (typeof obj === "object" && obj !== null && !Array.isArray(obj)) {
+    return Object.entries(obj).reduce((acc, [key, value]) => {
+      acc[key] = parseObject(value);
+      return acc;
+    }, {});
+  }
  return obj;
components/letzai/sources/new-image-edit/test-event.mjs (1)

1-293: Comprehensive test event structure

This test event provides a detailed representation of the expected data structure for image edits, which will be useful for testing and documentation. The structure includes all relevant fields and nested objects with appropriate placeholder values.

For better maintainability and reusability, consider structuring the test data to avoid duplication:

+// Define reusable objects
+const userObject = {
+  "id": "string",
+  "name": "string",
+  "username": "string",
+  "profilePicture": "string",
+  "description": "string",
+  "website": "string",
+  "imagesGenerated": 0,
+  "imagesAvailable": 0,
+  "modelsAvailable": 0,
+  "followersCount": 0,
+  "followingCount": 0,
+  "isVerified": true
+};
+
+const modelVersionObject = {
+  "id": "string",
+  "version": 0,
+  "storagePath": "string",
+  "systemVersions": [
+    "string"
+  ],
+  "status": "string",
+  "createdAt": "2025-05-07T13:00:26.293Z",
+  "trainedAt": "2025-05-07T13:00:26.293Z"
+};
+
+const modelObject = {
+  "id": "string",
+  "user": userObject,
+  "userId": "string",
+  "name": "string",
+  // ... remaining model properties
+  "versions": [modelVersionObject]
+};
+
+const imageCompletionObject = {
+  "id": "string",
+  "user": userObject,
+  // ... remaining completion properties
+  "models": [modelObject]
+};
+
export default {
  "id": "string",
-  "originalImageCompletion": {
-    "id": "string",
-    "user": {
-      // ... lengthy object
-    },
-    // ... lengthy object
-  },
+  "originalImageCompletion": imageCompletionObject,
  "originalImageEdit": "string",
-  "generatedImageCompletion": {
-    // ... duplicate structure
-  },
+  "generatedImageCompletion": imageCompletionObject,
  // ... remaining top-level properties
-  "models": [
-    {
-      // ... duplicate structure
-    }
-  ],
+  "models": [modelObject],
  "status": "string"
}

This approach would make the test event more maintainable, especially when structure changes are needed.

components/letzai/common/constants.mjs (1)

1-34: Clear and well-structured constants

The constants defined here provide a standardized set of options for the LetzAI integration. The use of label/value pairs in option arrays is a good practice for UI components.

Consider adding JSDoc comments to provide context about what these constants represent and how they're used:

+/**
+ * Maximum number of items to return in API requests
+ */
export const LIMIT = 50;

+/**
+ * Generation mode options for image creation
+ */
export const GENERATION_MODE_OPTIONS = [
  // ...
];

For better type safety and IDE autocompletion, consider adding value object constants:

+/**
+ * Generation mode values
+ */
+export const GENERATION_MODE = {
+  DEFAULT: "default",
+  SIGMA: "sigma",
+};

export const GENERATION_MODE_OPTIONS = [
  {
    label: "Default",
-    value: "default",
+    value: GENERATION_MODE.DEFAULT,
  },
  {
    label: "Sigma",
-    value: "sigma",
+    value: GENERATION_MODE.SIGMA,
  },
];

This approach would provide better refactoring support and prevent typos when using these values elsewhere in the code.

components/letzai/actions/create-new-image/create-new-image.mjs (1)

78-81: Be more explicit with API parameters

Rather than passing all props to the API, consider explicitly selecting only the required parameters for better clarity and preventing potential issues with unexpected parameters.

-   const response = await letzai.createImage({
-     $,
-     data,
-   });
+   const response = await letzai.createImage({
+     $,
+     data: {
+       prompt: data.prompt,
+       width: data.width,
+       height: data.height,
+       quality: data.quality,
+       creativity: data.creativity,
+       hasWatermark: data.hasWatermark,
+       systemVersion: data.systemVersion,
+       mode: data.mode,
+     },
+   });
components/letzai/actions/create-image-edit/create-image-edit.mjs (1)

1-4: Nit – duplicate letzai symbol may confuse readers

You import letzai at the top and de-structure letzai from this later.
Consider renaming the imported symbol (letzaiApp) to avoid shadowing.

components/letzai/letzai.app.mjs (1)

164-188: paginate loop can silently stop after first page

hasMore = data.length; assigns a number, which is truthy even when the server indicates no additional pages (e.g. via hasMore flag or links.next). If the final page has LIMIT items, the loop will continue and request an empty page, wasting API quota.

Recommend:

-const data = await fn({ params, ...opts });
-...
-hasMore = data.length;
+const data = await fn({ params, ...opts });
+const items = Array.isArray(data) ? data : data.data ?? [];
+...
+hasMore = items.length === LIMIT;

This also guards against object-wrapped responses.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a47e41 and 0f5c6fb.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • components/letzai/actions/create-image-edit/create-image-edit.mjs (1 hunks)
  • components/letzai/actions/create-new-image/create-new-image.mjs (1 hunks)
  • components/letzai/actions/get-image-information/get-image-information.mjs (1 hunks)
  • components/letzai/common/constants.mjs (1 hunks)
  • components/letzai/common/utils.mjs (1 hunks)
  • components/letzai/letzai.app.mjs (1 hunks)
  • components/letzai/package.json (2 hunks)
  • components/letzai/sources/common/base.mjs (1 hunks)
  • components/letzai/sources/new-image-edit/new-image-edit.mjs (1 hunks)
  • components/letzai/sources/new-image-edit/test-event.mjs (1 hunks)
  • components/letzai/sources/new-image/new-image.mjs (1 hunks)
  • components/letzai/sources/new-image/test-event.mjs (1 hunks)
🧰 Additional context used
🪛 GitHub Check: Lint Code Base
components/letzai/actions/create-new-image/create-new-image.mjs

[warning] 11-11:
Component prop info must have a label. See https://pipedream.com/docs/components/guidelines/#props


[warning] 11-11:
Component prop info must have a description. See https://pipedream.com/docs/components/guidelines/#props

🔇 Additional comments (8)
components/letzai/package.json (2)

3-3: Version bumped appropriately for new features

The version update from 0.0.1 to 0.1.0 follows semantic versioning principles, indicating that new features have been added without breaking changes.


14-16:

✅ Verification successful

Dependencies correctly updated

Adding the @pipedream/platform dependency is appropriate for a Pipedream integration to access the platform's functionality.

Let's verify this is the latest version of the @pipedream/platform package:


🌐 Web query:

What is the latest version of @pipedream/platform npm package?

💡 Result:

The latest version of the @pipedream/platform npm package is 3.0.3, published 11 days ago. (npmjs.com)

This package provides Pipedream platform globals, including typing and runtime type checking. For usage examples, refer to the Pipedream documentation.

To install this package, you can use the following npm command:

npm install @pipedream/platform

For more details, visit the npm package page: (npmjs.com)

Citations:


Verified @pipedream/platform Dependency Version

The dependency in components/letzai/package.json is set to ^3.0.3, which matches the latest release on npm. Approving the update.

components/letzai/sources/new-image-edit/new-image-edit.mjs (1)

1-22: Well structured source component!

This component follows good practices for Pipedream sources. I appreciate the fallback mechanism in the getSummary method that uses the item ID when a prompt isn't available.

components/letzai/actions/create-new-image/create-new-image.mjs (1)

11-15: ⚠️ Potential issue

Add required label and description to the info prop

According to Pipedream's component guidelines, the info prop must have both a label and description.

  info: {
    type: "alert",
    alertType: "info",
+   label: "Generation Status Note",
+   description: "Information about monitoring the image generation process",
    content: "**Note:** You can monitor the generation status using the Action \"Get Image Information\".",
  },
⛔ Skipped due to learnings
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#15376
File: components/monday/sources/column-value-updated/column-value-updated.mjs:17-24
Timestamp: 2025-01-23T03:55:51.998Z
Learning: Alert props in Pipedream components are a special case that do not require a label property, and use the 'content' property as a replacement for description.
🧰 Tools
🪛 GitHub Check: Lint Code Base

[warning] 11-11:
Component prop info must have a label. See https://pipedream.com/docs/components/guidelines/#props


[warning] 11-11:
Component prop info must have a description. See https://pipedream.com/docs/components/guidelines/#props

components/letzai/sources/new-image/test-event.mjs (1)

1-381: Comprehensive test event structure with potential inconsistency

The test event is thorough, but I noticed an inconsistency: this test event for the "New Image Created" source includes an imageEdit property (lines 17-308), which seems more appropriate for an image edit event rather than a new image event.

Consider reviewing whether this is intentional or if the test event structure should be adjusted to better represent a new image creation event.

components/letzai/actions/get-image-information/get-image-information.mjs (1)

18-25: Solid, minimal implementation – no issues spotted

The action is concise and leverages the shared app client correctly.
• Correct prop wiring (imageId → app propDefinition)
• Proper summary emission
• Returns raw API response for downstream steps

No changes needed here. 👍

components/letzai/sources/common/base.mjs (1)

25-33: Assumes paginated endpoint returns an array – verify API contract

paginate yields over the raw response of this.letzai.paginate, but that helper expects each page to be an array.
If LetzAI returns { data: [...] }, the iteration will fail.

Please confirm the API shape or unwrap the data field before iteration.

components/letzai/letzai.app.mjs (1)

121-129: Missing Content-Type & Accept headers may cause 415/406 errors

If LetzAI expects JSON, explicitly declare:

 _headers() {
   return {
     Authorization: `Bearer ${this.$auth.api_key}`,
+    "Content-Type": "application/json",
+    Accept: "application/json",
   };
 },

[ suggest_nitpick ]

Comment on lines +72 to +84
async run({ $ }) {
const {
letzai,
...data
} = this;

const response = await letzai.createImage({
$,
data,
});
$.export("$summary", `Created image with ID: ${response.id}`);
return response;
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding explicit error handling

The current implementation doesn't handle potential errors from the API call. Consider adding try/catch to handle errors gracefully and provide more helpful error messages to users.

  async run({ $ }) {
    const {
      letzai,
      ...data
    } = this;

+   try {
      const response = await letzai.createImage({
        $,
        data,
      });
      $.export("$summary", `Created image with ID: ${response.id}`);
      return response;
+   } catch (error) {
+     $.export("$summary", `Failed to create image: ${error.message}`);
+     throw error;
+   }
  },
📝 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.

Suggested change
async run({ $ }) {
const {
letzai,
...data
} = this;
const response = await letzai.createImage({
$,
data,
});
$.export("$summary", `Created image with ID: ${response.id}`);
return response;
},
async run({ $ }) {
const {
letzai,
...data
} = this;
try {
const response = await letzai.createImage({
$,
data,
});
$.export("$summary", `Created image with ID: ${response.id}`);
return response;
} catch (error) {
$.export("$summary", `Failed to create image: ${error.message}`);
throw error;
}
},

Comment on lines +17 to +19
getSummary(item) {
return `New image created: ${item.prompt}`;
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add fallback for undefined prompt

Unlike the new-image-edit source, this getSummary method doesn't handle cases where item.prompt might be undefined. Consider adding a fallback to the item ID.

  getSummary(item) {
-   return `New image created: ${item.prompt}`;
+   return `New image created: ${item.prompt || item.id}`;
  },
📝 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.

Suggested change
getSummary(item) {
return `New image created: ${item.prompt}`;
},
getSummary(item) {
return `New image created: ${item.prompt || item.id}`;
},

Comment on lines +84 to +89
async additionalProps(props) {
if (this.mode === "in") {
props.mask.optional = false;
}
return {};
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

additionalProps() mutates instead of returning – UI requirement will not stick

additionalProps is expected to return a new/overridden prop definition.
Directly mutating props.mask.optional and then returning {} means the UI will still treat mask as optional, causing runtime errors if users omit it.

   async additionalProps(props) {
-    if (this.mode === "in") {
-      props.mask.optional = false;
-    }
-    return {};
+    if (this.mode === "in") {
+      return {
+        mask: {
+          ...props.mask,
+          optional: false,
+        },
+      };
+    }
+    return {};
   },
📝 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.

Suggested change
async additionalProps(props) {
if (this.mode === "in") {
props.mask.optional = false;
}
return {};
},
async additionalProps(props) {
if (this.mode === "in") {
return {
mask: {
...props.mask,
optional: false,
},
};
}
return {};
},

Comment on lines +90 to +110
async run({ $ }) {
if (!this.originalImageCompletionId && !this.imageUrl) {
throw new ConfigurationError("Please provide either an original image completion ID or an image URL.");
}

const {
letzai,
settings,
...data
} = this;

const response = await letzai.createImageEditTask({
$,
data: {
...data,
settings: settings && parseObject(settings),
},
});
$.export("$summary", `Image edit task created successfully with request ID: ${response.id}`);
return response;
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing runtime validation for required mask when mode = in

Even after the UI fix above, users can supply props programmatically.
Add a guard to prevent API 400s:

    if (!this.originalImageCompletionId && !this.imageUrl) {
      throw new ConfigurationError("Please provide either an original image completion ID or an image URL.");
    }
+   if (this.mode === "in" && !this.mask) {
+     throw new ConfigurationError("`mask` is required when mode is set to \"in\" (inpainting).");
+   }
📝 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.

Suggested change
async run({ $ }) {
if (!this.originalImageCompletionId && !this.imageUrl) {
throw new ConfigurationError("Please provide either an original image completion ID or an image URL.");
}
const {
letzai,
settings,
...data
} = this;
const response = await letzai.createImageEditTask({
$,
data: {
...data,
settings: settings && parseObject(settings),
},
});
$.export("$summary", `Image edit task created successfully with request ID: ${response.id}`);
return response;
},
async run({ $ }) {
if (!this.originalImageCompletionId && !this.imageUrl) {
throw new ConfigurationError("Please provide either an original image completion ID or an image URL.");
}
if (this.mode === "in" && !this.mask) {
throw new ConfigurationError("`mask` is required when mode is set to \"in\" (inpainting).");
}
const {
letzai,
settings,
...data
} = this;
const response = await letzai.createImageEditTask({
$,
data: {
...data,
settings: settings && parseObject(settings),
},
});
$.export("$summary", `Image edit task created successfully with request ID: ${response.id}`);
return response;
},

Comment on lines +34 to +45
let responseArray = [];
for await (const item of response) {
const createdAt = item.createdAt || item.imageCompletionChoices[0].createdAt;
if (Date.parse(createdAt) <= lastDate) break;
responseArray.push(item);
}

if (responseArray.length) {
const createdAt = responseArray[0].createdAt
|| responseArray[0].imageCompletionChoices[0].createdAt;
this._setLastDate(Date.parse(createdAt));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Potential NaN & missed events if createdAt is absent or unparsable

Date.parse(createdAt) can return NaN, which will:

  1. Break the chronological comparison, possibly letting old events through.
  2. Store NaN in the DB, blocking future polling.

Add a safety net:

-const createdAt = responseArray[0].createdAt
-  || responseArray[0].imageCompletionChoices[0].createdAt;
-this._setLastDate(Date.parse(createdAt));
+const createdAt =
+  responseArray[0].createdAt
+  ?? responseArray[0].imageCompletionChoices?.[0]?.createdAt;
+const ts = Date.parse(createdAt || "");
+if (!Number.isNaN(ts)) this._setLastDate(ts);

Also consider logging / skipping items where the timestamp is missing.

📝 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.

Suggested change
let responseArray = [];
for await (const item of response) {
const createdAt = item.createdAt || item.imageCompletionChoices[0].createdAt;
if (Date.parse(createdAt) <= lastDate) break;
responseArray.push(item);
}
if (responseArray.length) {
const createdAt = responseArray[0].createdAt
|| responseArray[0].imageCompletionChoices[0].createdAt;
this._setLastDate(Date.parse(createdAt));
}
if (responseArray.length) {
const createdAt =
responseArray[0].createdAt
?? responseArray[0].imageCompletionChoices?.[0]?.createdAt;
const ts = Date.parse(createdAt || "");
if (!Number.isNaN(ts)) this._setLastDate(ts);
}

@luancazarine luancazarine merged commit 2b7246a into master May 9, 2025
11 checks passed
@luancazarine luancazarine deleted the issue-16541 branch May 9, 2025 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ai-assisted Content generated by AI, with human refinement and modification
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Components] letzai
2 participants