lfx-nightly 0.1.12.dev25__py3-none-any.whl → 0.1.12.dev27__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/base/agents/agent.py CHANGED
@@ -138,15 +138,22 @@ class LCAgentComponent(Component):
138
138
  max_iterations=max_iterations,
139
139
  )
140
140
  input_dict: dict[str, str | list[BaseMessage]] = {
141
- "input": self.input_value.to_lc_message() if isinstance(self.input_value, Message) else self.input_value
141
+ "input": self.input_value.to_lc_message()
142
+ if hasattr(self.input_value, "to_lc_message")
143
+ else self.input_value
142
144
  }
143
145
  if hasattr(self, "system_prompt"):
144
146
  input_dict["system_prompt"] = self.system_prompt
145
147
  if hasattr(self, "chat_history") and self.chat_history:
146
- if isinstance(self.chat_history, Data):
148
+ if (
149
+ hasattr(self.chat_history, "to_data")
150
+ and callable(self.chat_history.to_data)
151
+ and self.chat_history.__class__.__name__ == "Data"
152
+ ):
153
+ input_dict["chat_history"] = data_to_messages(self.chat_history)
154
+ # Handle both lfx.schema.message.Message and langflow.schema.message.Message types
155
+ if all(hasattr(m, "to_data") and callable(m.to_data) and "text" in m.data for m in self.chat_history):
147
156
  input_dict["chat_history"] = data_to_messages(self.chat_history)
148
- if all(isinstance(m, Message) for m in self.chat_history):
149
- input_dict["chat_history"] = data_to_messages([m.to_data() for m in self.chat_history])
150
157
  if hasattr(input_dict["input"], "content") and isinstance(input_dict["input"].content, list):
151
158
  # ! Because the input has to be a string, we must pass the images in the chat_history
152
159
 
lfx/base/agents/utils.py CHANGED
@@ -17,6 +17,7 @@ from pydantic import BaseModel
17
17
 
18
18
  from lfx.log.logger import logger
19
19
  from lfx.schema.data import Data
20
+ from lfx.schema.message import Message
20
21
  from lfx.services.cache.base import CacheService
21
22
  from lfx.services.cache.utils import CacheMiss
22
23
 
@@ -39,14 +40,14 @@ class AgentSpec(BaseModel):
39
40
  hub_repo: str | None = None
40
41
 
41
42
 
42
- def data_to_messages(data: list[Data]) -> list[BaseMessage]:
43
+ def data_to_messages(data: list[Data | Message]) -> list[BaseMessage]:
43
44
  """Convert a list of data to a list of messages.
44
45
 
45
46
  Args:
46
- data (List[Data]): The data to convert.
47
+ data (List[Data | Message]): The data to convert.
47
48
 
48
49
  Returns:
49
- List[Message]: The data as messages.
50
+ List[BaseMessage]: The data as messages.
50
51
  """
51
52
  return [value.to_lc_message() for value in data]
52
53
 
@@ -154,7 +154,7 @@ class AgentComponent(ToolCallingAgentComponent):
154
154
  },
155
155
  ],
156
156
  ),
157
- *LCToolsAgentComponent.get_base_inputs(),
157
+ *LCToolsAgentComponent._base_inputs,
158
158
  # removed memory inputs from agent component
159
159
  # *memory_inputs,
160
160
  BoolInput(
@@ -182,6 +182,8 @@ class ParameterHandler:
182
182
  params = self._handle_code_field(field_name, val, params)
183
183
  elif field.get("type") in {"dict", "NestedDict"}:
184
184
  params = self._handle_dict_field(field_name, val, params)
185
+ elif field.get("type") == "table":
186
+ params = self._handle_table_field(field_name, val, params, load_from_db_fields)
185
187
  else:
186
188
  params = self._handle_other_direct_types(field_name, field, val, params)
187
189
 
@@ -190,6 +192,53 @@ class ParameterHandler:
190
192
 
191
193
  return params, load_from_db_fields
192
194
 
195
+ def _handle_table_field(
196
+ self,
197
+ field_name: str,
198
+ val: Any,
199
+ params: dict[str, Any],
200
+ load_from_db_fields: list[str] | None = None,
201
+ ) -> dict[str, Any]:
202
+ """Handle table field type with load_from_db column support."""
203
+ if load_from_db_fields is None:
204
+ load_from_db_fields = []
205
+ if val is None:
206
+ params[field_name] = []
207
+ return params
208
+
209
+ # Store the table data as-is for now
210
+ # The actual column processing will happen in the loading phase
211
+ if isinstance(val, list) and all(isinstance(item, dict) for item in val):
212
+ params[field_name] = val
213
+ else:
214
+ msg = f"Invalid value type {type(val)} for table field {field_name}"
215
+ raise ValueError(msg)
216
+
217
+ # Get table schema from the field to identify load_from_db columns
218
+ field_template = self.template_dict.get(field_name, {})
219
+ table_schema = field_template.get("table_schema", [])
220
+
221
+ # Track which columns need database loading
222
+ load_from_db_columns = []
223
+ for column_schema in table_schema:
224
+ if isinstance(column_schema, dict) and column_schema.get("load_from_db"):
225
+ load_from_db_columns.append(column_schema["name"])
226
+ elif hasattr(column_schema, "load_from_db") and column_schema.load_from_db:
227
+ load_from_db_columns.append(column_schema.name)
228
+
229
+ # Store metadata for later processing
230
+ if load_from_db_columns:
231
+ # Store table column metadata for the loading phase
232
+ table_load_metadata_key = f"{field_name}_load_from_db_columns"
233
+ params[table_load_metadata_key] = load_from_db_columns
234
+
235
+ # Add to load_from_db_fields so it gets processed
236
+ # We'll use a special naming convention to identify table fields
237
+ load_from_db_fields.append(f"table:{field_name}")
238
+ self.load_from_db_fields.append(f"table:{field_name}")
239
+
240
+ return params
241
+
193
242
  def handle_optional_field(self, field_name: str, field: dict, params: dict[str, Any]) -> None:
194
243
  """Handle optional fields."""
195
244
  if not field.get("required") and params.get(field_name) is None:
@@ -126,6 +126,88 @@ def load_from_env_vars(params, load_from_db_fields):
126
126
  return params
127
127
 
128
128
 
129
+ async def update_table_params_with_load_from_db_fields(
130
+ custom_component: CustomComponent,
131
+ params: dict,
132
+ table_field_name: str,
133
+ *,
134
+ fallback_to_env_vars: bool = False,
135
+ ) -> dict:
136
+ """Update table parameters with load_from_db column values."""
137
+ # Get the table data and column metadata
138
+ table_data = params.get(table_field_name, [])
139
+ metadata_key = f"{table_field_name}_load_from_db_columns"
140
+ load_from_db_columns = params.pop(metadata_key, [])
141
+
142
+ if not table_data or not load_from_db_columns:
143
+ return params
144
+
145
+ async with session_scope() as session:
146
+ settings_service = get_settings_service()
147
+ is_noop_session = isinstance(session, NoopSession) or (
148
+ settings_service and settings_service.settings.use_noop_database
149
+ )
150
+
151
+ # Process each row in the table
152
+ updated_table_data = []
153
+ for row in table_data:
154
+ if not isinstance(row, dict):
155
+ updated_table_data.append(row)
156
+ continue
157
+
158
+ updated_row = row.copy()
159
+
160
+ # Process each column that needs database loading
161
+ for column_name in load_from_db_columns:
162
+ if column_name not in updated_row:
163
+ continue
164
+
165
+ # The column value should be the name of the global variable to lookup
166
+ variable_name = updated_row[column_name]
167
+ if not variable_name:
168
+ continue
169
+
170
+ try:
171
+ if is_noop_session:
172
+ # Fallback to environment variables
173
+ key = os.getenv(variable_name)
174
+ if key:
175
+ logger.info(f"Using environment variable {variable_name} for table column {column_name}")
176
+ else:
177
+ logger.error(f"Environment variable {variable_name} is not set.")
178
+ else:
179
+ # Load from database
180
+ key = await custom_component.get_variable(
181
+ name=variable_name, field=f"{table_field_name}.{column_name}", session=session
182
+ )
183
+
184
+ except ValueError as e:
185
+ if "User id is not set" in str(e):
186
+ raise
187
+ logger.debug(str(e))
188
+ key = None
189
+
190
+ # If we couldn't get from database and fallback is enabled, try environment
191
+ if fallback_to_env_vars and key is None:
192
+ key = os.getenv(variable_name)
193
+ if key:
194
+ logger.info(f"Using environment variable {variable_name} for table column {column_name}")
195
+ else:
196
+ logger.error(f"Environment variable {variable_name} is not set.")
197
+
198
+ # Update the column value with the resolved value
199
+ updated_row[column_name] = key if key is not None else None
200
+ if key is None:
201
+ logger.warning(
202
+ f"Could not get value for {variable_name} in table column {column_name}. Setting it to None."
203
+ )
204
+
205
+ updated_table_data.append(updated_row)
206
+
207
+ params[table_field_name] = updated_table_data
208
+ return params
209
+
210
+
129
211
  async def update_params_with_load_from_db_fields(
130
212
  custom_component: CustomComponent,
131
213
  params,
@@ -142,27 +224,38 @@ async def update_params_with_load_from_db_fields(
142
224
  logger.debug("Loading variables from environment variables because database is not available.")
143
225
  return load_from_env_vars(params, load_from_db_fields)
144
226
  for field in load_from_db_fields:
145
- if field not in params or not params[field]:
146
- continue
147
-
148
- try:
149
- key = await custom_component.get_variable(name=params[field], field=field, session=session)
150
- except ValueError as e:
151
- if any(reason in str(e) for reason in ["User id is not set", "variable not found."]):
152
- raise
153
- logger.debug(str(e))
154
- key = None
155
-
156
- if fallback_to_env_vars and key is None:
157
- key = os.getenv(params[field])
158
- if key:
159
- logger.info(f"Using environment variable {params[field]} for {field}")
160
- else:
161
- logger.error(f"Environment variable {params[field]} is not set.")
162
-
163
- params[field] = key if key is not None else None
164
- if key is None:
165
- logger.warning(f"Could not get value for {field}. Setting it to None.")
227
+ # Check if this is a table field (using our naming convention)
228
+ if field.startswith("table:"):
229
+ table_field_name = field[6:] # Remove "table:" prefix
230
+ params = await update_table_params_with_load_from_db_fields(
231
+ custom_component,
232
+ params,
233
+ table_field_name,
234
+ fallback_to_env_vars=fallback_to_env_vars,
235
+ )
236
+ else:
237
+ # Handle regular field-level load_from_db
238
+ if field not in params or not params[field]:
239
+ continue
240
+
241
+ try:
242
+ key = await custom_component.get_variable(name=params[field], field=field, session=session)
243
+ except ValueError as e:
244
+ if any(reason in str(e) for reason in ["User id is not set", "variable not found."]):
245
+ raise
246
+ logger.debug(str(e))
247
+ key = None
248
+
249
+ if fallback_to_env_vars and key is None:
250
+ key = os.getenv(params[field])
251
+ if key:
252
+ logger.info(f"Using environment variable {params[field]} for {field}")
253
+ else:
254
+ logger.error(f"Environment variable {params[field]} is not set.")
255
+
256
+ params[field] = key if key is not None else None
257
+ if key is None:
258
+ logger.warning(f"Could not get value for {field}. Setting it to None.")
166
259
 
167
260
  return params
168
261
 
lfx/schema/table.py CHANGED
@@ -44,6 +44,8 @@ class Column(BaseModel):
44
44
  disable_edit: bool = Field(default=False)
45
45
  edit_mode: EditMode | None = Field(default=EditMode.POPOVER)
46
46
  hidden: bool = Field(default=False)
47
+ load_from_db: bool = Field(default=False)
48
+ """Whether this column's default value should be loaded from global variables"""
47
49
 
48
50
  @model_validator(mode="after")
49
51
  def set_display_name(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lfx-nightly
3
- Version: 0.1.12.dev25
3
+ Version: 0.1.12.dev27
4
4
  Summary: Langflow Executor - A lightweight CLI tool for executing and serving Langflow AI flows
5
5
  Author-email: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
6
6
  Requires-Python: <3.14,>=3.10
@@ -7,13 +7,13 @@ lfx/type_extraction.py,sha256=eCZNl9nAQivKdaPv_9BK71N0JV9Rtr--veAht0dnQ4A,2921
7
7
  lfx/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  lfx/base/constants.py,sha256=v9vo0Ifg8RxDu__XqgGzIXHlsnUFyWM-SSux0uHHoz8,1187
9
9
  lfx/base/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- lfx/base/agents/agent.py,sha256=ZePHU8aGDP3_oVXDMFh2SHA44KlRtJU6irkV9cqBq5M,10968
10
+ lfx/base/agents/agent.py,sha256=O8NHVX5m5zjCTdTJ8kcNPKWBfQLwpJvPSuWV0RfHql4,11270
11
11
  lfx/base/agents/callback.py,sha256=mjlT9ukBMVrfjYrHsJowqpY4g9hVGBVBIYhncLWr3tQ,3692
12
12
  lfx/base/agents/context.py,sha256=u0wboX1aRR22Ia8gY14WF12RjhE0Rxv9hPBiixT9DtQ,3916
13
13
  lfx/base/agents/default_prompts.py,sha256=tUjfczwt4D5R1KozNOl1uSL2V2rSCZeUMS-cfV4Gwn0,955
14
14
  lfx/base/agents/errors.py,sha256=4QY1AqSWZaOjq-iQRYH_aeCfH_hWECLQkiwybNXz66U,531
15
15
  lfx/base/agents/events.py,sha256=1SLai0H5pvorojgBL7l_xbtJ7gpkcddd5IWyUw25UTg,14035
16
- lfx/base/agents/utils.py,sha256=PYt_Mh3pdZD-n6PUamR3MeTSkwQJPWeqr3vxwfoLke8,5876
16
+ lfx/base/agents/utils.py,sha256=mxtYSl1tUghgV55CXnep6zMOOxs8kVdgwvLtX0oPmUE,5939
17
17
  lfx/base/agents/crewai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  lfx/base/agents/crewai/crew.py,sha256=TN1JyLXMpJc2yPH3tokhFmxKKYoJ4lMvmG19DmpKfeY,7953
19
19
  lfx/base/agents/crewai/tasks.py,sha256=1pBok1UDdAjLtOf2Y-rDrjRaM93no-XLy5Bf_zvWsRM,151
@@ -110,7 +110,7 @@ lfx/components/Notion/update_page_property.py,sha256=tgmPMbD1eX58dQQNXv1w5FzDec7
110
110
  lfx/components/agentql/__init__.py,sha256=Erl669Dzsk-SegsDPWTtkKbprMXVuv8UTCo5REzZGTc,56
111
111
  lfx/components/agentql/agentql_api.py,sha256=N94yEK7ZuQCIsFBlr_8dqrJY-K1-KNb6QEEYfDIsDME,5569
112
112
  lfx/components/agents/__init__.py,sha256=u1PH9Ui0dUgTdTZVP7cdVysCv4extdusKS_brcbE7Eg,1049
113
- lfx/components/agents/agent.py,sha256=zPI-8TRbzzuQUEcBMICqjdUjnRZ98x4PB-DhJqV447M,26597
113
+ lfx/components/agents/agent.py,sha256=gUZ5RTgf_6G8Yi6QnQRuC4qn1rh2eeIF9MHQL8G-D3k,26592
114
114
  lfx/components/agents/mcp_component.py,sha256=dW0eENDKz8esIShOooDEL48r3J3GoI1h0tuqIPLSnR4,25462
115
115
  lfx/components/aiml/__init__.py,sha256=DNKB-HMFGFYmsdkON-s8557ttgBXVXADmS-BcuSQiIQ,1087
116
116
  lfx/components/aiml/aiml.py,sha256=23Ineg1ajlCoqXgWgp50I20OnQbaleRNsw1c6IzPu3A,3877
@@ -596,7 +596,7 @@ lfx/graph/vertex/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
596
596
  lfx/graph/vertex/base.py,sha256=drvm5o-y2NMyZ99uupHqjh4lUl8kIV4SeYol-q7FTdQ,33310
597
597
  lfx/graph/vertex/constants.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
598
598
  lfx/graph/vertex/exceptions.py,sha256=QTe-7TRCI0TXswRZh1kh0Z3KySjQsJgY5zTU6o0jboQ,193
599
- lfx/graph/vertex/param_handler.py,sha256=gmvcc8cYH43YMKAs-Z5-etDBhI779_mZFfK4DoXqbN0,10738
599
+ lfx/graph/vertex/param_handler.py,sha256=ugIsqxXd5YHYixbufW39VDgrfDICvI-im2U_oxiOWGM,12887
600
600
  lfx/graph/vertex/schema.py,sha256=3h6c7TTdZI1mzfAebhD-6CCCRLu1mQ8UDmgJijx5zWg,552
601
601
  lfx/graph/vertex/utils.py,sha256=iJmY4PXta5dYWTX2SMEbpfMKrzwkJVQmi8qstSv8D7I,738
602
602
  lfx/graph/vertex/vertex_types.py,sha256=r4eMlTUTWR5CQf-W34BBzpHpQ9KdWcK3L-2byE22enU,21140
@@ -618,7 +618,7 @@ lfx/interface/utils.py,sha256=qKi2HRg-QgeI3hmXLMtG6DHBbaQPuVMW5-o9lcN7j0Q,3790
618
618
  lfx/interface/importing/__init__.py,sha256=uPlvLJZ_XQ4eK08GjfqOyoQ0ercc2ApRO-JRSB26z1o,154
619
619
  lfx/interface/importing/utils.py,sha256=-3-M4MSzA_2zlwRWy1SdJHDsjeRkFvWZaTynITRj1x8,1460
620
620
  lfx/interface/initialize/__init__.py,sha256=wxisnaYxjaqrjA_-By2oHmd4Fht5lAAJFYrotkPm7HA,45
621
- lfx/interface/initialize/loading.py,sha256=QSkK10ZRfrmfa-h8YLiT-MACJHZZuxnJEGFgvy7eyZI,8308
621
+ lfx/interface/initialize/loading.py,sha256=WF6sp20wYvY52nKbAQpPDrzGKBHwW5xEz45qnGZBc_o,12229
622
622
  lfx/io/__init__.py,sha256=hIH6GC2gKdupGZVyRqrbOIm9UyUhNqIga8z1jd4ri2w,1131
623
623
  lfx/io/schema.py,sha256=ddF10TCK2TLx4rGSFCP-NTEDpTS7wyG4WzpZ0HJgZ2c,10404
624
624
  lfx/load/__init__.py,sha256=y35GBUhVTOsG3GzL5UVL-RNAsu0D7T8MVPrNXoDMx7U,224
@@ -649,7 +649,7 @@ lfx/schema/openai_responses_schemas.py,sha256=drMCAlliefHfGRojBTMepPwk4DyEGh67na
649
649
  lfx/schema/properties.py,sha256=ZRY6FUDfqpc5wQ-bi-ZuUUrusF9t-pt9fQa_FNPpia0,1356
650
650
  lfx/schema/schema.py,sha256=XbIuvD64EdVljP1V32tsEL-ETXOQSFipMDaiMGzYttM,5079
651
651
  lfx/schema/serialize.py,sha256=Y7aL91w3BW4ZYkgdIHosUYdpIJUDku-SoqYoIQtwtGM,252
652
- lfx/schema/table.py,sha256=BQFuO3Vn9msGFAx6t2sofyQS44hW6xH12773KMAymSw,4537
652
+ lfx/schema/table.py,sha256=1RdMmk1vbzmPFW0JEGhP7WDDRtvUKH9lkDw5v-JWhSw,4668
653
653
  lfx/schema/validators.py,sha256=1CC4jU3sFmPnauie_U_Xb_QpcnsBf3XT7oWphr5Lt8U,4023
654
654
  lfx/serialization/__init__.py,sha256=g-CG7Y--Eog6mSPMI7wqXh6J8lYygFthqmJWrCa3P7k,145
655
655
  lfx/serialization/constants.py,sha256=mAYNbapEPu9-KixSHVPCXUyM-bsFMjSoCc4ohkQGvQY,47
@@ -718,7 +718,7 @@ lfx/utils/schemas.py,sha256=NbOtVQBrn4d0BAu-0H_eCTZI2CXkKZlRY37XCSmuJwc,3865
718
718
  lfx/utils/util.py,sha256=xGR32XDRr_TtruhjnXfI7lEWmk-vgywHAy3kz5SBowc,15725
719
719
  lfx/utils/util_strings.py,sha256=nU_IcdphNaj6bAPbjeL-c1cInQPfTBit8mp5Y57lwQk,1686
720
720
  lfx/utils/version.py,sha256=cHpbO0OJD2JQAvVaTH_6ibYeFbHJV0QDHs_YXXZ-bT8,671
721
- lfx_nightly-0.1.12.dev25.dist-info/METADATA,sha256=iJ9KDTFj1LdeBt0dQnjhRIbQIgKYXHKput5c5iCemEQ,8068
722
- lfx_nightly-0.1.12.dev25.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
723
- lfx_nightly-0.1.12.dev25.dist-info/entry_points.txt,sha256=1724p3RHDQRT2CKx_QRzEIa7sFuSVO0Ux70YfXfoMT4,42
724
- lfx_nightly-0.1.12.dev25.dist-info/RECORD,,
721
+ lfx_nightly-0.1.12.dev27.dist-info/METADATA,sha256=p2TGyWv_8_LFW3SYqHt2ph5T9V4jQnQ0_fV5T4l8cHQ,8068
722
+ lfx_nightly-0.1.12.dev27.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
723
+ lfx_nightly-0.1.12.dev27.dist-info/entry_points.txt,sha256=1724p3RHDQRT2CKx_QRzEIa7sFuSVO0Ux70YfXfoMT4,42
724
+ lfx_nightly-0.1.12.dev27.dist-info/RECORD,,