lfx-nightly 0.1.12.dev38__py3-none-any.whl → 0.1.12.dev39__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lfx-nightly might be problematic. Click here for more details.
- lfx/_assets/component_index.json +1 -0
- lfx/base/composio/composio_base.py +170 -73
- lfx/cli/run.py +7 -3
- lfx/components/agents/agent.py +1 -0
- lfx/components/composio/slack_composio.py +2 -573
- lfx/components/helpers/current_date.py +1 -1
- lfx/components/lmstudio/lmstudiomodel.py +9 -5
- lfx/components/nvidia/nvidia.py +3 -3
- lfx/components/processing/__init__.py +3 -0
- lfx/components/processing/dynamic_create_data.py +357 -0
- lfx/custom/validate.py +12 -3
- lfx/interface/components.py +336 -8
- lfx/services/settings/base.py +7 -0
- {lfx_nightly-0.1.12.dev38.dist-info → lfx_nightly-0.1.12.dev39.dist-info}/METADATA +1 -1
- {lfx_nightly-0.1.12.dev38.dist-info → lfx_nightly-0.1.12.dev39.dist-info}/RECORD +17 -15
- {lfx_nightly-0.1.12.dev38.dist-info → lfx_nightly-0.1.12.dev39.dist-info}/WHEEL +0 -0
- {lfx_nightly-0.1.12.dev38.dist-info → lfx_nightly-0.1.12.dev39.dist-info}/entry_points.txt +0 -0
|
@@ -67,6 +67,96 @@ class ComposioBaseComponent(Component):
|
|
|
67
67
|
auth_tooltip="Please insert a valid Composio API Key.",
|
|
68
68
|
show=False,
|
|
69
69
|
),
|
|
70
|
+
# Pre-defined placeholder fields for dynamic auth - will be updated dynamically
|
|
71
|
+
StrInput(
|
|
72
|
+
name="client_id",
|
|
73
|
+
display_name="Client id",
|
|
74
|
+
info="",
|
|
75
|
+
show=False,
|
|
76
|
+
value="",
|
|
77
|
+
required=False,
|
|
78
|
+
),
|
|
79
|
+
StrInput(
|
|
80
|
+
name="client_secret",
|
|
81
|
+
display_name="Client secret",
|
|
82
|
+
info="",
|
|
83
|
+
show=False,
|
|
84
|
+
value="",
|
|
85
|
+
required=False,
|
|
86
|
+
),
|
|
87
|
+
StrInput(
|
|
88
|
+
name="verification_token",
|
|
89
|
+
display_name="Verification Token",
|
|
90
|
+
info="",
|
|
91
|
+
show=False,
|
|
92
|
+
value="",
|
|
93
|
+
required=False,
|
|
94
|
+
),
|
|
95
|
+
StrInput(
|
|
96
|
+
name="api_key_field",
|
|
97
|
+
display_name="API Key",
|
|
98
|
+
info="",
|
|
99
|
+
show=False,
|
|
100
|
+
value="",
|
|
101
|
+
required=False,
|
|
102
|
+
),
|
|
103
|
+
StrInput(
|
|
104
|
+
name="token",
|
|
105
|
+
display_name="Token",
|
|
106
|
+
info="",
|
|
107
|
+
show=False,
|
|
108
|
+
value="",
|
|
109
|
+
required=False,
|
|
110
|
+
),
|
|
111
|
+
# Additional common auth fields
|
|
112
|
+
StrInput(
|
|
113
|
+
name="access_token",
|
|
114
|
+
display_name="Access Token",
|
|
115
|
+
info="",
|
|
116
|
+
show=False,
|
|
117
|
+
value="",
|
|
118
|
+
required=False,
|
|
119
|
+
),
|
|
120
|
+
StrInput(
|
|
121
|
+
name="refresh_token",
|
|
122
|
+
display_name="Refresh Token",
|
|
123
|
+
info="",
|
|
124
|
+
show=False,
|
|
125
|
+
value="",
|
|
126
|
+
required=False,
|
|
127
|
+
),
|
|
128
|
+
StrInput(
|
|
129
|
+
name="username",
|
|
130
|
+
display_name="Username",
|
|
131
|
+
info="",
|
|
132
|
+
show=False,
|
|
133
|
+
value="",
|
|
134
|
+
required=False,
|
|
135
|
+
),
|
|
136
|
+
StrInput(
|
|
137
|
+
name="password",
|
|
138
|
+
display_name="Password",
|
|
139
|
+
info="",
|
|
140
|
+
show=False,
|
|
141
|
+
value="",
|
|
142
|
+
required=False,
|
|
143
|
+
),
|
|
144
|
+
StrInput(
|
|
145
|
+
name="domain",
|
|
146
|
+
display_name="Domain",
|
|
147
|
+
info="",
|
|
148
|
+
show=False,
|
|
149
|
+
value="",
|
|
150
|
+
required=False,
|
|
151
|
+
),
|
|
152
|
+
StrInput(
|
|
153
|
+
name="base_url",
|
|
154
|
+
display_name="Base URL",
|
|
155
|
+
info="",
|
|
156
|
+
show=False,
|
|
157
|
+
value="",
|
|
158
|
+
required=False,
|
|
159
|
+
),
|
|
70
160
|
SortableListInput(
|
|
71
161
|
name="action_button",
|
|
72
162
|
display_name="Action",
|
|
@@ -761,9 +851,6 @@ class ComposioBaseComponent(Component):
|
|
|
761
851
|
for inp in lf_inputs:
|
|
762
852
|
if inp.name is not None:
|
|
763
853
|
inp_dict = inp.to_dict() if hasattr(inp, "to_dict") else inp.__dict__.copy()
|
|
764
|
-
|
|
765
|
-
# Do not mutate input_types here; keep original configuration
|
|
766
|
-
|
|
767
854
|
inp_dict.setdefault("show", True) # visible once action selected
|
|
768
855
|
# Preserve previously entered value if user already filled something
|
|
769
856
|
if inp.name in build_config:
|
|
@@ -925,26 +1012,14 @@ class ComposioBaseComponent(Component):
|
|
|
925
1012
|
return self._toolkit_schema
|
|
926
1013
|
try:
|
|
927
1014
|
composio = self._build_wrapper()
|
|
928
|
-
# The SDK typically offers a retrieve by slug; if not present, try a few fallbacks
|
|
929
1015
|
app_slug = getattr(self, "app_name", "").lower()
|
|
930
1016
|
if not app_slug:
|
|
931
1017
|
return None
|
|
932
1018
|
try:
|
|
933
|
-
schema = composio.toolkits.
|
|
934
|
-
except (AttributeError, ValueError, ConnectionError, TypeError):
|
|
935
|
-
schema
|
|
936
|
-
|
|
937
|
-
("retrieve", {"toolkit_slug": app_slug}),
|
|
938
|
-
("get", {"slug": app_slug}),
|
|
939
|
-
("get", {"toolkit_slug": app_slug}),
|
|
940
|
-
):
|
|
941
|
-
try:
|
|
942
|
-
method = getattr(composio.toolkits, method_name)
|
|
943
|
-
schema = method(**kwargs)
|
|
944
|
-
if schema:
|
|
945
|
-
break
|
|
946
|
-
except (AttributeError, ValueError, ConnectionError, TypeError):
|
|
947
|
-
continue
|
|
1019
|
+
schema = composio.toolkits.get(slug=app_slug)
|
|
1020
|
+
except (AttributeError, ValueError, ConnectionError, TypeError) as e:
|
|
1021
|
+
logger.debug(f"Could not get toolkit schema for {app_slug}: {e}")
|
|
1022
|
+
return None
|
|
948
1023
|
self._toolkit_schema = self._to_plain_dict(schema)
|
|
949
1024
|
except (AttributeError, ValueError, ConnectionError, TypeError) as e:
|
|
950
1025
|
logger.debug(f"Could not retrieve toolkit schema for {getattr(self, 'app_name', '')}: {e}")
|
|
@@ -959,8 +1034,12 @@ class ComposioBaseComponent(Component):
|
|
|
959
1034
|
modes: list[str] = []
|
|
960
1035
|
# composio_managed_auth_schemes: list[str]
|
|
961
1036
|
managed = schema.get("composio_managed_auth_schemes") or schema.get("composioManagedAuthSchemes") or []
|
|
962
|
-
|
|
963
|
-
|
|
1037
|
+
has_managed_schemes = isinstance(managed, list) and len(managed) > 0
|
|
1038
|
+
|
|
1039
|
+
# Add "Composio managed" as first option if there are managed schemes
|
|
1040
|
+
if has_managed_schemes:
|
|
1041
|
+
modes.append("Composio managed")
|
|
1042
|
+
|
|
964
1043
|
# auth_config_details: list with entries containing mode
|
|
965
1044
|
details = schema.get("auth_config_details") or schema.get("authConfigDetails") or []
|
|
966
1045
|
for item in details:
|
|
@@ -1014,8 +1093,11 @@ class ComposioBaseComponent(Component):
|
|
|
1014
1093
|
|
|
1015
1094
|
def _clear_auth_dynamic_fields(self, build_config: dict) -> None:
|
|
1016
1095
|
for fname in list(self._auth_dynamic_fields):
|
|
1017
|
-
if fname in build_config:
|
|
1018
|
-
|
|
1096
|
+
if fname in build_config and isinstance(build_config[fname], dict):
|
|
1097
|
+
# Hide and reset instead of removing
|
|
1098
|
+
build_config[fname]["show"] = False
|
|
1099
|
+
build_config[fname]["value"] = ""
|
|
1100
|
+
build_config[fname]["required"] = False
|
|
1019
1101
|
self._auth_dynamic_fields.clear()
|
|
1020
1102
|
|
|
1021
1103
|
def _add_text_field(
|
|
@@ -1028,18 +1110,29 @@ class ComposioBaseComponent(Component):
|
|
|
1028
1110
|
required: bool,
|
|
1029
1111
|
default_value: str | None = None,
|
|
1030
1112
|
) -> None:
|
|
1031
|
-
"""
|
|
1032
|
-
field
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
show=True
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1113
|
+
"""Update existing field or add new text input for custom auth forms."""
|
|
1114
|
+
# Check if field already exists in build_config (pre-defined placeholder)
|
|
1115
|
+
if name in build_config:
|
|
1116
|
+
# Update existing field properties
|
|
1117
|
+
build_config[name]["display_name"] = display_name or name.replace("_", " ").title()
|
|
1118
|
+
build_config[name]["info"] = info or ""
|
|
1119
|
+
build_config[name]["required"] = required
|
|
1120
|
+
build_config[name]["show"] = True
|
|
1121
|
+
if default_value is not None and default_value != "":
|
|
1122
|
+
build_config[name]["value"] = default_value
|
|
1123
|
+
else:
|
|
1124
|
+
# Create new field if not pre-defined
|
|
1125
|
+
field = StrInput(
|
|
1126
|
+
name=name,
|
|
1127
|
+
display_name=display_name or name.replace("_", " ").title(),
|
|
1128
|
+
info=info or "",
|
|
1129
|
+
required=required,
|
|
1130
|
+
real_time_refresh=True,
|
|
1131
|
+
show=True,
|
|
1132
|
+
).to_dict()
|
|
1133
|
+
if default_value is not None and default_value != "":
|
|
1134
|
+
field["value"] = default_value
|
|
1135
|
+
build_config[name] = field
|
|
1043
1136
|
self._auth_dynamic_fields.add(name)
|
|
1044
1137
|
|
|
1045
1138
|
def _render_custom_auth_fields(self, build_config: dict, schema: dict[str, Any], mode: str) -> None:
|
|
@@ -1053,35 +1146,37 @@ class ComposioBaseComponent(Component):
|
|
|
1053
1146
|
if not selected:
|
|
1054
1147
|
return
|
|
1055
1148
|
fields = selected.get("fields") or {}
|
|
1056
|
-
|
|
1149
|
+
|
|
1150
|
+
# Helper function to process fields
|
|
1151
|
+
def process_fields(field_list: list, *, required: bool) -> None:
|
|
1152
|
+
for field in field_list:
|
|
1153
|
+
name = field.get("name")
|
|
1154
|
+
if not name:
|
|
1155
|
+
continue
|
|
1156
|
+
# Skip Access Token field (bearer_token)
|
|
1157
|
+
if name == "bearer_token":
|
|
1158
|
+
continue
|
|
1159
|
+
# Skip fields with default values for both required and optional fields
|
|
1160
|
+
default_val = field.get("default")
|
|
1161
|
+
if default_val is not None:
|
|
1162
|
+
continue
|
|
1163
|
+
disp = field.get("display_name") or field.get("displayName") or name
|
|
1164
|
+
desc = field.get("description")
|
|
1165
|
+
self._add_text_field(build_config, name, disp, desc, required=required, default_value=default_val)
|
|
1166
|
+
|
|
1167
|
+
# a) AuthConfigCreation fields (for custom OAuth2, etc.)
|
|
1057
1168
|
creation = fields.get("auth_config_creation") or fields.get("authConfigCreation") or {}
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
default_val = req.get("default")
|
|
1065
|
-
self._add_text_field(build_config, name, disp, desc, required=True, default_value=default_val)
|
|
1066
|
-
# Optional auth_config_creation fields intentionally not rendered
|
|
1067
|
-
# b) ConnectedAccountInitiation fields for API_KEY mode
|
|
1169
|
+
# Process required fields
|
|
1170
|
+
process_fields(creation.get("required", []), required=True)
|
|
1171
|
+
# Process optional fields (excluding those with defaults and bearer_token)
|
|
1172
|
+
process_fields(creation.get("optional", []), required=False)
|
|
1173
|
+
|
|
1174
|
+
# b) ConnectedAccountInitiation fields (for API_KEY, etc.)
|
|
1068
1175
|
initiation = fields.get("connected_account_initiation") or fields.get("connectedAccountInitiation") or {}
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
disp = req.get("display_name") or req.get("displayName") or name
|
|
1074
|
-
desc = req.get("description")
|
|
1075
|
-
default_val = req.get("default")
|
|
1076
|
-
self._add_text_field(build_config, name, disp, desc, required=True, default_value=default_val)
|
|
1077
|
-
for opt in initiation.get("optional", []):
|
|
1078
|
-
name = opt.get("name")
|
|
1079
|
-
if not name:
|
|
1080
|
-
continue
|
|
1081
|
-
disp = opt.get("display_name") or opt.get("displayName") or name
|
|
1082
|
-
desc = opt.get("description")
|
|
1083
|
-
default_val = opt.get("default")
|
|
1084
|
-
self._add_text_field(build_config, name, disp, desc, required=False, default_value=default_val)
|
|
1176
|
+
# Process required fields
|
|
1177
|
+
process_fields(initiation.get("required", []), required=True)
|
|
1178
|
+
# Process optional fields (excluding those with defaults)
|
|
1179
|
+
process_fields(initiation.get("optional", []), required=False)
|
|
1085
1180
|
|
|
1086
1181
|
def _collect_all_auth_field_names(self, schema: dict[str, Any] | None) -> set[str]:
|
|
1087
1182
|
names: set[str] = set()
|
|
@@ -1131,8 +1226,6 @@ class ComposioBaseComponent(Component):
|
|
|
1131
1226
|
|
|
1132
1227
|
def update_build_config(self, build_config: dict, field_value: Any, field_name: str | None = None) -> dict:
|
|
1133
1228
|
"""Update build config for auth and action selection."""
|
|
1134
|
-
# Avoid normalizing legacy input_types here; rely on upstream fixes
|
|
1135
|
-
|
|
1136
1229
|
# BULLETPROOF tool_mode checking - check all possible places where tool_mode could be stored
|
|
1137
1230
|
instance_tool_mode = getattr(self, "tool_mode", False) if hasattr(self, "tool_mode") else False
|
|
1138
1231
|
|
|
@@ -1189,7 +1282,8 @@ class ComposioBaseComponent(Component):
|
|
|
1189
1282
|
try:
|
|
1190
1283
|
selected_mode = (build_config.get("auth_mode") or {}).get("value")
|
|
1191
1284
|
managed = (schema or {}).get("composio_managed_auth_schemes") or []
|
|
1192
|
-
|
|
1285
|
+
# Don't render custom fields if "Composio managed" is selected
|
|
1286
|
+
if selected_mode and selected_mode != "Composio managed":
|
|
1193
1287
|
self._clear_auth_dynamic_fields(build_config)
|
|
1194
1288
|
self._render_custom_auth_fields(build_config, schema or {}, selected_mode)
|
|
1195
1289
|
except (TypeError, ValueError, AttributeError):
|
|
@@ -1335,9 +1429,13 @@ class ComposioBaseComponent(Component):
|
|
|
1335
1429
|
build_config["create_auth_config"]["value"] = ""
|
|
1336
1430
|
build_config["create_auth_config"]["helper_text"] = ""
|
|
1337
1431
|
build_config["create_auth_config"]["options"] = ["create"]
|
|
1338
|
-
if
|
|
1339
|
-
#
|
|
1432
|
+
if mode == "Composio managed":
|
|
1433
|
+
# Composio managed → no extra fields needed
|
|
1340
1434
|
pass
|
|
1435
|
+
elif isinstance(managed, list) and mode in managed:
|
|
1436
|
+
# This is a specific managed auth scheme (e.g., OAUTH2) but user can still choose custom
|
|
1437
|
+
# So we should render custom fields for this mode
|
|
1438
|
+
self._render_custom_auth_fields(build_config, schema, mode)
|
|
1341
1439
|
else:
|
|
1342
1440
|
# Custom → render only required fields based on the toolkit schema
|
|
1343
1441
|
self._render_custom_auth_fields(build_config, schema, mode)
|
|
@@ -1373,7 +1471,10 @@ class ComposioBaseComponent(Component):
|
|
|
1373
1471
|
mode = build_config["auth_mode"].get("value")
|
|
1374
1472
|
# If no managed default exists (400 Default auth config), require mode selection
|
|
1375
1473
|
managed = (schema or {}).get("composio_managed_auth_schemes") or []
|
|
1376
|
-
|
|
1474
|
+
|
|
1475
|
+
# Handle "Composio managed" mode explicitly
|
|
1476
|
+
if mode == "Composio managed":
|
|
1477
|
+
# Use Composio managed auth flow
|
|
1377
1478
|
redirect_url, connection_id = self._initiate_connection(toolkit_slug)
|
|
1378
1479
|
build_config["auth_link"]["value"] = redirect_url
|
|
1379
1480
|
logger.info(f"New OAuth URL created for {toolkit_slug}: {redirect_url}")
|
|
@@ -1748,11 +1849,7 @@ class ComposioBaseComponent(Component):
|
|
|
1748
1849
|
schema = self._get_toolkit_schema()
|
|
1749
1850
|
mode = (build_config.get("auth_mode") or {}).get("value")
|
|
1750
1851
|
managed = (schema or {}).get("composio_managed_auth_schemes") or []
|
|
1751
|
-
if (
|
|
1752
|
-
mode
|
|
1753
|
-
and not (isinstance(managed, list) and mode in managed)
|
|
1754
|
-
and not getattr(self, "_auth_dynamic_fields", set())
|
|
1755
|
-
):
|
|
1852
|
+
if mode and mode != "Composio managed" and not getattr(self, "_auth_dynamic_fields", set()):
|
|
1756
1853
|
self._render_custom_auth_fields(build_config, schema or {}, mode)
|
|
1757
1854
|
except (TypeError, ValueError, AttributeError):
|
|
1758
1855
|
pass
|
lfx/cli/run.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import re
|
|
2
3
|
import sys
|
|
3
4
|
import tempfile
|
|
4
5
|
from functools import partial
|
|
@@ -243,9 +244,12 @@ async def run(
|
|
|
243
244
|
if "ModuleNotFoundError" in str(e) or "No module named" in str(e):
|
|
244
245
|
logger.info("This appears to be a missing dependency issue")
|
|
245
246
|
if "langchain" in str(e).lower():
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
247
|
+
match = re.search(r"langchain_(.*)", str(e).lower())
|
|
248
|
+
if match:
|
|
249
|
+
module_name = match.group(1)
|
|
250
|
+
logger.info(
|
|
251
|
+
f"Missing LangChain dependency detected. Try: pip install langchain-{module_name}",
|
|
252
|
+
)
|
|
249
253
|
elif "ImportError" in str(e):
|
|
250
254
|
logger.info("This appears to be an import issue - check component dependencies")
|
|
251
255
|
elif "AttributeError" in str(e):
|
lfx/components/agents/agent.py
CHANGED
|
@@ -179,6 +179,7 @@ class AgentComponent(ToolCallingAgentComponent):
|
|
|
179
179
|
|
|
180
180
|
# Get memory data
|
|
181
181
|
self.chat_history = await self.get_memory_data()
|
|
182
|
+
await logger.adebug(f"Retrieved {len(self.chat_history)} chat history messages")
|
|
182
183
|
if isinstance(self.chat_history, Message):
|
|
183
184
|
self.chat_history = [self.chat_history]
|
|
184
185
|
|