lfx-nightly 0.1.13.dev0__py3-none-any.whl → 0.2.0.dev26__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.
Files changed (237) hide show
  1. lfx/_assets/component_index.json +1 -1
  2. lfx/base/agents/agent.py +121 -29
  3. lfx/base/agents/altk_base_agent.py +380 -0
  4. lfx/base/agents/altk_tool_wrappers.py +565 -0
  5. lfx/base/agents/events.py +103 -35
  6. lfx/base/agents/utils.py +15 -2
  7. lfx/base/composio/composio_base.py +183 -233
  8. lfx/base/data/base_file.py +88 -21
  9. lfx/base/data/storage_utils.py +192 -0
  10. lfx/base/data/utils.py +178 -14
  11. lfx/base/datastax/__init__.py +5 -0
  12. lfx/{components/vectorstores/astradb.py → base/datastax/astradb_base.py} +84 -473
  13. lfx/base/embeddings/embeddings_class.py +113 -0
  14. lfx/base/io/chat.py +5 -4
  15. lfx/base/mcp/util.py +101 -15
  16. lfx/base/models/groq_constants.py +74 -58
  17. lfx/base/models/groq_model_discovery.py +265 -0
  18. lfx/base/models/model.py +1 -1
  19. lfx/base/models/model_input_constants.py +74 -7
  20. lfx/base/models/model_utils.py +100 -0
  21. lfx/base/models/ollama_constants.py +3 -0
  22. lfx/base/models/openai_constants.py +7 -0
  23. lfx/base/models/watsonx_constants.py +36 -0
  24. lfx/base/tools/run_flow.py +601 -129
  25. lfx/cli/commands.py +7 -4
  26. lfx/cli/common.py +2 -2
  27. lfx/cli/run.py +1 -1
  28. lfx/cli/script_loader.py +53 -11
  29. lfx/components/Notion/create_page.py +1 -1
  30. lfx/components/Notion/list_database_properties.py +1 -1
  31. lfx/components/Notion/list_pages.py +1 -1
  32. lfx/components/Notion/list_users.py +1 -1
  33. lfx/components/Notion/page_content_viewer.py +1 -1
  34. lfx/components/Notion/search.py +1 -1
  35. lfx/components/Notion/update_page_property.py +1 -1
  36. lfx/components/__init__.py +19 -5
  37. lfx/components/altk/__init__.py +34 -0
  38. lfx/components/altk/altk_agent.py +193 -0
  39. lfx/components/amazon/amazon_bedrock_converse.py +1 -1
  40. lfx/components/apify/apify_actor.py +4 -4
  41. lfx/components/composio/__init__.py +70 -18
  42. lfx/components/composio/apollo_composio.py +11 -0
  43. lfx/components/composio/bitbucket_composio.py +11 -0
  44. lfx/components/composio/canva_composio.py +11 -0
  45. lfx/components/composio/coda_composio.py +11 -0
  46. lfx/components/composio/composio_api.py +10 -0
  47. lfx/components/composio/discord_composio.py +1 -1
  48. lfx/components/composio/elevenlabs_composio.py +11 -0
  49. lfx/components/composio/exa_composio.py +11 -0
  50. lfx/components/composio/firecrawl_composio.py +11 -0
  51. lfx/components/composio/fireflies_composio.py +11 -0
  52. lfx/components/composio/gmail_composio.py +1 -1
  53. lfx/components/composio/googlebigquery_composio.py +11 -0
  54. lfx/components/composio/googlecalendar_composio.py +1 -1
  55. lfx/components/composio/googledocs_composio.py +1 -1
  56. lfx/components/composio/googlemeet_composio.py +1 -1
  57. lfx/components/composio/googlesheets_composio.py +1 -1
  58. lfx/components/composio/googletasks_composio.py +1 -1
  59. lfx/components/composio/heygen_composio.py +11 -0
  60. lfx/components/composio/mem0_composio.py +11 -0
  61. lfx/components/composio/peopledatalabs_composio.py +11 -0
  62. lfx/components/composio/perplexityai_composio.py +11 -0
  63. lfx/components/composio/serpapi_composio.py +11 -0
  64. lfx/components/composio/slack_composio.py +3 -574
  65. lfx/components/composio/slackbot_composio.py +1 -1
  66. lfx/components/composio/snowflake_composio.py +11 -0
  67. lfx/components/composio/tavily_composio.py +11 -0
  68. lfx/components/composio/youtube_composio.py +2 -2
  69. lfx/components/{agents → cuga}/__init__.py +5 -7
  70. lfx/components/cuga/cuga_agent.py +730 -0
  71. lfx/components/data/__init__.py +78 -28
  72. lfx/components/data_source/__init__.py +58 -0
  73. lfx/components/{data → data_source}/api_request.py +26 -3
  74. lfx/components/{data → data_source}/csv_to_data.py +15 -10
  75. lfx/components/{data → data_source}/json_to_data.py +15 -8
  76. lfx/components/{data → data_source}/news_search.py +1 -1
  77. lfx/components/{data → data_source}/rss.py +1 -1
  78. lfx/components/{data → data_source}/sql_executor.py +1 -1
  79. lfx/components/{data → data_source}/url.py +1 -1
  80. lfx/components/{data → data_source}/web_search.py +1 -1
  81. lfx/components/datastax/__init__.py +12 -6
  82. lfx/components/datastax/{astra_assistant_manager.py → astradb_assistant_manager.py} +1 -0
  83. lfx/components/datastax/astradb_chatmemory.py +40 -0
  84. lfx/components/datastax/astradb_cql.py +6 -32
  85. lfx/components/datastax/astradb_graph.py +10 -124
  86. lfx/components/datastax/astradb_tool.py +13 -53
  87. lfx/components/datastax/astradb_vectorstore.py +134 -977
  88. lfx/components/datastax/create_assistant.py +1 -0
  89. lfx/components/datastax/create_thread.py +1 -0
  90. lfx/components/datastax/dotenv.py +1 -0
  91. lfx/components/datastax/get_assistant.py +1 -0
  92. lfx/components/datastax/getenvvar.py +1 -0
  93. lfx/components/datastax/graph_rag.py +1 -1
  94. lfx/components/datastax/hcd.py +1 -1
  95. lfx/components/datastax/list_assistants.py +1 -0
  96. lfx/components/datastax/run.py +1 -0
  97. lfx/components/deactivated/json_document_builder.py +1 -1
  98. lfx/components/elastic/elasticsearch.py +1 -1
  99. lfx/components/elastic/opensearch_multimodal.py +1575 -0
  100. lfx/components/files_and_knowledge/__init__.py +47 -0
  101. lfx/components/{data → files_and_knowledge}/directory.py +1 -1
  102. lfx/components/{data → files_and_knowledge}/file.py +246 -18
  103. lfx/components/{knowledge_bases → files_and_knowledge}/ingestion.py +17 -9
  104. lfx/components/{knowledge_bases → files_and_knowledge}/retrieval.py +18 -10
  105. lfx/components/{data → files_and_knowledge}/save_file.py +142 -22
  106. lfx/components/flow_controls/__init__.py +58 -0
  107. lfx/components/{logic → flow_controls}/conditional_router.py +1 -1
  108. lfx/components/{logic → flow_controls}/loop.py +47 -9
  109. lfx/components/flow_controls/run_flow.py +108 -0
  110. lfx/components/glean/glean_search_api.py +1 -1
  111. lfx/components/groq/groq.py +35 -28
  112. lfx/components/helpers/__init__.py +102 -0
  113. lfx/components/ibm/watsonx.py +25 -21
  114. lfx/components/input_output/__init__.py +3 -1
  115. lfx/components/input_output/chat.py +12 -3
  116. lfx/components/input_output/chat_output.py +12 -4
  117. lfx/components/input_output/text.py +1 -1
  118. lfx/components/input_output/text_output.py +1 -1
  119. lfx/components/{data → input_output}/webhook.py +1 -1
  120. lfx/components/knowledge_bases/__init__.py +59 -4
  121. lfx/components/langchain_utilities/character.py +1 -1
  122. lfx/components/langchain_utilities/csv_agent.py +84 -16
  123. lfx/components/langchain_utilities/json_agent.py +67 -12
  124. lfx/components/langchain_utilities/language_recursive.py +1 -1
  125. lfx/components/llm_operations/__init__.py +46 -0
  126. lfx/components/{processing → llm_operations}/batch_run.py +1 -1
  127. lfx/components/{processing → llm_operations}/lambda_filter.py +1 -1
  128. lfx/components/{logic → llm_operations}/llm_conditional_router.py +1 -1
  129. lfx/components/{processing/llm_router.py → llm_operations/llm_selector.py} +3 -3
  130. lfx/components/{processing → llm_operations}/structured_output.py +56 -18
  131. lfx/components/logic/__init__.py +126 -0
  132. lfx/components/mem0/mem0_chat_memory.py +11 -0
  133. lfx/components/mistral/mistral_embeddings.py +1 -1
  134. lfx/components/models/__init__.py +64 -9
  135. lfx/components/models_and_agents/__init__.py +49 -0
  136. lfx/components/{agents → models_and_agents}/agent.py +49 -6
  137. lfx/components/models_and_agents/embedding_model.py +423 -0
  138. lfx/components/models_and_agents/language_model.py +398 -0
  139. lfx/components/{agents → models_and_agents}/mcp_component.py +84 -45
  140. lfx/components/{helpers → models_and_agents}/memory.py +1 -1
  141. lfx/components/nvidia/system_assist.py +1 -1
  142. lfx/components/olivya/olivya.py +1 -1
  143. lfx/components/ollama/ollama.py +235 -14
  144. lfx/components/openrouter/openrouter.py +49 -147
  145. lfx/components/processing/__init__.py +9 -57
  146. lfx/components/processing/converter.py +1 -1
  147. lfx/components/processing/dataframe_operations.py +1 -1
  148. lfx/components/processing/parse_json_data.py +2 -2
  149. lfx/components/processing/parser.py +7 -2
  150. lfx/components/processing/split_text.py +1 -1
  151. lfx/components/qdrant/qdrant.py +1 -1
  152. lfx/components/redis/redis.py +1 -1
  153. lfx/components/twelvelabs/split_video.py +10 -0
  154. lfx/components/twelvelabs/video_file.py +12 -0
  155. lfx/components/utilities/__init__.py +43 -0
  156. lfx/components/{helpers → utilities}/calculator_core.py +1 -1
  157. lfx/components/{helpers → utilities}/current_date.py +1 -1
  158. lfx/components/{processing → utilities}/python_repl_core.py +1 -1
  159. lfx/components/vectorstores/__init__.py +0 -6
  160. lfx/components/vectorstores/local_db.py +9 -0
  161. lfx/components/youtube/youtube_transcripts.py +118 -30
  162. lfx/custom/custom_component/component.py +60 -3
  163. lfx/custom/custom_component/custom_component.py +68 -6
  164. lfx/field_typing/constants.py +1 -0
  165. lfx/graph/edge/base.py +45 -22
  166. lfx/graph/graph/base.py +5 -2
  167. lfx/graph/graph/schema.py +3 -2
  168. lfx/graph/state/model.py +15 -2
  169. lfx/graph/utils.py +6 -0
  170. lfx/graph/vertex/base.py +4 -1
  171. lfx/graph/vertex/param_handler.py +10 -7
  172. lfx/graph/vertex/vertex_types.py +1 -1
  173. lfx/helpers/__init__.py +12 -0
  174. lfx/helpers/flow.py +117 -0
  175. lfx/inputs/input_mixin.py +24 -1
  176. lfx/inputs/inputs.py +13 -1
  177. lfx/interface/components.py +161 -83
  178. lfx/io/schema.py +6 -0
  179. lfx/log/logger.py +5 -3
  180. lfx/schema/schema.py +5 -0
  181. lfx/services/database/__init__.py +5 -0
  182. lfx/services/database/service.py +25 -0
  183. lfx/services/deps.py +87 -22
  184. lfx/services/manager.py +19 -6
  185. lfx/services/mcp_composer/service.py +998 -157
  186. lfx/services/session.py +5 -0
  187. lfx/services/settings/base.py +51 -7
  188. lfx/services/settings/constants.py +8 -0
  189. lfx/services/storage/local.py +76 -46
  190. lfx/services/storage/service.py +152 -29
  191. lfx/template/field/base.py +3 -0
  192. lfx/utils/ssrf_protection.py +384 -0
  193. lfx/utils/validate_cloud.py +26 -0
  194. {lfx_nightly-0.1.13.dev0.dist-info → lfx_nightly-0.2.0.dev26.dist-info}/METADATA +38 -22
  195. {lfx_nightly-0.1.13.dev0.dist-info → lfx_nightly-0.2.0.dev26.dist-info}/RECORD +210 -196
  196. {lfx_nightly-0.1.13.dev0.dist-info → lfx_nightly-0.2.0.dev26.dist-info}/WHEEL +1 -1
  197. lfx/components/agents/cuga_agent.py +0 -1013
  198. lfx/components/datastax/astra_db.py +0 -77
  199. lfx/components/datastax/cassandra.py +0 -92
  200. lfx/components/logic/run_flow.py +0 -71
  201. lfx/components/models/embedding_model.py +0 -114
  202. lfx/components/models/language_model.py +0 -144
  203. lfx/components/vectorstores/astradb_graph.py +0 -326
  204. lfx/components/vectorstores/cassandra.py +0 -264
  205. lfx/components/vectorstores/cassandra_graph.py +0 -238
  206. lfx/components/vectorstores/chroma.py +0 -167
  207. lfx/components/vectorstores/clickhouse.py +0 -135
  208. lfx/components/vectorstores/couchbase.py +0 -102
  209. lfx/components/vectorstores/elasticsearch.py +0 -267
  210. lfx/components/vectorstores/faiss.py +0 -111
  211. lfx/components/vectorstores/graph_rag.py +0 -141
  212. lfx/components/vectorstores/hcd.py +0 -314
  213. lfx/components/vectorstores/milvus.py +0 -115
  214. lfx/components/vectorstores/mongodb_atlas.py +0 -213
  215. lfx/components/vectorstores/opensearch.py +0 -243
  216. lfx/components/vectorstores/pgvector.py +0 -72
  217. lfx/components/vectorstores/pinecone.py +0 -134
  218. lfx/components/vectorstores/qdrant.py +0 -109
  219. lfx/components/vectorstores/supabase.py +0 -76
  220. lfx/components/vectorstores/upstash.py +0 -124
  221. lfx/components/vectorstores/vectara.py +0 -97
  222. lfx/components/vectorstores/vectara_rag.py +0 -164
  223. lfx/components/vectorstores/weaviate.py +0 -89
  224. /lfx/components/{data → data_source}/mock_data.py +0 -0
  225. /lfx/components/datastax/{astra_vectorize.py → astradb_vectorize.py} +0 -0
  226. /lfx/components/{logic → flow_controls}/data_conditional_router.py +0 -0
  227. /lfx/components/{logic → flow_controls}/flow_tool.py +0 -0
  228. /lfx/components/{logic → flow_controls}/listen.py +0 -0
  229. /lfx/components/{logic → flow_controls}/notify.py +0 -0
  230. /lfx/components/{logic → flow_controls}/pass_message.py +0 -0
  231. /lfx/components/{logic → flow_controls}/sub_flow.py +0 -0
  232. /lfx/components/{processing → models_and_agents}/prompt.py +0 -0
  233. /lfx/components/{helpers → processing}/create_list.py +0 -0
  234. /lfx/components/{helpers → processing}/output_parser.py +0 -0
  235. /lfx/components/{helpers → processing}/store_message.py +0 -0
  236. /lfx/components/{helpers → utilities}/id_generator.py +0 -0
  237. {lfx_nightly-0.1.13.dev0.dist-info → lfx_nightly-0.2.0.dev26.dist-info}/entry_points.txt +0 -0
@@ -1,34 +1,28 @@
1
+ """Data module - backwards compatibility alias for data_source.
2
+
3
+ This module provides backwards compatibility by forwarding all imports
4
+ to data_source where the actual data components are located.
5
+ """
6
+
1
7
  from __future__ import annotations
2
8
 
3
- from typing import TYPE_CHECKING, Any
9
+ from typing import Any
4
10
 
5
11
  from lfx.components._importing import import_mod
6
12
 
7
- if TYPE_CHECKING:
8
- from lfx.components.data.api_request import APIRequestComponent
9
- from lfx.components.data.csv_to_data import CSVToDataComponent
10
- from lfx.components.data.directory import DirectoryComponent
11
- from lfx.components.data.file import FileComponent
12
- from lfx.components.data.json_to_data import JSONToDataComponent
13
- from lfx.components.data.news_search import NewsSearchComponent
14
- from lfx.components.data.rss import RSSReaderComponent
15
- from lfx.components.data.sql_executor import SQLComponent
16
- from lfx.components.data.url import URLComponent
17
- from lfx.components.data.web_search import WebSearchComponent
18
- from lfx.components.data.webhook import WebhookComponent
19
-
13
+ # Replicate the same dynamic imports as data_source
20
14
  _dynamic_imports = {
21
15
  "APIRequestComponent": "api_request",
22
16
  "CSVToDataComponent": "csv_to_data",
23
- "DirectoryComponent": "directory",
24
- "FileComponent": "file",
25
17
  "JSONToDataComponent": "json_to_data",
26
- "SQLComponent": "sql_executor",
27
- "URLComponent": "url",
28
- "WebSearchComponent": "web_search",
29
- "WebhookComponent": "webhook",
18
+ "MockDataGeneratorComponent": "mock_data",
30
19
  "NewsSearchComponent": "news_search",
31
20
  "RSSReaderComponent": "rss",
21
+ "URLComponent": "url",
22
+ "WebSearchComponent": "web_search",
23
+ # File and Directory components are in files_and_knowledge, forward them for backwards compatibility
24
+ "FileComponent": ("file", "files_and_knowledge"),
25
+ "DirectoryComponent": ("directory", "files_and_knowledge"),
32
26
  }
33
27
 
34
28
  __all__ = [
@@ -37,28 +31,84 @@ __all__ = [
37
31
  "DirectoryComponent",
38
32
  "FileComponent",
39
33
  "JSONToDataComponent",
34
+ "MockDataGeneratorComponent",
40
35
  "NewsSearchComponent",
41
36
  "RSSReaderComponent",
42
- "SQLComponent",
43
37
  "URLComponent",
44
38
  "WebSearchComponent",
45
- "WebhookComponent",
46
39
  ]
47
40
 
48
41
 
49
42
  def __getattr__(attr_name: str) -> Any:
50
- """Lazily import data components on attribute access."""
43
+ """Forward attribute access to data_source components."""
44
+ # Handle submodule access for backwards compatibility
45
+ # e.g., lfx.components.data.directory -> lfx.components.files_and_knowledge.directory
46
+ if attr_name == "directory":
47
+ from importlib import import_module
48
+
49
+ result = import_module("lfx.components.files_and_knowledge.directory")
50
+ globals()[attr_name] = result
51
+ return result
52
+ if attr_name == "file":
53
+ from importlib import import_module
54
+
55
+ result = import_module("lfx.components.files_and_knowledge.file")
56
+ globals()[attr_name] = result
57
+ return result
58
+ # Data source components were moved to data_source
59
+ if attr_name == "news_search":
60
+ from importlib import import_module
61
+
62
+ result = import_module("lfx.components.data_source.news_search")
63
+ globals()[attr_name] = result
64
+ return result
65
+ if attr_name == "rss":
66
+ from importlib import import_module
67
+
68
+ result = import_module("lfx.components.data_source.rss")
69
+ globals()[attr_name] = result
70
+ return result
71
+ if attr_name == "web_search":
72
+ from importlib import import_module
73
+
74
+ result = import_module("lfx.components.data_source.web_search")
75
+ globals()[attr_name] = result
76
+ return result
77
+ # SQLComponent was moved to utilities
78
+ if attr_name == "sql_executor":
79
+ from importlib import import_module
80
+
81
+ result = import_module("lfx.components.utilities.sql_executor")
82
+ globals()[attr_name] = result
83
+ return result
84
+
51
85
  if attr_name not in _dynamic_imports:
52
86
  msg = f"module '{__name__}' has no attribute '{attr_name}'"
53
87
  raise AttributeError(msg)
54
- try:
55
- result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
56
- except (ModuleNotFoundError, ImportError, AttributeError) as e:
57
- msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
58
- raise AttributeError(msg) from e
88
+
89
+ mapping = _dynamic_imports[attr_name]
90
+
91
+ # Handle FileComponent and DirectoryComponent which are in files_and_knowledge
92
+ if isinstance(mapping, tuple):
93
+ module_name, package = mapping
94
+ try:
95
+ result = import_mod(attr_name, module_name, f"lfx.components.{package}")
96
+ except (ModuleNotFoundError, ImportError, AttributeError) as e:
97
+ msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
98
+ raise AttributeError(msg) from e
99
+ else:
100
+ # Import from data_source using the correct package path
101
+ package = "lfx.components.data_source"
102
+ try:
103
+ result = import_mod(attr_name, mapping, package)
104
+ except (ModuleNotFoundError, ImportError, AttributeError) as e:
105
+ msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
106
+ raise AttributeError(msg) from e
107
+
59
108
  globals()[attr_name] = result
60
109
  return result
61
110
 
62
111
 
63
112
  def __dir__() -> list[str]:
113
+ """Return directory of available components."""
64
114
  return list(__all__)
@@ -0,0 +1,58 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any
4
+
5
+ from lfx.components._importing import import_mod
6
+
7
+ if TYPE_CHECKING:
8
+ from lfx.components.data_source.api_request import APIRequestComponent
9
+ from lfx.components.data_source.csv_to_data import CSVToDataComponent
10
+ from lfx.components.data_source.json_to_data import JSONToDataComponent
11
+ from lfx.components.data_source.mock_data import MockDataGeneratorComponent
12
+ from lfx.components.data_source.news_search import NewsSearchComponent
13
+ from lfx.components.data_source.rss import RSSReaderComponent
14
+ from lfx.components.data_source.sql_executor import SQLComponent
15
+ from lfx.components.data_source.url import URLComponent
16
+ from lfx.components.data_source.web_search import WebSearchComponent
17
+
18
+ _dynamic_imports = {
19
+ "APIRequestComponent": "api_request",
20
+ "CSVToDataComponent": "csv_to_data",
21
+ "JSONToDataComponent": "json_to_data",
22
+ "MockDataGeneratorComponent": "mock_data",
23
+ "NewsSearchComponent": "news_search",
24
+ "RSSReaderComponent": "rss",
25
+ "URLComponent": "url",
26
+ "WebSearchComponent": "web_search",
27
+ "SQLComponent": "sql_executor",
28
+ }
29
+
30
+ __all__ = [
31
+ "APIRequestComponent",
32
+ "CSVToDataComponent",
33
+ "JSONToDataComponent",
34
+ "MockDataGeneratorComponent",
35
+ "NewsSearchComponent",
36
+ "RSSReaderComponent",
37
+ "SQLComponent",
38
+ "URLComponent",
39
+ "WebSearchComponent",
40
+ ]
41
+
42
+
43
+ def __getattr__(attr_name: str) -> Any:
44
+ """Lazily import data source components on attribute access."""
45
+ if attr_name not in _dynamic_imports:
46
+ msg = f"module '{__name__}' has no attribute '{attr_name}'"
47
+ raise AttributeError(msg)
48
+ try:
49
+ result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
50
+ except (ModuleNotFoundError, ImportError, AttributeError) as e:
51
+ msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
52
+ raise AttributeError(msg) from e
53
+ globals()[attr_name] = result
54
+ return result
55
+
56
+
57
+ def __dir__() -> list[str]:
58
+ return list(__all__)
@@ -27,6 +27,7 @@ from lfx.io import (
27
27
  from lfx.schema.data import Data
28
28
  from lfx.schema.dotdict import dotdict
29
29
  from lfx.utils.component_utils import set_current_fields, set_field_advanced, set_field_display
30
+ from lfx.utils.ssrf_protection import SSRFProtectionError, validate_url_for_ssrf
30
31
 
31
32
  # Define fields for each mode
32
33
  MODE_FIELDS = {
@@ -44,7 +45,7 @@ DEFAULT_FIELDS = ["mode"]
44
45
  class APIRequestComponent(Component):
45
46
  display_name = "API Request"
46
47
  description = "Make HTTP requests using URL or cURL commands."
47
- documentation: str = "https://docs.langflow.org/components-data#api-request"
48
+ documentation: str = "https://docs.langflow.org/api-request"
48
49
  icon = "Globe"
49
50
  name = "APIRequest"
50
51
 
@@ -145,8 +146,13 @@ class APIRequestComponent(Component):
145
146
  BoolInput(
146
147
  name="follow_redirects",
147
148
  display_name="Follow Redirects",
148
- value=True,
149
- info="Whether to follow http redirects.",
149
+ value=False,
150
+ info=(
151
+ "Whether to follow HTTP redirects. "
152
+ "WARNING: Enabling redirects may allow SSRF bypass attacks where a public URL "
153
+ "redirects to internal resources. Only enable if you trust the target server. "
154
+ "See OWASP SSRF Prevention Cheat Sheet for details."
155
+ ),
150
156
  advanced=True,
151
157
  ),
152
158
  BoolInput(
@@ -424,6 +430,14 @@ class APIRequestComponent(Component):
424
430
  save_to_file = self.save_to_file
425
431
  include_httpx_metadata = self.include_httpx_metadata
426
432
 
433
+ # Security warning when redirects are enabled
434
+ if follow_redirects:
435
+ self.log(
436
+ "Security Warning: HTTP redirects are enabled. This may allow SSRF bypass attacks "
437
+ "where a public URL redirects to internal resources (e.g., cloud metadata endpoints). "
438
+ "Only enable this if you trust the target server."
439
+ )
440
+
427
441
  # if self.mode == "cURL" and self.curl_input:
428
442
  # self._build_config = self.parse_curl(self.curl_input, dotdict())
429
443
  # # After parsing curl, get the normalized URL
@@ -437,6 +451,15 @@ class APIRequestComponent(Component):
437
451
  msg = f"Invalid URL provided: {url}"
438
452
  raise ValueError(msg)
439
453
 
454
+ # SSRF Protection: Validate URL to prevent access to internal resources
455
+ # TODO: In next major version (2.0), remove warn_only=True to enforce blocking
456
+ try:
457
+ validate_url_for_ssrf(url, warn_only=True)
458
+ except SSRFProtectionError as e:
459
+ # This will only raise if SSRF protection is enabled and warn_only=False
460
+ msg = f"SSRF Protection: {e}"
461
+ raise ValueError(msg) from e
462
+
440
463
  # Process query parameters
441
464
  if isinstance(self.query_params, str):
442
465
  query_params = dict(parse_qsl(self.query_params))
@@ -2,9 +2,11 @@ import csv
2
2
  import io
3
3
  from pathlib import Path
4
4
 
5
+ from lfx.base.data.storage_utils import read_file_text
5
6
  from lfx.custom.custom_component.component import Component
6
7
  from lfx.io import FileInput, MessageTextInput, MultilineInput, Output
7
8
  from lfx.schema.data import Data
9
+ from lfx.utils.async_helpers import run_until_complete
8
10
 
9
11
 
10
12
  class CSVToDataComponent(Component):
@@ -52,21 +54,24 @@ class CSVToDataComponent(Component):
52
54
  csv_data = None
53
55
  try:
54
56
  if self.csv_file:
55
- resolved_path = self.resolve_path(self.csv_file)
56
- file_path = Path(resolved_path)
57
- if file_path.suffix.lower() != ".csv":
57
+ # FileInput always provides a local file path
58
+ file_path = self.csv_file
59
+ if not file_path.lower().endswith(".csv"):
58
60
  self.status = "The provided file must be a CSV file."
59
61
  else:
60
- with file_path.open(newline="", encoding="utf-8") as csvfile:
61
- csv_data = csvfile.read()
62
+ # Resolve to absolute path and read from local filesystem
63
+ resolved_path = self.resolve_path(file_path)
64
+ csv_bytes = Path(resolved_path).read_bytes()
65
+ csv_data = csv_bytes.decode("utf-8")
62
66
 
63
67
  elif self.csv_path:
64
- file_path = Path(self.csv_path)
65
- if file_path.suffix.lower() != ".csv":
66
- self.status = "The provided file must be a CSV file."
68
+ file_path = self.csv_path
69
+ if not file_path.lower().endswith(".csv"):
70
+ self.status = "The provided path must be to a CSV file."
67
71
  else:
68
- with file_path.open(newline="", encoding="utf-8") as csvfile:
69
- csv_data = csvfile.read()
72
+ csv_data = run_until_complete(
73
+ read_file_text(file_path, encoding="utf-8", resolve_path=self.resolve_path, newline="")
74
+ )
70
75
 
71
76
  else:
72
77
  csv_data = self.csv_string
@@ -3,9 +3,11 @@ from pathlib import Path
3
3
 
4
4
  from json_repair import repair_json
5
5
 
6
+ from lfx.base.data.storage_utils import read_file_text
6
7
  from lfx.custom.custom_component.component import Component
7
8
  from lfx.io import FileInput, MessageTextInput, MultilineInput, Output
8
9
  from lfx.schema.data import Data
10
+ from lfx.utils.async_helpers import run_until_complete
9
11
 
10
12
 
11
13
  class JSONToDataComponent(Component):
@@ -51,19 +53,24 @@ class JSONToDataComponent(Component):
51
53
 
52
54
  try:
53
55
  if self.json_file:
54
- resolved_path = self.resolve_path(self.json_file)
55
- file_path = Path(resolved_path)
56
- if file_path.suffix.lower() != ".json":
56
+ # FileInput always provides a local file path
57
+ file_path = self.json_file
58
+ if not file_path.lower().endswith(".json"):
57
59
  self.status = "The provided file must be a JSON file."
58
60
  else:
59
- json_data = file_path.read_text(encoding="utf-8")
61
+ # Resolve to absolute path and read from local filesystem
62
+ resolved_path = self.resolve_path(file_path)
63
+ json_data = Path(resolved_path).read_text(encoding="utf-8")
60
64
 
61
65
  elif self.json_path:
62
- file_path = Path(self.json_path)
63
- if file_path.suffix.lower() != ".json":
64
- self.status = "The provided file must be a JSON file."
66
+ # User-provided text path - could be local or S3 key
67
+ file_path = self.json_path
68
+ if not file_path.lower().endswith(".json"):
69
+ self.status = "The provided path must be to a JSON file."
65
70
  else:
66
- json_data = file_path.read_text(encoding="utf-8")
71
+ json_data = run_until_complete(
72
+ read_file_text(file_path, encoding="utf-8", resolve_path=self.resolve_path)
73
+ )
67
74
 
68
75
  else:
69
76
  json_data = self.json_string
@@ -12,7 +12,7 @@ from lfx.schema import DataFrame
12
12
  class NewsSearchComponent(Component):
13
13
  display_name = "News Search"
14
14
  description = "Searches Google News via RSS. Returns clean article data."
15
- documentation: str = "https://docs.langflow.org/components-data#news-search"
15
+ documentation: str = "https://docs.langflow.org/web-search"
16
16
  icon = "newspaper"
17
17
  name = "NewsSearch"
18
18
  legacy = True
@@ -11,7 +11,7 @@ from lfx.schema import DataFrame
11
11
  class RSSReaderComponent(Component):
12
12
  display_name = "RSS Reader"
13
13
  description = "Fetches and parses an RSS feed."
14
- documentation: str = "https://docs.langflow.org/components-data#rss-reader"
14
+ documentation: str = "https://docs.langflow.org/web-search"
15
15
  icon = "rss"
16
16
  name = "RSSReaderSimple"
17
17
  legacy = True
@@ -18,7 +18,7 @@ class SQLComponent(ComponentWithCache):
18
18
 
19
19
  display_name = "SQL Database"
20
20
  description = "Executes SQL queries on SQLAlchemy-compatible databases."
21
- documentation: str = "https://docs.langflow.org/components-data#sql-database"
21
+ documentation: str = "https://docs.langflow.org/sql-database"
22
22
  icon = "database"
23
23
  name = "SQLComponent"
24
24
  metadata = {"keywords": ["sql", "database", "query", "db", "fetch"]}
@@ -48,7 +48,7 @@ class URLComponent(Component):
48
48
 
49
49
  display_name = "URL"
50
50
  description = "Fetch content from one or more web pages, following links recursively."
51
- documentation: str = "https://docs.langflow.org/components-data#url"
51
+ documentation: str = "https://docs.langflow.org/url"
52
52
  icon = "layout-template"
53
53
  name = "URLComponent"
54
54
 
@@ -21,7 +21,7 @@ from lfx.utils.request_utils import get_user_agent
21
21
  class WebSearchComponent(Component):
22
22
  display_name = "Web Search"
23
23
  description = "Search the web, news, or RSS feeds."
24
- documentation: str = "https://docs.langflow.org/components-data#web-search"
24
+ documentation: str = "https://docs.langflow.org/web-search"
25
25
  icon = "search"
26
26
  name = "UnifiedWebSearch"
27
27
 
@@ -5,17 +5,19 @@ from typing import TYPE_CHECKING, Any
5
5
  from lfx.components._importing import import_mod
6
6
 
7
7
  if TYPE_CHECKING:
8
- from .astra_assistant_manager import AstraAssistantManager
9
- from .astra_db import AstraDBChatMemory
10
- from .astra_vectorize import AstraVectorizeComponent
8
+ from .astradb_assistant_manager import AstraAssistantManager
9
+ from .astradb_chatmemory import AstraDBChatMemory
11
10
  from .astradb_cql import AstraDBCQLToolComponent
11
+ from .astradb_graph import AstraDBGraphVectorStoreComponent
12
12
  from .astradb_tool import AstraDBToolComponent
13
+ from .astradb_vectorize import AstraVectorizeComponent
13
14
  from .astradb_vectorstore import AstraDBVectorStoreComponent
14
15
  from .create_assistant import AssistantsCreateAssistant
15
16
  from .create_thread import AssistantsCreateThread
16
17
  from .dotenv import Dotenv
17
18
  from .get_assistant import AssistantsGetAssistantName
18
19
  from .getenvvar import GetEnvVar
20
+ from .graph_rag import GraphRAGComponent
19
21
  from .list_assistants import AssistantsListAssistants
20
22
  from .run import AssistantsRun
21
23
 
@@ -25,14 +27,16 @@ _dynamic_imports = {
25
27
  "AssistantsGetAssistantName": "get_assistant",
26
28
  "AssistantsListAssistants": "list_assistants",
27
29
  "AssistantsRun": "run",
28
- "AstraAssistantManager": "astra_assistant_manager",
30
+ "AstraAssistantManager": "astradb_assistant_manager",
29
31
  "AstraDBCQLToolComponent": "astradb_cql",
30
- "AstraDBChatMemory": "astra_db",
32
+ "AstraDBChatMemory": "astradb_chatmemory",
33
+ "AstraDBGraphVectorStoreComponent": "astradb_graph",
31
34
  "AstraDBToolComponent": "astradb_tool",
32
35
  "AstraDBVectorStoreComponent": "astradb_vectorstore",
33
- "AstraVectorizeComponent": "astra_vectorize",
36
+ "AstraVectorizeComponent": "astradb_vectorize",
34
37
  "Dotenv": "dotenv",
35
38
  "GetEnvVar": "getenvvar",
39
+ "GraphRAGComponent": "graph_rag",
36
40
  }
37
41
 
38
42
  __all__ = [
@@ -44,11 +48,13 @@ __all__ = [
44
48
  "AstraAssistantManager",
45
49
  "AstraDBCQLToolComponent",
46
50
  "AstraDBChatMemory",
51
+ "AstraDBGraphVectorStoreComponent",
47
52
  "AstraDBToolComponent",
48
53
  "AstraDBVectorStoreComponent",
49
54
  "AstraVectorizeComponent",
50
55
  "Dotenv",
51
56
  "GetEnvVar",
57
+ "GraphRAGComponent",
52
58
  ]
53
59
 
54
60
 
@@ -30,6 +30,7 @@ class AstraAssistantManager(ComponentWithCache):
30
30
  name = "Astra Assistant Agent"
31
31
  description = "Manages Assistant Interactions"
32
32
  icon = "AstraDB"
33
+ legacy = True
33
34
 
34
35
  inputs = [
35
36
  DropdownInput(
@@ -0,0 +1,40 @@
1
+ from lfx.base.datastax.astradb_base import AstraDBBaseComponent
2
+ from lfx.base.memory.model import LCChatMemoryComponent
3
+ from lfx.field_typing.constants import Memory
4
+ from lfx.inputs.inputs import MessageTextInput
5
+
6
+
7
+ class AstraDBChatMemory(AstraDBBaseComponent, LCChatMemoryComponent):
8
+ display_name = "Astra DB Chat Memory"
9
+ description = "Retrieves and stores chat messages from Astra DB."
10
+ name = "AstraDBChatMemory"
11
+ icon: str = "AstraDB"
12
+
13
+ inputs = [
14
+ *AstraDBBaseComponent.inputs,
15
+ MessageTextInput(
16
+ name="session_id",
17
+ display_name="Session ID",
18
+ info="The session ID of the chat. If empty, the current session ID parameter will be used.",
19
+ advanced=True,
20
+ ),
21
+ ]
22
+
23
+ def build_message_history(self) -> Memory:
24
+ try:
25
+ from langchain_astradb.chat_message_histories import AstraDBChatMessageHistory
26
+ except ImportError as e:
27
+ msg = (
28
+ "Could not import langchain Astra DB integration package. "
29
+ "Please install it with `uv pip install langchain-astradb`."
30
+ )
31
+ raise ImportError(msg) from e
32
+
33
+ return AstraDBChatMessageHistory(
34
+ session_id=self.session_id,
35
+ collection_name=self.collection_name,
36
+ token=self.token,
37
+ api_endpoint=self.get_api_endpoint(),
38
+ namespace=self.get_keyspace(),
39
+ environment=self.environment,
40
+ )
@@ -8,20 +8,22 @@ import requests
8
8
  from langchain_core.tools import StructuredTool, Tool
9
9
  from pydantic import BaseModel, Field, create_model
10
10
 
11
+ from lfx.base.datastax.astradb_base import AstraDBBaseComponent
11
12
  from lfx.base.langchain_utilities.model import LCToolComponent
12
- from lfx.io import DictInput, IntInput, SecretStrInput, StrInput, TableInput
13
+ from lfx.io import DictInput, IntInput, StrInput, TableInput
13
14
  from lfx.log.logger import logger
14
15
  from lfx.schema.data import Data
15
16
  from lfx.schema.table import EditMode
16
17
 
17
18
 
18
- class AstraDBCQLToolComponent(LCToolComponent):
19
+ class AstraDBCQLToolComponent(AstraDBBaseComponent, LCToolComponent):
19
20
  display_name: str = "Astra DB CQL"
20
21
  description: str = "Create a tool to get transactional data from DataStax Astra DB CQL Table"
21
- documentation: str = "https://docs.langflow.org/bundles-datastax#astra-db-cql"
22
+ documentation: str = "https://docs.langflow.org/bundles-datastax"
22
23
  icon: str = "AstraDB"
23
24
 
24
25
  inputs = [
26
+ *AstraDBBaseComponent.inputs,
25
27
  StrInput(name="tool_name", display_name="Tool Name", info="The name of the tool.", required=True),
26
28
  StrInput(
27
29
  name="tool_description",
@@ -29,34 +31,6 @@ class AstraDBCQLToolComponent(LCToolComponent):
29
31
  info="The tool description to be passed to the model.",
30
32
  required=True,
31
33
  ),
32
- StrInput(
33
- name="keyspace",
34
- display_name="Keyspace",
35
- value="default_keyspace",
36
- info="The keyspace name within Astra DB where the data is stored.",
37
- required=True,
38
- advanced=True,
39
- ),
40
- StrInput(
41
- name="table_name",
42
- display_name="Table Name",
43
- info="The name of the table within Astra DB where the data is stored.",
44
- required=True,
45
- ),
46
- SecretStrInput(
47
- name="token",
48
- display_name="Astra DB Application Token",
49
- info="Authentication token for accessing Astra DB.",
50
- value="ASTRA_DB_APPLICATION_TOKEN",
51
- required=True,
52
- ),
53
- StrInput(
54
- name="api_endpoint",
55
- display_name="API Endpoint",
56
- info="API endpoint URL for the Astra DB service.",
57
- value="ASTRA_DB_API_ENDPOINT",
58
- required=True,
59
- ),
60
34
  StrInput(
61
35
  name="projection_fields",
62
36
  display_name="Projection fields",
@@ -204,7 +178,7 @@ class AstraDBCQLToolComponent(LCToolComponent):
204
178
 
205
179
  def astra_rest(self, args):
206
180
  headers = {"Accept": "application/json", "X-Cassandra-Token": f"{self.token}"}
207
- astra_url = f"{self.api_endpoint}/api/rest/v2/keyspaces/{self.keyspace}/{self.table_name}/"
181
+ astra_url = f"{self.get_api_endpoint()}/api/rest/v2/keyspaces/{self.get_keyspace()}/{self.collection_name}/"
208
182
  where = {}
209
183
 
210
184
  for param in self.tools_params: