lfx-nightly 0.1.12.dev40__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 +514 -76
- 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/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/models/language_model.py +2 -2
- {lfx_nightly-0.1.12.dev40.dist-info → lfx_nightly-0.1.12.dev41.dist-info}/METADATA +1 -1
- {lfx_nightly-0.1.12.dev40.dist-info → lfx_nightly-0.1.12.dev41.dist-info}/RECORD +17 -15
- {lfx_nightly-0.1.12.dev40.dist-info → lfx_nightly-0.1.12.dev41.dist-info}/WHEEL +0 -0
- {lfx_nightly-0.1.12.dev40.dist-info → lfx_nightly-0.1.12.dev41.dist-info}/entry_points.txt +0 -0
|
@@ -67,6 +67,200 @@ 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 - hidden by default
|
|
71
|
+
SecretStrInput(
|
|
72
|
+
name="client_id",
|
|
73
|
+
display_name="Client ID",
|
|
74
|
+
info="",
|
|
75
|
+
show=False,
|
|
76
|
+
value="",
|
|
77
|
+
required=False,
|
|
78
|
+
real_time_refresh=True,
|
|
79
|
+
),
|
|
80
|
+
SecretStrInput(
|
|
81
|
+
name="client_secret",
|
|
82
|
+
display_name="Client Secret",
|
|
83
|
+
info="",
|
|
84
|
+
show=False,
|
|
85
|
+
value="",
|
|
86
|
+
required=False,
|
|
87
|
+
real_time_refresh=True,
|
|
88
|
+
),
|
|
89
|
+
StrInput(
|
|
90
|
+
name="verification_token",
|
|
91
|
+
display_name="Verification Token",
|
|
92
|
+
info="",
|
|
93
|
+
show=False,
|
|
94
|
+
value="",
|
|
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,
|
|
115
|
+
),
|
|
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(
|
|
127
|
+
name="api_key_field",
|
|
128
|
+
display_name="API Key",
|
|
129
|
+
info="",
|
|
130
|
+
show=False,
|
|
131
|
+
value="",
|
|
132
|
+
required=False,
|
|
133
|
+
real_time_refresh=True,
|
|
134
|
+
),
|
|
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(
|
|
145
|
+
name="token",
|
|
146
|
+
display_name="Token",
|
|
147
|
+
info="",
|
|
148
|
+
show=False,
|
|
149
|
+
value="",
|
|
150
|
+
required=False,
|
|
151
|
+
real_time_refresh=True,
|
|
152
|
+
),
|
|
153
|
+
SecretStrInput(
|
|
154
|
+
name="access_token",
|
|
155
|
+
display_name="Access Token",
|
|
156
|
+
info="",
|
|
157
|
+
show=False,
|
|
158
|
+
value="",
|
|
159
|
+
required=False,
|
|
160
|
+
real_time_refresh=True,
|
|
161
|
+
),
|
|
162
|
+
SecretStrInput(
|
|
163
|
+
name="refresh_token",
|
|
164
|
+
display_name="Refresh Token",
|
|
165
|
+
info="",
|
|
166
|
+
show=False,
|
|
167
|
+
value="",
|
|
168
|
+
required=False,
|
|
169
|
+
real_time_refresh=True,
|
|
170
|
+
),
|
|
171
|
+
# Basic Auth fields
|
|
172
|
+
StrInput(
|
|
173
|
+
name="username",
|
|
174
|
+
display_name="Username",
|
|
175
|
+
info="",
|
|
176
|
+
show=False,
|
|
177
|
+
value="",
|
|
178
|
+
required=False,
|
|
179
|
+
real_time_refresh=True,
|
|
180
|
+
),
|
|
181
|
+
SecretStrInput(
|
|
182
|
+
name="password",
|
|
183
|
+
display_name="Password",
|
|
184
|
+
info="",
|
|
185
|
+
show=False,
|
|
186
|
+
value="",
|
|
187
|
+
required=False,
|
|
188
|
+
real_time_refresh=True,
|
|
189
|
+
),
|
|
190
|
+
# Other common auth fields
|
|
191
|
+
StrInput(
|
|
192
|
+
name="domain",
|
|
193
|
+
display_name="Domain",
|
|
194
|
+
info="",
|
|
195
|
+
show=False,
|
|
196
|
+
value="",
|
|
197
|
+
required=False,
|
|
198
|
+
real_time_refresh=True,
|
|
199
|
+
),
|
|
200
|
+
StrInput(
|
|
201
|
+
name="base_url",
|
|
202
|
+
display_name="Base URL",
|
|
203
|
+
info="",
|
|
204
|
+
show=False,
|
|
205
|
+
value="",
|
|
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,
|
|
263
|
+
),
|
|
70
264
|
SortableListInput(
|
|
71
265
|
name="action_button",
|
|
72
266
|
display_name="Action",
|
|
@@ -87,6 +281,8 @@ class ComposioBaseComponent(Component):
|
|
|
87
281
|
# Class-level caches
|
|
88
282
|
_actions_cache: dict[str, dict[str, Any]] = {}
|
|
89
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()
|
|
90
286
|
|
|
91
287
|
outputs = [
|
|
92
288
|
Output(name="dataFrame", display_name="DataFrame", method="as_dataframe"),
|
|
@@ -925,26 +1121,11 @@ class ComposioBaseComponent(Component):
|
|
|
925
1121
|
return self._toolkit_schema
|
|
926
1122
|
try:
|
|
927
1123
|
composio = self._build_wrapper()
|
|
928
|
-
# The SDK typically offers a retrieve by slug; if not present, try a few fallbacks
|
|
929
1124
|
app_slug = getattr(self, "app_name", "").lower()
|
|
930
1125
|
if not app_slug:
|
|
931
1126
|
return None
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
except (AttributeError, ValueError, ConnectionError, TypeError):
|
|
935
|
-
schema = None
|
|
936
|
-
for method_name, kwargs in (
|
|
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
|
|
1127
|
+
# Use the correct Composio SDK method
|
|
1128
|
+
schema = composio.toolkits.get(slug=app_slug)
|
|
948
1129
|
self._toolkit_schema = self._to_plain_dict(schema)
|
|
949
1130
|
except (AttributeError, ValueError, ConnectionError, TypeError) as e:
|
|
950
1131
|
logger.debug(f"Could not retrieve toolkit schema for {getattr(self, 'app_name', '')}: {e}")
|
|
@@ -959,8 +1140,12 @@ class ComposioBaseComponent(Component):
|
|
|
959
1140
|
modes: list[str] = []
|
|
960
1141
|
# composio_managed_auth_schemes: list[str]
|
|
961
1142
|
managed = schema.get("composio_managed_auth_schemes") or schema.get("composioManagedAuthSchemes") or []
|
|
962
|
-
|
|
963
|
-
|
|
1143
|
+
has_managed_schemes = isinstance(managed, list) and len(managed) > 0
|
|
1144
|
+
|
|
1145
|
+
# Add "Composio_Managed" as first option if there are managed schemes
|
|
1146
|
+
if has_managed_schemes:
|
|
1147
|
+
modes.append("Composio_Managed")
|
|
1148
|
+
|
|
964
1149
|
# auth_config_details: list with entries containing mode
|
|
965
1150
|
details = schema.get("auth_config_details") or schema.get("authConfigDetails") or []
|
|
966
1151
|
for item in details:
|
|
@@ -1012,10 +1197,56 @@ class ComposioBaseComponent(Component):
|
|
|
1012
1197
|
except (TypeError, ValueError, AttributeError) as e:
|
|
1013
1198
|
logger.debug(f"Failed to render auth_mode dropdown: {e}")
|
|
1014
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
|
+
|
|
1015
1243
|
def _clear_auth_dynamic_fields(self, build_config: dict) -> None:
|
|
1016
1244
|
for fname in list(self._auth_dynamic_fields):
|
|
1017
|
-
if fname in build_config:
|
|
1018
|
-
|
|
1245
|
+
if fname in build_config and isinstance(build_config[fname], dict):
|
|
1246
|
+
# Hide and reset instead of removing
|
|
1247
|
+
build_config[fname]["show"] = False
|
|
1248
|
+
build_config[fname]["value"] = ""
|
|
1249
|
+
build_config[fname]["required"] = False
|
|
1019
1250
|
self._auth_dynamic_fields.clear()
|
|
1020
1251
|
|
|
1021
1252
|
def _add_text_field(
|
|
@@ -1028,19 +1259,61 @@ class ComposioBaseComponent(Component):
|
|
|
1028
1259
|
required: bool,
|
|
1029
1260
|
default_value: str | None = None,
|
|
1030
1261
|
) -> None:
|
|
1031
|
-
"""
|
|
1032
|
-
field
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
show=True
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1262
|
+
"""Update existing field or add new text input for custom auth forms."""
|
|
1263
|
+
# Check if field already exists in build_config (pre-defined placeholder)
|
|
1264
|
+
if name in build_config:
|
|
1265
|
+
# Update existing field properties
|
|
1266
|
+
build_config[name]["display_name"] = display_name or name.replace("_", " ").title()
|
|
1267
|
+
build_config[name]["info"] = info or ""
|
|
1268
|
+
build_config[name]["required"] = required
|
|
1269
|
+
build_config[name]["show"] = True
|
|
1270
|
+
if default_value is not None and default_value != "":
|
|
1271
|
+
build_config[name]["value"] = default_value
|
|
1272
|
+
else:
|
|
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
|
+
|
|
1308
|
+
if default_value is not None and default_value != "":
|
|
1309
|
+
field["value"] = default_value
|
|
1310
|
+
|
|
1311
|
+
# Insert the field in the correct position (before action_button)
|
|
1312
|
+
self._insert_field_before_action_button(build_config, name, field)
|
|
1313
|
+
|
|
1043
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)
|
|
1044
1317
|
|
|
1045
1318
|
def _render_custom_auth_fields(self, build_config: dict, schema: dict[str, Any], mode: str) -> None:
|
|
1046
1319
|
"""Render fields for custom auth based on schema auth_config_details sections."""
|
|
@@ -1053,35 +1326,37 @@ class ComposioBaseComponent(Component):
|
|
|
1053
1326
|
if not selected:
|
|
1054
1327
|
return
|
|
1055
1328
|
fields = selected.get("fields") or {}
|
|
1056
|
-
|
|
1329
|
+
|
|
1330
|
+
# Helper function to process fields
|
|
1331
|
+
def process_fields(field_list: list, *, required: bool) -> None:
|
|
1332
|
+
for field in field_list:
|
|
1333
|
+
name = field.get("name")
|
|
1334
|
+
if not name:
|
|
1335
|
+
continue
|
|
1336
|
+
# Skip Access Token field (bearer_token)
|
|
1337
|
+
if name == "bearer_token":
|
|
1338
|
+
continue
|
|
1339
|
+
# Skip fields with default values for both required and optional fields
|
|
1340
|
+
default_val = field.get("default")
|
|
1341
|
+
if default_val is not None:
|
|
1342
|
+
continue
|
|
1343
|
+
disp = field.get("display_name") or field.get("displayName") or name
|
|
1344
|
+
desc = field.get("description")
|
|
1345
|
+
self._add_text_field(build_config, name, disp, desc, required=required, default_value=default_val)
|
|
1346
|
+
|
|
1347
|
+
# a) AuthConfigCreation fields (for custom OAuth2, etc.)
|
|
1057
1348
|
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
|
|
1349
|
+
# Process required fields
|
|
1350
|
+
process_fields(creation.get("required", []), required=True)
|
|
1351
|
+
# Process optional fields (excluding those with defaults and bearer_token)
|
|
1352
|
+
process_fields(creation.get("optional", []), required=False)
|
|
1353
|
+
|
|
1354
|
+
# b) ConnectedAccountInitiation fields (for API_KEY, etc.)
|
|
1068
1355
|
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)
|
|
1356
|
+
# Process required fields
|
|
1357
|
+
process_fields(initiation.get("required", []), required=True)
|
|
1358
|
+
# Process optional fields (excluding those with defaults)
|
|
1359
|
+
process_fields(initiation.get("optional", []), required=False)
|
|
1085
1360
|
|
|
1086
1361
|
def _collect_all_auth_field_names(self, schema: dict[str, Any] | None) -> set[str]:
|
|
1087
1362
|
names: set[str] = set()
|
|
@@ -1102,6 +1377,8 @@ class ComposioBaseComponent(Component):
|
|
|
1102
1377
|
name = entry.get("name") if isinstance(entry, dict) else None
|
|
1103
1378
|
if name:
|
|
1104
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)
|
|
1105
1382
|
# Only use names discovered from the toolkit schema; do not add aliases
|
|
1106
1383
|
return names
|
|
1107
1384
|
|
|
@@ -1189,9 +1466,11 @@ class ComposioBaseComponent(Component):
|
|
|
1189
1466
|
try:
|
|
1190
1467
|
selected_mode = (build_config.get("auth_mode") or {}).get("value")
|
|
1191
1468
|
managed = (schema or {}).get("composio_managed_auth_schemes") or []
|
|
1192
|
-
|
|
1469
|
+
# Don't render custom fields if "Composio_Managed" is selected
|
|
1470
|
+
if selected_mode and selected_mode != "Composio_Managed":
|
|
1193
1471
|
self._clear_auth_dynamic_fields(build_config)
|
|
1194
1472
|
self._render_custom_auth_fields(build_config, schema or {}, selected_mode)
|
|
1473
|
+
# Already reordered in _render_custom_auth_fields
|
|
1195
1474
|
except (TypeError, ValueError, AttributeError):
|
|
1196
1475
|
pass
|
|
1197
1476
|
|
|
@@ -1335,12 +1614,18 @@ class ComposioBaseComponent(Component):
|
|
|
1335
1614
|
build_config["create_auth_config"]["value"] = ""
|
|
1336
1615
|
build_config["create_auth_config"]["helper_text"] = ""
|
|
1337
1616
|
build_config["create_auth_config"]["options"] = ["create"]
|
|
1338
|
-
if
|
|
1339
|
-
#
|
|
1617
|
+
if mode == "Composio_Managed":
|
|
1618
|
+
# Composio_Managed → no extra fields needed
|
|
1340
1619
|
pass
|
|
1620
|
+
elif isinstance(managed, list) and mode in managed:
|
|
1621
|
+
# This is a specific managed auth scheme (e.g., OAUTH2) but user can still choose custom
|
|
1622
|
+
# So we should render custom fields for this mode
|
|
1623
|
+
self._render_custom_auth_fields(build_config, schema, mode)
|
|
1624
|
+
# Already reordered in _render_custom_auth_fields
|
|
1341
1625
|
else:
|
|
1342
1626
|
# Custom → render only required fields based on the toolkit schema
|
|
1343
1627
|
self._render_custom_auth_fields(build_config, schema, mode)
|
|
1628
|
+
# Already reordered in _render_custom_auth_fields
|
|
1344
1629
|
return self.update_input_types(build_config)
|
|
1345
1630
|
|
|
1346
1631
|
# Handle connection initiation when tool mode is enabled
|
|
@@ -1357,6 +1642,37 @@ class ComposioBaseComponent(Component):
|
|
|
1357
1642
|
build_config["auth_link"]["connection_id"] = connection_id
|
|
1358
1643
|
build_config["action_button"]["helper_text"] = ""
|
|
1359
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
|
+
|
|
1360
1676
|
logger.info(f"Using existing ACTIVE connection {connection_id} for {toolkit_slug}")
|
|
1361
1677
|
return self.update_input_types(build_config)
|
|
1362
1678
|
|
|
@@ -1373,11 +1689,15 @@ class ComposioBaseComponent(Component):
|
|
|
1373
1689
|
mode = build_config["auth_mode"].get("value")
|
|
1374
1690
|
# If no managed default exists (400 Default auth config), require mode selection
|
|
1375
1691
|
managed = (schema or {}).get("composio_managed_auth_schemes") or []
|
|
1376
|
-
|
|
1692
|
+
|
|
1693
|
+
# Handle "Composio_Managed" mode explicitly
|
|
1694
|
+
if mode == "Composio_Managed":
|
|
1695
|
+
# Use Composio_Managed auth flow
|
|
1377
1696
|
redirect_url, connection_id = self._initiate_connection(toolkit_slug)
|
|
1378
1697
|
build_config["auth_link"]["value"] = redirect_url
|
|
1379
1698
|
logger.info(f"New OAuth URL created for {toolkit_slug}: {redirect_url}")
|
|
1380
1699
|
return self.update_input_types(build_config)
|
|
1700
|
+
|
|
1381
1701
|
if not mode:
|
|
1382
1702
|
build_config["auth_link"]["value"] = "connect"
|
|
1383
1703
|
build_config["auth_link"]["auth_tooltip"] = "Select Auth Mode"
|
|
@@ -1585,6 +1905,33 @@ class ComposioBaseComponent(Component):
|
|
|
1585
1905
|
self._clear_auth_fields_from_schema(build_config, schema)
|
|
1586
1906
|
build_config["action_button"]["helper_text"] = ""
|
|
1587
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
|
+
|
|
1588
1935
|
return self.update_input_types(build_config)
|
|
1589
1936
|
# Generic custom auth flow for any other mode (treat like API_KEY)
|
|
1590
1937
|
ac = composio.auth_configs.create(
|
|
@@ -1619,6 +1966,36 @@ class ComposioBaseComponent(Component):
|
|
|
1619
1966
|
else:
|
|
1620
1967
|
build_config["auth_link"]["value"] = "validated"
|
|
1621
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
|
+
}
|
|
1622
1999
|
return self.update_input_types(build_config)
|
|
1623
2000
|
except (ValueError, ConnectionError, TypeError) as e:
|
|
1624
2001
|
logger.error(f"Error creating connection: {e}")
|
|
@@ -1744,18 +2121,22 @@ class ComposioBaseComponent(Component):
|
|
|
1744
2121
|
build_config.setdefault("auth_link", {})
|
|
1745
2122
|
build_config["auth_link"]["show"] = False
|
|
1746
2123
|
build_config["auth_link"]["display_name"] = ""
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
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)
|
|
1759
2140
|
# Do NOT return here; allow auth flow to run in Tool Mode
|
|
1760
2141
|
|
|
1761
2142
|
if field_name == "tool_mode":
|
|
@@ -1942,6 +2323,36 @@ class ComposioBaseComponent(Component):
|
|
|
1942
2323
|
build_config["auth_link"]["auth_tooltip"] = "Disconnect"
|
|
1943
2324
|
build_config["action_button"]["helper_text"] = ""
|
|
1944
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
|
+
}
|
|
1945
2356
|
elif stored_connection_id:
|
|
1946
2357
|
status = self._check_connection_status_by_id(stored_connection_id)
|
|
1947
2358
|
if status == "INITIATED":
|
|
@@ -2186,7 +2597,34 @@ class ComposioBaseComponent(Component):
|
|
|
2186
2597
|
"auth_mode",
|
|
2187
2598
|
"auth_mode_pill",
|
|
2188
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",
|
|
2189
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
|
+
|
|
2190
2628
|
for key, cfg in list(build_config.items()):
|
|
2191
2629
|
if key in protected:
|
|
2192
2630
|
continue
|