Skip to content

feat: add Composio Reddit component#8595

Closed
abhishekpatil4 wants to merge 5 commits into
langflow-ai:mainfrom
ComposioHQ:feat/reddit-component
Closed

feat: add Composio Reddit component#8595
abhishekpatil4 wants to merge 5 commits into
langflow-ai:mainfrom
ComposioHQ:feat/reddit-component

Conversation

@abhishekpatil4
Copy link
Copy Markdown
Contributor

@abhishekpatil4 abhishekpatil4 commented Jun 17, 2025

This pull request introduces a new integration for Reddit, including backend support, frontend components, and tests. The changes ensure that Reddit can be used as a new component in the system, with appropriate backend logic, frontend icons, and sidebar integration.

Backend Changes:

  • Added ComposioRedditAPIComponent to the composio module, enabling backend support for Reddit API interactions. (src/backend/base/langflow/components/composio/__init__.py)
  • Implemented unit tests for ComposioRedditAPIComponent, covering initialization, action execution, data conversion to a DataFrame, and configuration updates. (src/backend/tests/unit/components/bundles/composio/test_Reddit.py)

Frontend Changes:

  • Added a new Reddit icon to the lazy icon imports for dynamic loading. (src/frontend/src/icons/lazyIconImports.ts)
  • Created a RedditIcon component and its corresponding SVG file for rendering the Reddit icon in the UI. (src/frontend/src/icons/reddit/index.tsx, src/frontend/src/icons/reddit/reddit.jsx)
  • Integrated Reddit into the sidebar bundles, making it accessible in the UI with its display name and icon. (src/frontend/src/utils/styleUtils.ts)

Summary by CodeRabbit

  • New Features

    • Introduced Reddit integration, allowing users to interact with Reddit actions such as creating and retrieving posts directly within the platform.
    • Added a Reddit icon and updated sidebar and bundle options to include Reddit.
  • Bug Fixes

    • Removed outdated Outlook and related icons and bundles from the interface.
  • Style

    • Updated sidebar category and bundle icons for a refreshed look, including changes to Prompts and Models icons.
  • Tests

    • Added comprehensive tests for Reddit integration to ensure reliability and correct behavior.

@dosubot dosubot Bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Jun 17, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 17, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This change removes Outlook and generic API components from the Composio backend integration and introduces a new Reddit API component. Corresponding frontend updates add Reddit icon support, remove Outlook and other unused icons, and update sidebar and bundle configurations to reflect the new Reddit integration. Comprehensive unit tests for the Reddit component are also included.

Changes

File(s) Change Summary
src/backend/base/langflow/components/composio/__init__.py Removed exports for Outlook and generic API components; added export for Reddit API component.
src/backend/base/langflow/components/composio/reddit_composio.py Introduced ComposioRedditAPIComponent class, implementing Reddit API actions, input handling, response normalization, and error management.
src/backend/tests/unit/components/bundles/composio/test_reddit.py Added unit tests for the new Reddit component, covering initialization, action execution, error handling, dataframe conversion, and configuration updates.
src/frontend/src/icons/lazyIconImports.ts Added direct import and mapping for Reddit and TwelveLabs icons; removed Cleanlab, Claude, Cursor, and Outlook icons from mapping.
src/frontend/src/icons/reddit/index.tsx, src/frontend/src/icons/reddit/reddit.jsx Added new Reddit icon React component and SVG implementation.
src/frontend/src/utils/styleUtils.ts Updated sidebar and bundle icon/category assignments: removed Outlook and legacy entries, added Reddit bundle/category, changed icons for Prompts and Models, and updated icon mappings to include Reddit.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ComposioRedditAPIComponent
    participant ComposioToolset
    participant RedditAPI

    User->>ComposioRedditAPIComponent: Selects Reddit action and provides input
    ComposioRedditAPIComponent->>ComposioToolset: Maps action, prepares parameters, calls execute_action
    ComposioToolset->>RedditAPI: Executes mapped Reddit API action
    RedditAPI-->>ComposioToolset: Returns API response
    ComposioToolset-->>ComposioRedditAPIComponent: Returns result or error
    ComposioRedditAPIComponent-->>User: Returns normalized result or error message
Loading

Possibly related PRs

Suggested labels

lgtm, fast-track

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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 auto-generate unit tests to generate unit tests for 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.

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.

@dosubot dosubot Bot added the enhancement New feature or request label Jun 17, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Jun 17, 2025
Copy link
Copy Markdown
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: 3

🧹 Nitpick comments (6)
src/frontend/src/icons/reddit/reddit.jsx (1)

2-2: Make icon size configurable instead of hard-coding 23 px

Hard-coding width="23px" / height="23px" limits reusability and breaks when an icon needs to scale with font size (e.g., inside buttons). Default to 1em and allow callers to override via props.

-  <svg viewBox="0 0 16 16" width="23px" height="23px" {...props}>
+  <svg
+    viewBox="0 0 16 16"
+    width={props.width ?? "1em"}
+    height={props.height ?? "1em"}
+    {...props}
+  >
src/frontend/src/icons/reddit/index.tsx (1)

4-9: Expose a displayName to improve DevTools readability

Adding displayName keeps this wrapper consistent with many existing icons and makes React-DevTools inspection easier.

   return <RedditIconSVG ref={ref} {...props} />;
 });
+
+RedditIcon.displayName = "RedditIcon";
src/frontend/src/icons/lazyIconImports.ts (1)

1-1: Remove unused eager import of TwelveLabsIcon

The symbol isn’t referenced anywhere in this file; the lazy mapping already covers TwelveLabs. Keeping the eager import bloats the bundle.

-import { TwelveLabsIcon } from "./TwelveLabs";
src/backend/tests/unit/components/bundles/composio/test_reddit.py (1)

63-71: Reduce brittleness by avoiding direct _actions_data overrides

Manually recreating _actions_data duplicates component internals: a future change in field names will break the test even though functionality may still be correct. Prefer to:

  1. Use the component’s own _actions_data (already built in __init__), or
  2. Patch only the specific keys you need to control.

This keeps tests focused on behaviour rather than implementation details.

src/frontend/src/utils/styleUtils.ts (1)

8-9: Remove or wire up the RedditIcon import

RedditIcon is imported but never referenced.
Either:

  1. Drop the import, or
  2. Add it to eagerLoadedIconsMap (and/or lazyIconImports.ts) and map "Reddit"RedditIcon.

Keeping an unused import just bloats the bundle and may trigger lint warnings.

src/backend/base/langflow/components/composio/reddit_composio.py (1)

105-108: _bool_variables is dead code

The set is never referenced after declaration.
Remove it or integrate it into the parameter-building logic to avoid confusion.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1fcb500 and 4992e71.

⛔ Files ignored due to path filters (1)
  • src/frontend/src/icons/reddit/reddit.svg is excluded by !**/*.svg
📒 Files selected for processing (7)
  • src/backend/base/langflow/components/composio/__init__.py (1 hunks)
  • src/backend/base/langflow/components/composio/reddit_composio.py (1 hunks)
  • src/backend/tests/unit/components/bundles/composio/test_reddit.py (1 hunks)
  • src/frontend/src/icons/lazyIconImports.ts (2 hunks)
  • src/frontend/src/icons/reddit/index.tsx (1 hunks)
  • src/frontend/src/icons/reddit/reddit.jsx (1 hunks)
  • src/frontend/src/utils/styleUtils.ts (6 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/frontend/src/icons/reddit/index.tsx (1)
Learnt from: dolfim-ibm
PR: langflow-ai/langflow#8394
File: src/frontend/src/icons/Docling/index.tsx:4-6
Timestamp: 2025-06-16T11:14:04.188Z
Learning: The Langflow codebase consistently uses `React.PropsWithChildren<{}>` as the prop type for all icon components using forwardRef, rather than `React.SVGProps<SVGSVGElement>`. This is an established pattern across hundreds of icon files in src/frontend/src/icons/.
🪛 Biome (1.9.4)
src/frontend/src/icons/reddit/index.tsx

[error] 6-6: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

🪛 Pylint (3.3.7)
src/backend/base/langflow/components/composio/__init__.py

[error] 8-8: Undefined variable name 'ComposioAPIComponent' in all

(E0603)

src/backend/tests/unit/components/bundles/composio/test_reddit.py

[error] 5-5: No name 'components' in module 'langflow'

(E0611)


[error] 6-6: No name 'schema' in module 'langflow'

(E0611)


[refactor] 13-13: Too few public methods (0/2)

(R0903)

src/backend/base/langflow/components/composio/reddit_composio.py

[refactor] 286-286: Too many local variables (25/15)

(R0914)


[refactor] 286-286: Too many return statements (8/6)

(R0911)


[refactor] 286-286: Too many branches (19/12)

(R0912)


[refactor] 286-286: Too many statements (71/50)

(R0915)

🔇 Additional comments (3)
src/frontend/src/icons/lazyIconImports.ts (1)

59-60: Good addition of Reddit icon mapping

Mapping looks correct and follows existing pattern.

src/frontend/src/utils/styleUtils.ts (1)

233-236: Verify that the Reddit display-icon actually resolves

Both SIDEBAR_BUNDLES and nodeIconToDisplayIconMap point to the string "Reddit".
Unless "Reddit" is present in lazyIconImports.ts or eagerLoadedIconsMap, getNodeIcon will fall through to an empty component and the icon will not render.

Double-check that lazyIconsMapping includes an entry like:

export const lazyIconsMapping = {
  // …
  Reddit: () => import("@/icons/reddit").then(m => m.RedditIcon),
};

Otherwise users will see a blank icon.

Also applies to: 335-336

src/backend/base/langflow/components/composio/reddit_composio.py (1)

354-356: isinstance(result_data, int | str | float | bool) requires Python 3.10+

If the project still supports 3.9, use isinstance(result_data, (int, str, float, bool)).

Comment on lines 7 to 13
__all__ = [
"ComposioAPIComponent",
"ComposioGitHubAPIComponent",
"ComposioGmailAPIComponent",
"ComposioGoogleCalendarAPIComponent",
"ComposioOutlookAPIComponent",
"ComposioRedditAPIComponent",
"ComposioSlackAPIComponent",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

__all__ still exports removed symbol ComposioAPIComponent

ComposioAPIComponent is no longer imported, so from composio import * will raise NameError.
Either import it again or, more plausibly, drop it from __all__.

-    "ComposioAPIComponent",
     "ComposioGitHubAPIComponent",
     "ComposioGmailAPIComponent",
     "ComposioGoogleCalendarAPIComponent",
     "ComposioRedditAPIComponent",
     "ComposioSlackAPIComponent",
📝 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
__all__ = [
"ComposioAPIComponent",
"ComposioGitHubAPIComponent",
"ComposioGmailAPIComponent",
"ComposioGoogleCalendarAPIComponent",
"ComposioOutlookAPIComponent",
"ComposioRedditAPIComponent",
"ComposioSlackAPIComponent",
__all__ = [
"ComposioGitHubAPIComponent",
"ComposioGmailAPIComponent",
"ComposioGoogleCalendarAPIComponent",
"ComposioRedditAPIComponent",
"ComposioSlackAPIComponent",
]
🧰 Tools
🪛 Pylint (3.3.7)

[error] 8-8: Undefined variable name 'ComposioAPIComponent' in all

(E0603)

🤖 Prompt for AI Agents
In src/backend/base/langflow/components/composio/__init__.py between lines 7 and
13, the __all__ list includes "ComposioAPIComponent" which is no longer
imported, causing a NameError when using from composio import *. To fix this,
remove "ComposioAPIComponent" from the __all__ list to ensure only currently
imported symbols are exported.

Comment on lines +298 to +299
enum_name = getattr(Action, action_key)
params = {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Guard against missing enum members

getattr(Action, action_key) will raise AttributeError if action_key isn’t defined in the Action enum.
Consider using getattr(Action, action_key, None) and failing gracefully with a clear error message.

🤖 Prompt for AI Agents
In src/backend/base/langflow/components/composio/reddit_composio.py around lines
298 to 299, the code uses getattr(Action, action_key) which raises
AttributeError if action_key is not a member of the Action enum. Modify this to
use getattr(Action, action_key, None) to safely get the enum member or None if
missing, then add a check to handle the None case by failing gracefully with a
clear error message indicating the invalid action_key.

Comment on lines +286 to +409
def execute_action(self):
"""Execute action and return response as Message."""
toolset = self._build_wrapper()

try:
self._build_action_maps()
display_name = self.action[0]["name"] if isinstance(self.action, list) and self.action else self.action
action_key = self._display_to_key_map.get(display_name)
if not action_key:
msg = f"Invalid action: {display_name}"
raise ValueError(msg)

enum_name = getattr(Action, action_key)
params = {}
if action_key in self._actions_data:
for field in self._actions_data[action_key]["action_fields"]:
value = getattr(self, field)

if value is None or value == "":
continue

param_name = field.replace(action_key + "_", "")
params[param_name] = value

result = toolset.execute_action(
action=enum_name,
params=params,
)

# Ensure result is a dictionary
if not isinstance(result, dict):
logger.error(f"Unexpected result type: {type(result)}, value: {result}")
return {"error": f"Unexpected result type: {type(result)}"}

if not result.get("successful"):
message = result.get("data", {})
message = message.get("message", {}) if isinstance(message, dict) else str(message)

error_info = {"error": result.get("error", "No response")}
if isinstance(message, str):
try:
parsed_message = json.loads(message)
if isinstance(parsed_message, dict) and "error" in parsed_message:
error_data = parsed_message["error"]
error_info = {
"error": {
"code": error_data.get("code", "Unknown"),
"message": error_data.get("message", "No error message"),
}
}
except (json.JSONDecodeError, KeyError) as e:
logger.error(f"Failed to parse error message as JSON: {e}")
error_info = {"error": str(message)}
elif isinstance(message, dict) and "error" in message:
error_data = message["error"]
error_info = {
"error": {
"code": error_data.get("code", "Unknown"),
"message": error_data.get("message", "No error message"),
}
}

return error_info

result_data = result.get("data", [])

if result_data is None:
result_data = []
elif isinstance(result_data, int | str | float | bool):
logger.warning(f"Result data is a primitive type: {type(result_data)}, value: {result_data}")
result_data = [{"value": result_data}]

action_data = self._actions_data.get(action_key, {})

def ensure_dict_list(data):
"""Ensure data is a list of dictionaries."""
if isinstance(data, dict):
return [data]
if isinstance(data, list):
dict_list = []
for item in data:
if isinstance(item, dict):
dict_list.append(item)
else:
dict_list.append({"value": item})
return dict_list
return [{"value": data}]

def convert_posts_list_to_indexed_dict(data):
"""Convert posts_list array to indexed dictionary."""
if isinstance(data, list):
indexed_dict = {}
for i, item in enumerate(data):
indexed_dict[str(i)] = item
return [indexed_dict]
return ensure_dict_list(data)

if action_data.get("get_result_field"):
result_field = action_data.get("result_field")
if result_field:
found = self._find_key_recursively(result_data, result_field)
if found is not None and found != []:
converted = self._convert_pandas_to_python(found)
if result_field in ["posts_list", "children"]:
return convert_posts_list_to_indexed_dict(converted)
return ensure_dict_list(converted)

converted_data = self._convert_pandas_to_python(result_data)
return ensure_dict_list(converted_data)

if result_data and isinstance(result_data, dict):
converted_data = self._convert_pandas_to_python(result_data)
if converted_data:
first_key = next(iter(converted_data))
return ensure_dict_list(converted_data[first_key])
return []

converted_data = self._convert_pandas_to_python(result_data)
return ensure_dict_list(converted_data)
except Exception as e:
logger.error(f"Error executing action: {e}")
display_name = self.action[0]["name"] if isinstance(self.action, list) and self.action else str(self.action)
msg = f"Failed to execute {display_name}: {e!s}"
raise ValueError(msg) from e
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

execute_action exceeds reasonable complexity limits

Pylint flags: 25 locals, 8 returns, 19 branches, 71 statements.
Splitting the method into focused helpers (e.g. _build_params, _handle_error, _normalize_result) will:

• Improve readability & testability
• Eliminate the need for broad except Exception
• Satisfy static-analysis thresholds

Refactor suggested for maintainability.

🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 286-286: Too many local variables (25/15)

(R0914)


[refactor] 286-286: Too many return statements (8/6)

(R0911)


[refactor] 286-286: Too many branches (19/12)

(R0912)


[refactor] 286-286: Too many statements (71/50)

(R0915)

🤖 Prompt for AI Agents
In src/backend/base/langflow/components/composio/reddit_composio.py from lines
286 to 409, the execute_action method is overly complex with too many local
variables, return points, branches, and statements. To fix this, refactor the
method by extracting distinct logical parts into separate helper methods such as
_build_params for constructing the params dictionary, _handle_error for
processing error responses, and _normalize_result for converting and normalizing
the result data. This will reduce complexity, improve readability and
testability, and allow removing the broad try-except block by handling errors
more granularly within these helpers.

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Jun 17, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Jun 17, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Jun 17, 2025
@ogabrielluiz ogabrielluiz added the community Pull Request from an external contributor label Jul 14, 2025
Copy link
Copy Markdown
Collaborator

@erichare erichare left a comment

Choose a reason for hiding this comment

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

Not sure if this is still in scope. but if we do want to include this, please fix the merge conflicts and i'll review, thanks so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community Pull Request from an external contributor enhancement New feature or request size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants