lfx-nightly 0.1.12.dev39__py3-none-any.whl → 0.1.12.dev41__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 -1
- lfx/base/composio/composio_base.py +383 -42
- lfx/base/models/google_generative_ai_model.py +38 -0
- lfx/components/agents/__init__.py +3 -1
- lfx/components/agents/cuga_agent.py +995 -0
- lfx/components/arxiv/arxiv.py +8 -2
- lfx/components/composio/__init__.py +71 -17
- lfx/components/composio/agentql_composio.py +11 -0
- lfx/components/composio/agiled_composio.py +11 -0
- lfx/components/composio/bolna_composio.py +11 -0
- lfx/components/composio/brightdata_composio.py +11 -0
- lfx/components/composio/canvas_composio.py +11 -0
- lfx/components/composio/digicert_composio.py +11 -0
- lfx/components/composio/finage_composio.py +11 -0
- lfx/components/composio/fixer_composio.py +11 -0
- lfx/components/composio/flexisign_composio.py +11 -0
- lfx/components/composio/freshdesk_composio.py +11 -0
- lfx/components/composio/googleclassroom_composio.py +11 -0
- lfx/components/composio/instagram_composio.py +11 -0
- lfx/components/composio/jira_composio.py +11 -0
- lfx/components/composio/jotform_composio.py +11 -0
- lfx/components/composio/listennotes_composio.py +11 -0
- lfx/components/composio/missive_composio.py +11 -0
- lfx/components/composio/pandadoc_composio.py +11 -0
- lfx/components/composio/slack_composio.py +573 -2
- lfx/components/composio/timelinesai_composio.py +11 -0
- lfx/components/datastax/astra_db.py +1 -0
- lfx/components/datastax/astradb_cql.py +1 -1
- lfx/components/datastax/astradb_graph.py +1 -0
- lfx/components/datastax/astradb_tool.py +1 -1
- lfx/components/datastax/astradb_vectorstore.py +1 -1
- lfx/components/datastax/hcd.py +1 -0
- lfx/components/google/google_generative_ai.py +4 -7
- lfx/components/logic/__init__.py +3 -0
- lfx/components/logic/llm_conditional_router.py +65 -21
- lfx/components/models/language_model.py +2 -2
- lfx/components/processing/lambda_filter.py +82 -18
- {lfx_nightly-0.1.12.dev39.dist-info → lfx_nightly-0.1.12.dev41.dist-info}/METADATA +1 -1
- {lfx_nightly-0.1.12.dev39.dist-info → lfx_nightly-0.1.12.dev41.dist-info}/RECORD +41 -21
- {lfx_nightly-0.1.12.dev39.dist-info → lfx_nightly-0.1.12.dev41.dist-info}/WHEEL +0 -0
- {lfx_nightly-0.1.12.dev39.dist-info → lfx_nightly-0.1.12.dev41.dist-info}/entry_points.txt +0 -0
|
@@ -67,22 +67,24 @@ 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 -
|
|
71
|
-
|
|
70
|
+
# Pre-defined placeholder fields for dynamic auth - hidden by default
|
|
71
|
+
SecretStrInput(
|
|
72
72
|
name="client_id",
|
|
73
|
-
display_name="Client
|
|
73
|
+
display_name="Client ID",
|
|
74
74
|
info="",
|
|
75
75
|
show=False,
|
|
76
76
|
value="",
|
|
77
77
|
required=False,
|
|
78
|
+
real_time_refresh=True,
|
|
78
79
|
),
|
|
79
|
-
|
|
80
|
+
SecretStrInput(
|
|
80
81
|
name="client_secret",
|
|
81
|
-
display_name="Client
|
|
82
|
+
display_name="Client Secret",
|
|
82
83
|
info="",
|
|
83
84
|
show=False,
|
|
84
85
|
value="",
|
|
85
86
|
required=False,
|
|
87
|
+
real_time_refresh=True,
|
|
86
88
|
),
|
|
87
89
|
StrInput(
|
|
88
90
|
name="verification_token",
|
|
@@ -91,40 +93,82 @@ class ComposioBaseComponent(Component):
|
|
|
91
93
|
show=False,
|
|
92
94
|
value="",
|
|
93
95
|
required=False,
|
|
96
|
+
real_time_refresh=True,
|
|
97
|
+
),
|
|
98
|
+
StrInput(
|
|
99
|
+
name="redirect_uri",
|
|
100
|
+
display_name="Redirect URI",
|
|
101
|
+
info="",
|
|
102
|
+
show=False,
|
|
103
|
+
value="",
|
|
104
|
+
required=False,
|
|
105
|
+
real_time_refresh=True,
|
|
106
|
+
),
|
|
107
|
+
StrInput(
|
|
108
|
+
name="authorization_url",
|
|
109
|
+
display_name="Authorization URL",
|
|
110
|
+
info="",
|
|
111
|
+
show=False,
|
|
112
|
+
value="",
|
|
113
|
+
required=False,
|
|
114
|
+
real_time_refresh=True,
|
|
94
115
|
),
|
|
95
116
|
StrInput(
|
|
117
|
+
name="token_url",
|
|
118
|
+
display_name="Token URL",
|
|
119
|
+
info="",
|
|
120
|
+
show=False,
|
|
121
|
+
value="",
|
|
122
|
+
required=False,
|
|
123
|
+
real_time_refresh=True,
|
|
124
|
+
),
|
|
125
|
+
# API Key auth fields
|
|
126
|
+
SecretStrInput(
|
|
96
127
|
name="api_key_field",
|
|
97
128
|
display_name="API Key",
|
|
98
129
|
info="",
|
|
99
130
|
show=False,
|
|
100
131
|
value="",
|
|
101
132
|
required=False,
|
|
133
|
+
real_time_refresh=True,
|
|
102
134
|
),
|
|
103
|
-
|
|
135
|
+
SecretStrInput(
|
|
136
|
+
name="generic_api_key",
|
|
137
|
+
display_name="API Key",
|
|
138
|
+
info="",
|
|
139
|
+
show=False,
|
|
140
|
+
value="",
|
|
141
|
+
required=False,
|
|
142
|
+
real_time_refresh=True,
|
|
143
|
+
),
|
|
144
|
+
SecretStrInput(
|
|
104
145
|
name="token",
|
|
105
146
|
display_name="Token",
|
|
106
147
|
info="",
|
|
107
148
|
show=False,
|
|
108
149
|
value="",
|
|
109
150
|
required=False,
|
|
151
|
+
real_time_refresh=True,
|
|
110
152
|
),
|
|
111
|
-
|
|
112
|
-
StrInput(
|
|
153
|
+
SecretStrInput(
|
|
113
154
|
name="access_token",
|
|
114
155
|
display_name="Access Token",
|
|
115
156
|
info="",
|
|
116
157
|
show=False,
|
|
117
158
|
value="",
|
|
118
159
|
required=False,
|
|
160
|
+
real_time_refresh=True,
|
|
119
161
|
),
|
|
120
|
-
|
|
162
|
+
SecretStrInput(
|
|
121
163
|
name="refresh_token",
|
|
122
164
|
display_name="Refresh Token",
|
|
123
165
|
info="",
|
|
124
166
|
show=False,
|
|
125
167
|
value="",
|
|
126
168
|
required=False,
|
|
169
|
+
real_time_refresh=True,
|
|
127
170
|
),
|
|
171
|
+
# Basic Auth fields
|
|
128
172
|
StrInput(
|
|
129
173
|
name="username",
|
|
130
174
|
display_name="Username",
|
|
@@ -132,15 +176,18 @@ class ComposioBaseComponent(Component):
|
|
|
132
176
|
show=False,
|
|
133
177
|
value="",
|
|
134
178
|
required=False,
|
|
179
|
+
real_time_refresh=True,
|
|
135
180
|
),
|
|
136
|
-
|
|
181
|
+
SecretStrInput(
|
|
137
182
|
name="password",
|
|
138
183
|
display_name="Password",
|
|
139
184
|
info="",
|
|
140
185
|
show=False,
|
|
141
186
|
value="",
|
|
142
187
|
required=False,
|
|
188
|
+
real_time_refresh=True,
|
|
143
189
|
),
|
|
190
|
+
# Other common auth fields
|
|
144
191
|
StrInput(
|
|
145
192
|
name="domain",
|
|
146
193
|
display_name="Domain",
|
|
@@ -148,6 +195,7 @@ class ComposioBaseComponent(Component):
|
|
|
148
195
|
show=False,
|
|
149
196
|
value="",
|
|
150
197
|
required=False,
|
|
198
|
+
real_time_refresh=True,
|
|
151
199
|
),
|
|
152
200
|
StrInput(
|
|
153
201
|
name="base_url",
|
|
@@ -156,6 +204,62 @@ class ComposioBaseComponent(Component):
|
|
|
156
204
|
show=False,
|
|
157
205
|
value="",
|
|
158
206
|
required=False,
|
|
207
|
+
real_time_refresh=True,
|
|
208
|
+
),
|
|
209
|
+
SecretStrInput(
|
|
210
|
+
name="bearer_token",
|
|
211
|
+
display_name="Bearer Token",
|
|
212
|
+
info="",
|
|
213
|
+
show=False,
|
|
214
|
+
value="",
|
|
215
|
+
required=False,
|
|
216
|
+
real_time_refresh=True,
|
|
217
|
+
),
|
|
218
|
+
SecretStrInput(
|
|
219
|
+
name="authorization_code",
|
|
220
|
+
display_name="Authorization Code",
|
|
221
|
+
info="",
|
|
222
|
+
show=False,
|
|
223
|
+
value="",
|
|
224
|
+
required=False,
|
|
225
|
+
real_time_refresh=True,
|
|
226
|
+
),
|
|
227
|
+
StrInput(
|
|
228
|
+
name="scopes",
|
|
229
|
+
display_name="Scopes",
|
|
230
|
+
info="",
|
|
231
|
+
show=False,
|
|
232
|
+
value="",
|
|
233
|
+
required=False,
|
|
234
|
+
real_time_refresh=True,
|
|
235
|
+
),
|
|
236
|
+
# Add more common auth fields
|
|
237
|
+
StrInput(
|
|
238
|
+
name="subdomain",
|
|
239
|
+
display_name="Subdomain",
|
|
240
|
+
info="",
|
|
241
|
+
show=False,
|
|
242
|
+
value="",
|
|
243
|
+
required=False,
|
|
244
|
+
real_time_refresh=True,
|
|
245
|
+
),
|
|
246
|
+
StrInput(
|
|
247
|
+
name="instance_url",
|
|
248
|
+
display_name="Instance URL",
|
|
249
|
+
info="",
|
|
250
|
+
show=False,
|
|
251
|
+
value="",
|
|
252
|
+
required=False,
|
|
253
|
+
real_time_refresh=True,
|
|
254
|
+
),
|
|
255
|
+
StrInput(
|
|
256
|
+
name="tenant_id",
|
|
257
|
+
display_name="Tenant ID",
|
|
258
|
+
info="",
|
|
259
|
+
show=False,
|
|
260
|
+
value="",
|
|
261
|
+
required=False,
|
|
262
|
+
real_time_refresh=True,
|
|
159
263
|
),
|
|
160
264
|
SortableListInput(
|
|
161
265
|
name="action_button",
|
|
@@ -177,6 +281,8 @@ class ComposioBaseComponent(Component):
|
|
|
177
281
|
# Class-level caches
|
|
178
282
|
_actions_cache: dict[str, dict[str, Any]] = {}
|
|
179
283
|
_action_schema_cache: dict[str, dict[str, Any]] = {}
|
|
284
|
+
# Track all auth field names discovered across all toolkits
|
|
285
|
+
_all_auth_field_names: set[str] = set()
|
|
180
286
|
|
|
181
287
|
outputs = [
|
|
182
288
|
Output(name="dataFrame", display_name="DataFrame", method="as_dataframe"),
|
|
@@ -851,6 +957,9 @@ class ComposioBaseComponent(Component):
|
|
|
851
957
|
for inp in lf_inputs:
|
|
852
958
|
if inp.name is not None:
|
|
853
959
|
inp_dict = inp.to_dict() if hasattr(inp, "to_dict") else inp.__dict__.copy()
|
|
960
|
+
|
|
961
|
+
# Do not mutate input_types here; keep original configuration
|
|
962
|
+
|
|
854
963
|
inp_dict.setdefault("show", True) # visible once action selected
|
|
855
964
|
# Preserve previously entered value if user already filled something
|
|
856
965
|
if inp.name in build_config:
|
|
@@ -1015,11 +1124,8 @@ class ComposioBaseComponent(Component):
|
|
|
1015
1124
|
app_slug = getattr(self, "app_name", "").lower()
|
|
1016
1125
|
if not app_slug:
|
|
1017
1126
|
return None
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
except (AttributeError, ValueError, ConnectionError, TypeError) as e:
|
|
1021
|
-
logger.debug(f"Could not get toolkit schema for {app_slug}: {e}")
|
|
1022
|
-
return None
|
|
1127
|
+
# Use the correct Composio SDK method
|
|
1128
|
+
schema = composio.toolkits.get(slug=app_slug)
|
|
1023
1129
|
self._toolkit_schema = self._to_plain_dict(schema)
|
|
1024
1130
|
except (AttributeError, ValueError, ConnectionError, TypeError) as e:
|
|
1025
1131
|
logger.debug(f"Could not retrieve toolkit schema for {getattr(self, 'app_name', '')}: {e}")
|
|
@@ -1036,9 +1142,9 @@ class ComposioBaseComponent(Component):
|
|
|
1036
1142
|
managed = schema.get("composio_managed_auth_schemes") or schema.get("composioManagedAuthSchemes") or []
|
|
1037
1143
|
has_managed_schemes = isinstance(managed, list) and len(managed) > 0
|
|
1038
1144
|
|
|
1039
|
-
# Add "
|
|
1145
|
+
# Add "Composio_Managed" as first option if there are managed schemes
|
|
1040
1146
|
if has_managed_schemes:
|
|
1041
|
-
modes.append("
|
|
1147
|
+
modes.append("Composio_Managed")
|
|
1042
1148
|
|
|
1043
1149
|
# auth_config_details: list with entries containing mode
|
|
1044
1150
|
details = schema.get("auth_config_details") or schema.get("authConfigDetails") or []
|
|
@@ -1091,6 +1197,49 @@ class ComposioBaseComponent(Component):
|
|
|
1091
1197
|
except (TypeError, ValueError, AttributeError) as e:
|
|
1092
1198
|
logger.debug(f"Failed to render auth_mode dropdown: {e}")
|
|
1093
1199
|
|
|
1200
|
+
def _insert_field_before_action_button(self, build_config: dict, field_name: str, field_data: dict) -> None:
|
|
1201
|
+
"""Insert a field in the correct position (before action_button) in build_config."""
|
|
1202
|
+
# If field already exists, don't add it again
|
|
1203
|
+
if field_name in build_config:
|
|
1204
|
+
return
|
|
1205
|
+
|
|
1206
|
+
# If action_button doesn't exist, just add the field normally
|
|
1207
|
+
if "action_button" not in build_config:
|
|
1208
|
+
build_config[field_name] = field_data
|
|
1209
|
+
return
|
|
1210
|
+
|
|
1211
|
+
# Find all the keys we need to preserve order for
|
|
1212
|
+
keys_before_action = []
|
|
1213
|
+
keys_after_action = []
|
|
1214
|
+
found_action = False
|
|
1215
|
+
|
|
1216
|
+
for key in list(build_config.keys()):
|
|
1217
|
+
if key == "action_button":
|
|
1218
|
+
found_action = True
|
|
1219
|
+
keys_after_action.append(key)
|
|
1220
|
+
elif found_action:
|
|
1221
|
+
keys_after_action.append(key)
|
|
1222
|
+
else:
|
|
1223
|
+
keys_before_action.append(key)
|
|
1224
|
+
|
|
1225
|
+
# Create new ordered dict
|
|
1226
|
+
new_config = {}
|
|
1227
|
+
|
|
1228
|
+
# Add all fields before action_button
|
|
1229
|
+
for key in keys_before_action:
|
|
1230
|
+
new_config[key] = build_config[key]
|
|
1231
|
+
|
|
1232
|
+
# Add the new field
|
|
1233
|
+
new_config[field_name] = field_data
|
|
1234
|
+
|
|
1235
|
+
# Add action_button and all fields after it
|
|
1236
|
+
for key in keys_after_action:
|
|
1237
|
+
new_config[key] = build_config[key]
|
|
1238
|
+
|
|
1239
|
+
# Clear and update build_config to maintain reference
|
|
1240
|
+
build_config.clear()
|
|
1241
|
+
build_config.update(new_config)
|
|
1242
|
+
|
|
1094
1243
|
def _clear_auth_dynamic_fields(self, build_config: dict) -> None:
|
|
1095
1244
|
for fname in list(self._auth_dynamic_fields):
|
|
1096
1245
|
if fname in build_config and isinstance(build_config[fname], dict):
|
|
@@ -1121,19 +1270,50 @@ class ComposioBaseComponent(Component):
|
|
|
1121
1270
|
if default_value is not None and default_value != "":
|
|
1122
1271
|
build_config[name]["value"] = default_value
|
|
1123
1272
|
else:
|
|
1124
|
-
# Create new field if
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1273
|
+
# Create new field if it doesn't exist
|
|
1274
|
+
# Use SecretStrInput for sensitive fields
|
|
1275
|
+
sensitive_fields = {
|
|
1276
|
+
"client_id",
|
|
1277
|
+
"client_secret",
|
|
1278
|
+
"api_key",
|
|
1279
|
+
"api_key_field",
|
|
1280
|
+
"generic_api_key",
|
|
1281
|
+
"token",
|
|
1282
|
+
"access_token",
|
|
1283
|
+
"refresh_token",
|
|
1284
|
+
"password",
|
|
1285
|
+
"bearer_token",
|
|
1286
|
+
"authorization_code",
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
if name in sensitive_fields:
|
|
1290
|
+
field = SecretStrInput(
|
|
1291
|
+
name=name,
|
|
1292
|
+
display_name=display_name or name.replace("_", " ").title(),
|
|
1293
|
+
info=info or "",
|
|
1294
|
+
required=required,
|
|
1295
|
+
real_time_refresh=True,
|
|
1296
|
+
show=True,
|
|
1297
|
+
).to_dict()
|
|
1298
|
+
else:
|
|
1299
|
+
field = StrInput(
|
|
1300
|
+
name=name,
|
|
1301
|
+
display_name=display_name or name.replace("_", " ").title(),
|
|
1302
|
+
info=info or "",
|
|
1303
|
+
required=required,
|
|
1304
|
+
real_time_refresh=True,
|
|
1305
|
+
show=True,
|
|
1306
|
+
).to_dict()
|
|
1307
|
+
|
|
1133
1308
|
if default_value is not None and default_value != "":
|
|
1134
1309
|
field["value"] = default_value
|
|
1135
|
-
|
|
1310
|
+
|
|
1311
|
+
# Insert the field in the correct position (before action_button)
|
|
1312
|
+
self._insert_field_before_action_button(build_config, name, field)
|
|
1313
|
+
|
|
1136
1314
|
self._auth_dynamic_fields.add(name)
|
|
1315
|
+
# Also add to class-level cache for better tracking
|
|
1316
|
+
self.__class__._all_auth_field_names.add(name)
|
|
1137
1317
|
|
|
1138
1318
|
def _render_custom_auth_fields(self, build_config: dict, schema: dict[str, Any], mode: str) -> None:
|
|
1139
1319
|
"""Render fields for custom auth based on schema auth_config_details sections."""
|
|
@@ -1197,6 +1377,8 @@ class ComposioBaseComponent(Component):
|
|
|
1197
1377
|
name = entry.get("name") if isinstance(entry, dict) else None
|
|
1198
1378
|
if name:
|
|
1199
1379
|
names.add(name)
|
|
1380
|
+
# Add to class-level cache for tracking all discovered auth fields
|
|
1381
|
+
self.__class__._all_auth_field_names.add(name)
|
|
1200
1382
|
# Only use names discovered from the toolkit schema; do not add aliases
|
|
1201
1383
|
return names
|
|
1202
1384
|
|
|
@@ -1226,6 +1408,8 @@ class ComposioBaseComponent(Component):
|
|
|
1226
1408
|
|
|
1227
1409
|
def update_build_config(self, build_config: dict, field_value: Any, field_name: str | None = None) -> dict:
|
|
1228
1410
|
"""Update build config for auth and action selection."""
|
|
1411
|
+
# Avoid normalizing legacy input_types here; rely on upstream fixes
|
|
1412
|
+
|
|
1229
1413
|
# BULLETPROOF tool_mode checking - check all possible places where tool_mode could be stored
|
|
1230
1414
|
instance_tool_mode = getattr(self, "tool_mode", False) if hasattr(self, "tool_mode") else False
|
|
1231
1415
|
|
|
@@ -1282,10 +1466,11 @@ class ComposioBaseComponent(Component):
|
|
|
1282
1466
|
try:
|
|
1283
1467
|
selected_mode = (build_config.get("auth_mode") or {}).get("value")
|
|
1284
1468
|
managed = (schema or {}).get("composio_managed_auth_schemes") or []
|
|
1285
|
-
# Don't render custom fields if "
|
|
1286
|
-
if selected_mode and selected_mode != "
|
|
1469
|
+
# Don't render custom fields if "Composio_Managed" is selected
|
|
1470
|
+
if selected_mode and selected_mode != "Composio_Managed":
|
|
1287
1471
|
self._clear_auth_dynamic_fields(build_config)
|
|
1288
1472
|
self._render_custom_auth_fields(build_config, schema or {}, selected_mode)
|
|
1473
|
+
# Already reordered in _render_custom_auth_fields
|
|
1289
1474
|
except (TypeError, ValueError, AttributeError):
|
|
1290
1475
|
pass
|
|
1291
1476
|
|
|
@@ -1429,16 +1614,18 @@ class ComposioBaseComponent(Component):
|
|
|
1429
1614
|
build_config["create_auth_config"]["value"] = ""
|
|
1430
1615
|
build_config["create_auth_config"]["helper_text"] = ""
|
|
1431
1616
|
build_config["create_auth_config"]["options"] = ["create"]
|
|
1432
|
-
if mode == "
|
|
1433
|
-
#
|
|
1617
|
+
if mode == "Composio_Managed":
|
|
1618
|
+
# Composio_Managed → no extra fields needed
|
|
1434
1619
|
pass
|
|
1435
1620
|
elif isinstance(managed, list) and mode in managed:
|
|
1436
1621
|
# This is a specific managed auth scheme (e.g., OAUTH2) but user can still choose custom
|
|
1437
1622
|
# So we should render custom fields for this mode
|
|
1438
1623
|
self._render_custom_auth_fields(build_config, schema, mode)
|
|
1624
|
+
# Already reordered in _render_custom_auth_fields
|
|
1439
1625
|
else:
|
|
1440
1626
|
# Custom → render only required fields based on the toolkit schema
|
|
1441
1627
|
self._render_custom_auth_fields(build_config, schema, mode)
|
|
1628
|
+
# Already reordered in _render_custom_auth_fields
|
|
1442
1629
|
return self.update_input_types(build_config)
|
|
1443
1630
|
|
|
1444
1631
|
# Handle connection initiation when tool mode is enabled
|
|
@@ -1455,6 +1642,37 @@ class ComposioBaseComponent(Component):
|
|
|
1455
1642
|
build_config["auth_link"]["connection_id"] = connection_id
|
|
1456
1643
|
build_config["action_button"]["helper_text"] = ""
|
|
1457
1644
|
build_config["action_button"]["helper_text_metadata"] = {}
|
|
1645
|
+
|
|
1646
|
+
# Clear auth fields when connected
|
|
1647
|
+
schema = self._get_toolkit_schema()
|
|
1648
|
+
self._clear_auth_fields_from_schema(build_config, schema)
|
|
1649
|
+
|
|
1650
|
+
# Convert auth_mode to pill for connected state
|
|
1651
|
+
scheme, _ = self._get_connection_auth_info(connection_id)
|
|
1652
|
+
if scheme:
|
|
1653
|
+
build_config.setdefault("auth_mode", {})
|
|
1654
|
+
build_config["auth_mode"]["value"] = scheme
|
|
1655
|
+
build_config["auth_mode"]["options"] = [scheme]
|
|
1656
|
+
build_config["auth_mode"]["show"] = False
|
|
1657
|
+
try:
|
|
1658
|
+
pill = TabInput(
|
|
1659
|
+
name="auth_mode",
|
|
1660
|
+
display_name="Auth Mode",
|
|
1661
|
+
options=[scheme],
|
|
1662
|
+
value=scheme,
|
|
1663
|
+
).to_dict()
|
|
1664
|
+
pill["show"] = True
|
|
1665
|
+
build_config["auth_mode"] = pill
|
|
1666
|
+
except (TypeError, ValueError, AttributeError):
|
|
1667
|
+
build_config["auth_mode"] = {
|
|
1668
|
+
"name": "auth_mode",
|
|
1669
|
+
"display_name": "Auth Mode",
|
|
1670
|
+
"type": "tab",
|
|
1671
|
+
"options": [scheme],
|
|
1672
|
+
"value": scheme,
|
|
1673
|
+
"show": True,
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1458
1676
|
logger.info(f"Using existing ACTIVE connection {connection_id} for {toolkit_slug}")
|
|
1459
1677
|
return self.update_input_types(build_config)
|
|
1460
1678
|
|
|
@@ -1472,13 +1690,14 @@ class ComposioBaseComponent(Component):
|
|
|
1472
1690
|
# If no managed default exists (400 Default auth config), require mode selection
|
|
1473
1691
|
managed = (schema or {}).get("composio_managed_auth_schemes") or []
|
|
1474
1692
|
|
|
1475
|
-
# Handle "
|
|
1476
|
-
if mode == "
|
|
1477
|
-
# Use
|
|
1693
|
+
# Handle "Composio_Managed" mode explicitly
|
|
1694
|
+
if mode == "Composio_Managed":
|
|
1695
|
+
# Use Composio_Managed auth flow
|
|
1478
1696
|
redirect_url, connection_id = self._initiate_connection(toolkit_slug)
|
|
1479
1697
|
build_config["auth_link"]["value"] = redirect_url
|
|
1480
1698
|
logger.info(f"New OAuth URL created for {toolkit_slug}: {redirect_url}")
|
|
1481
1699
|
return self.update_input_types(build_config)
|
|
1700
|
+
|
|
1482
1701
|
if not mode:
|
|
1483
1702
|
build_config["auth_link"]["value"] = "connect"
|
|
1484
1703
|
build_config["auth_link"]["auth_tooltip"] = "Select Auth Mode"
|
|
@@ -1686,6 +1905,33 @@ class ComposioBaseComponent(Component):
|
|
|
1686
1905
|
self._clear_auth_fields_from_schema(build_config, schema)
|
|
1687
1906
|
build_config["action_button"]["helper_text"] = ""
|
|
1688
1907
|
build_config["action_button"]["helper_text_metadata"] = {}
|
|
1908
|
+
|
|
1909
|
+
# Convert auth_mode to pill for connected state
|
|
1910
|
+
if not redirect_url and mode: # API_KEY or similar direct connection
|
|
1911
|
+
build_config["auth_link"]["connection_id"] = connection_id
|
|
1912
|
+
build_config.setdefault("auth_mode", {})
|
|
1913
|
+
build_config["auth_mode"]["value"] = mode
|
|
1914
|
+
build_config["auth_mode"]["options"] = [mode]
|
|
1915
|
+
build_config["auth_mode"]["show"] = False
|
|
1916
|
+
try:
|
|
1917
|
+
pill = TabInput(
|
|
1918
|
+
name="auth_mode",
|
|
1919
|
+
display_name="Auth Mode",
|
|
1920
|
+
options=[mode],
|
|
1921
|
+
value=mode,
|
|
1922
|
+
).to_dict()
|
|
1923
|
+
pill["show"] = True
|
|
1924
|
+
build_config["auth_mode"] = pill
|
|
1925
|
+
except (TypeError, ValueError, AttributeError):
|
|
1926
|
+
build_config["auth_mode"] = {
|
|
1927
|
+
"name": "auth_mode",
|
|
1928
|
+
"display_name": "Auth Mode",
|
|
1929
|
+
"type": "tab",
|
|
1930
|
+
"options": [mode],
|
|
1931
|
+
"value": mode,
|
|
1932
|
+
"show": True,
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1689
1935
|
return self.update_input_types(build_config)
|
|
1690
1936
|
# Generic custom auth flow for any other mode (treat like API_KEY)
|
|
1691
1937
|
ac = composio.auth_configs.create(
|
|
@@ -1720,6 +1966,36 @@ class ComposioBaseComponent(Component):
|
|
|
1720
1966
|
else:
|
|
1721
1967
|
build_config["auth_link"]["value"] = "validated"
|
|
1722
1968
|
build_config["auth_link"]["auth_tooltip"] = "Disconnect"
|
|
1969
|
+
build_config["auth_link"]["connection_id"] = connection_id
|
|
1970
|
+
|
|
1971
|
+
# Clear auth fields when connected
|
|
1972
|
+
schema = self._get_toolkit_schema()
|
|
1973
|
+
self._clear_auth_fields_from_schema(build_config, schema)
|
|
1974
|
+
|
|
1975
|
+
# Convert auth_mode to pill for connected state
|
|
1976
|
+
if mode:
|
|
1977
|
+
build_config.setdefault("auth_mode", {})
|
|
1978
|
+
build_config["auth_mode"]["value"] = mode
|
|
1979
|
+
build_config["auth_mode"]["options"] = [mode]
|
|
1980
|
+
build_config["auth_mode"]["show"] = False
|
|
1981
|
+
try:
|
|
1982
|
+
pill = TabInput(
|
|
1983
|
+
name="auth_mode",
|
|
1984
|
+
display_name="Auth Mode",
|
|
1985
|
+
options=[mode],
|
|
1986
|
+
value=mode,
|
|
1987
|
+
).to_dict()
|
|
1988
|
+
pill["show"] = True
|
|
1989
|
+
build_config["auth_mode"] = pill
|
|
1990
|
+
except (TypeError, ValueError, AttributeError):
|
|
1991
|
+
build_config["auth_mode"] = {
|
|
1992
|
+
"name": "auth_mode",
|
|
1993
|
+
"display_name": "Auth Mode",
|
|
1994
|
+
"type": "tab",
|
|
1995
|
+
"options": [mode],
|
|
1996
|
+
"value": mode,
|
|
1997
|
+
"show": True,
|
|
1998
|
+
}
|
|
1723
1999
|
return self.update_input_types(build_config)
|
|
1724
2000
|
except (ValueError, ConnectionError, TypeError) as e:
|
|
1725
2001
|
logger.error(f"Error creating connection: {e}")
|
|
@@ -1845,14 +2121,22 @@ class ComposioBaseComponent(Component):
|
|
|
1845
2121
|
build_config.setdefault("auth_link", {})
|
|
1846
2122
|
build_config["auth_link"]["show"] = False
|
|
1847
2123
|
build_config["auth_link"]["display_name"] = ""
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
self.
|
|
1854
|
-
|
|
1855
|
-
|
|
2124
|
+
|
|
2125
|
+
# Only render auth fields if NOT already connected
|
|
2126
|
+
active_connection = self._find_active_connection_for_app(self.app_name)
|
|
2127
|
+
if not active_connection:
|
|
2128
|
+
try:
|
|
2129
|
+
schema = self._get_toolkit_schema()
|
|
2130
|
+
mode = (build_config.get("auth_mode") or {}).get("value")
|
|
2131
|
+
managed = (schema or {}).get("composio_managed_auth_schemes") or []
|
|
2132
|
+
if mode and mode != "Composio_Managed" and not getattr(self, "_auth_dynamic_fields", set()):
|
|
2133
|
+
self._render_custom_auth_fields(build_config, schema or {}, mode)
|
|
2134
|
+
# Already reordered in _render_custom_auth_fields
|
|
2135
|
+
except (TypeError, ValueError, AttributeError):
|
|
2136
|
+
pass
|
|
2137
|
+
else:
|
|
2138
|
+
# If connected, clear any auth fields that might be showing
|
|
2139
|
+
self._clear_auth_dynamic_fields(build_config)
|
|
1856
2140
|
# Do NOT return here; allow auth flow to run in Tool Mode
|
|
1857
2141
|
|
|
1858
2142
|
if field_name == "tool_mode":
|
|
@@ -2039,6 +2323,36 @@ class ComposioBaseComponent(Component):
|
|
|
2039
2323
|
build_config["auth_link"]["auth_tooltip"] = "Disconnect"
|
|
2040
2324
|
build_config["action_button"]["helper_text"] = ""
|
|
2041
2325
|
build_config["action_button"]["helper_text_metadata"] = {}
|
|
2326
|
+
|
|
2327
|
+
# Clear auth fields when connected
|
|
2328
|
+
schema = self._get_toolkit_schema()
|
|
2329
|
+
self._clear_auth_fields_from_schema(build_config, schema)
|
|
2330
|
+
|
|
2331
|
+
# Convert auth_mode to pill for connected state
|
|
2332
|
+
scheme, _ = self._get_connection_auth_info(active_connection_id)
|
|
2333
|
+
if scheme:
|
|
2334
|
+
build_config.setdefault("auth_mode", {})
|
|
2335
|
+
build_config["auth_mode"]["value"] = scheme
|
|
2336
|
+
build_config["auth_mode"]["options"] = [scheme]
|
|
2337
|
+
build_config["auth_mode"]["show"] = False
|
|
2338
|
+
try:
|
|
2339
|
+
pill = TabInput(
|
|
2340
|
+
name="auth_mode",
|
|
2341
|
+
display_name="Auth Mode",
|
|
2342
|
+
options=[scheme],
|
|
2343
|
+
value=scheme,
|
|
2344
|
+
).to_dict()
|
|
2345
|
+
pill["show"] = True
|
|
2346
|
+
build_config["auth_mode"] = pill
|
|
2347
|
+
except (TypeError, ValueError, AttributeError):
|
|
2348
|
+
build_config["auth_mode"] = {
|
|
2349
|
+
"name": "auth_mode",
|
|
2350
|
+
"display_name": "Auth Mode",
|
|
2351
|
+
"type": "tab",
|
|
2352
|
+
"options": [scheme],
|
|
2353
|
+
"value": scheme,
|
|
2354
|
+
"show": True,
|
|
2355
|
+
}
|
|
2042
2356
|
elif stored_connection_id:
|
|
2043
2357
|
status = self._check_connection_status_by_id(stored_connection_id)
|
|
2044
2358
|
if status == "INITIATED":
|
|
@@ -2283,7 +2597,34 @@ class ComposioBaseComponent(Component):
|
|
|
2283
2597
|
"auth_mode",
|
|
2284
2598
|
"auth_mode_pill",
|
|
2285
2599
|
"create_auth_config",
|
|
2600
|
+
# Pre-defined auth fields
|
|
2601
|
+
"client_id",
|
|
2602
|
+
"client_secret",
|
|
2603
|
+
"verification_token",
|
|
2604
|
+
"redirect_uri",
|
|
2605
|
+
"authorization_url",
|
|
2606
|
+
"token_url",
|
|
2607
|
+
"api_key_field",
|
|
2608
|
+
"generic_api_key",
|
|
2609
|
+
"token",
|
|
2610
|
+
"access_token",
|
|
2611
|
+
"refresh_token",
|
|
2612
|
+
"username",
|
|
2613
|
+
"password",
|
|
2614
|
+
"domain",
|
|
2615
|
+
"base_url",
|
|
2616
|
+
"bearer_token",
|
|
2617
|
+
"authorization_code",
|
|
2618
|
+
"scopes",
|
|
2619
|
+
"subdomain",
|
|
2620
|
+
"instance_url",
|
|
2621
|
+
"tenant_id",
|
|
2286
2622
|
}
|
|
2623
|
+
# Add all dynamic auth fields to protected set
|
|
2624
|
+
protected.update(self._auth_dynamic_fields)
|
|
2625
|
+
# Also protect any auth fields discovered across all instances
|
|
2626
|
+
protected.update(self.__class__._all_auth_field_names)
|
|
2627
|
+
|
|
2287
2628
|
for key, cfg in list(build_config.items()):
|
|
2288
2629
|
if key in protected:
|
|
2289
2630
|
continue
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from langchain_google_genai import ChatGoogleGenerativeAI
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ChatGoogleGenerativeAIFixed(ChatGoogleGenerativeAI):
|
|
5
|
+
"""Custom ChatGoogleGenerativeAI that fixes function response name issues for Gemini."""
|
|
6
|
+
|
|
7
|
+
def __init__(self, *args, **kwargs):
|
|
8
|
+
"""Initialize with fix for empty function response names in ToolMessage and FunctionMessage."""
|
|
9
|
+
if ChatGoogleGenerativeAI is None:
|
|
10
|
+
msg = "The 'langchain_google_genai' package is required to use the Google Generative AI model."
|
|
11
|
+
raise ImportError(msg)
|
|
12
|
+
|
|
13
|
+
# Initialize the parent class
|
|
14
|
+
super().__init__(*args, **kwargs)
|
|
15
|
+
|
|
16
|
+
def _prepare_request(self, messages, **kwargs):
|
|
17
|
+
"""Override request preparation to fix empty function response names."""
|
|
18
|
+
from langchain_core.messages import FunctionMessage, ToolMessage
|
|
19
|
+
|
|
20
|
+
# Pre-process messages to ensure tool/function messages have names
|
|
21
|
+
fixed_messages = []
|
|
22
|
+
for message in messages:
|
|
23
|
+
fixed_message = message
|
|
24
|
+
if isinstance(message, ToolMessage) and not message.name:
|
|
25
|
+
# Create a new ToolMessage with a default name
|
|
26
|
+
fixed_message = ToolMessage(
|
|
27
|
+
content=message.content,
|
|
28
|
+
name="tool_response",
|
|
29
|
+
tool_call_id=getattr(message, "tool_call_id", None),
|
|
30
|
+
artifact=getattr(message, "artifact", None),
|
|
31
|
+
)
|
|
32
|
+
elif isinstance(message, FunctionMessage) and not message.name:
|
|
33
|
+
# Create a new FunctionMessage with a default name
|
|
34
|
+
fixed_message = FunctionMessage(content=message.content, name="function_response")
|
|
35
|
+
fixed_messages.append(fixed_message)
|
|
36
|
+
|
|
37
|
+
# Call the parent's method with fixed messages
|
|
38
|
+
return super()._prepare_request(fixed_messages, **kwargs)
|