From b48e57a22356ec1fce14e280de03228b5e79db97 Mon Sep 17 00:00:00 2001 From: Edwin Jose Date: Tue, 22 Apr 2025 11:14:56 -0400 Subject: [PATCH] fix: improve composio gmail component stability (#7673) * tool change check * optimised logic * Update composio_base.py * update to the init logic * Update gmail_composio.py * update default tool logic * Update src/backend/base/langflow/base/composio/composio_base.py Co-authored-by: Gabriel Luiz Freitas Almeida * Update test_gmail.py --------- Co-authored-by: Gabriel Luiz Freitas Almeida --- .../langflow/base/composio/composio_base.py | 7 ++++++- .../components/composio/gmail_composio.py | 19 ++++++------------- .../components/bundles/composio/test_gmail.py | 1 + 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/backend/base/langflow/base/composio/composio_base.py b/src/backend/base/langflow/base/composio/composio_base.py index dbd3396b2..3ca7da3ad 100644 --- a/src/backend/base/langflow/base/composio/composio_base.py +++ b/src/backend/base/langflow/base/composio/composio_base.py @@ -91,7 +91,7 @@ class ComposioBaseComponent(Component): def _build_action_maps(self): """Build lookup maps for action names.""" - if not self._display_to_key_map: + if not self._display_to_key_map or not self._key_to_display_map: self._display_to_key_map = {data["display_name"]: key for key, data in self._actions_data.items()} self._key_to_display_map = {key: data["display_name"] for key, data in self._actions_data.items()} self._sanitized_names = { @@ -285,6 +285,7 @@ class ComposioBaseComponent(Component): async def _get_tools(self) -> list[Tool]: """Get tools with cached results and optimized name sanitization.""" toolset = self._build_wrapper() + self.set_default_tools() return self.configure_tools(toolset) @property @@ -296,3 +297,7 @@ class ComposioBaseComponent(Component): @abstractmethod def execute_action(self) -> list[dict]: """Execute action and return response as Message.""" + + @abstractmethod + def set_default_tools(self): + """Set the default tools.""" diff --git a/src/backend/base/langflow/components/composio/gmail_composio.py b/src/backend/base/langflow/components/composio/gmail_composio.py index 7bdb3de4a..a6f0c9950 100644 --- a/src/backend/base/langflow/components/composio/gmail_composio.py +++ b/src/backend/base/langflow/components/composio/gmail_composio.py @@ -110,19 +110,6 @@ class ComposioGmailAPIComponent(ComposioBaseComponent): _all_fields = {field for action_data in _actions_data.values() for field in action_data["action_fields"]} _bool_variables = {"is_html", "include_spam_trash"} - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self._default_tools = { - self.sanitize_action_name("GMAIL_SEND_EMAIL").replace(" ", "-"), - self.sanitize_action_name("GMAIL_FETCH_EMAILS").replace(" ", "-"), - } - # Build the action maps right away - self._display_to_key_map = {data["display_name"]: key for key, data in self._actions_data.items()} - self._key_to_display_map = {key: data["display_name"] for key, data in self._actions_data.items()} - self._sanitized_names = { - action: self._name_sanitizer.sub("-", self.sanitize_action_name(action)) for action in self._actions_data - } - # Combine base inputs with Gmail-specific inputs inputs = [ *ComposioBaseComponent._base_inputs, @@ -404,3 +391,9 @@ class ComposioGmailAPIComponent(ComposioBaseComponent): def update_build_config(self, build_config: dict, field_value: Any, field_name: str | None = None) -> dict: return super().update_build_config(build_config, field_value, field_name) + + def set_default_tools(self): + self._default_tools = { + self.sanitize_action_name("GMAIL_SEND_EMAIL").replace(" ", "-"), + self.sanitize_action_name("GMAIL_FETCH_EMAILS").replace(" ", "-"), + } diff --git a/src/backend/tests/unit/components/bundles/composio/test_gmail.py b/src/backend/tests/unit/components/bundles/composio/test_gmail.py index 39ddf4d76..be219832d 100644 --- a/src/backend/tests/unit/components/bundles/composio/test_gmail.py +++ b/src/backend/tests/unit/components/bundles/composio/test_gmail.py @@ -99,6 +99,7 @@ class TestGmailComponent(ComponentTestBaseWithoutClient): # For this specific test, we need to customize the action_data to handle results field component._actions_data = { "GMAIL_FETCH_EMAILS": { + "display_name": "Fetch Emails", "action_fields": ["max_results", "query"], "result_field": "messages", "get_result_field": True,