lfx-nightly 0.1.13.dev2__py3-none-any.whl → 0.1.13.dev4__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.

Files changed (67) hide show
  1. lfx/_assets/component_index.json +1 -1
  2. lfx/base/agents/agent.py +17 -1
  3. lfx/base/agents/utils.py +15 -2
  4. lfx/base/composio/composio_base.py +24 -9
  5. lfx/base/datastax/__init__.py +5 -0
  6. lfx/{components/vectorstores/astradb.py → base/datastax/astradb_base.py} +84 -473
  7. lfx/base/io/chat.py +5 -4
  8. lfx/base/mcp/util.py +101 -15
  9. lfx/cli/commands.py +1 -1
  10. lfx/components/agents/agent.py +1 -1
  11. lfx/components/agents/cuga_agent.py +1 -1
  12. lfx/components/agents/mcp_component.py +16 -0
  13. lfx/components/amazon/amazon_bedrock_converse.py +1 -1
  14. lfx/components/apify/apify_actor.py +3 -3
  15. lfx/components/datastax/__init__.py +12 -6
  16. lfx/components/datastax/{astra_assistant_manager.py → astradb_assistant_manager.py} +1 -0
  17. lfx/components/datastax/astradb_chatmemory.py +40 -0
  18. lfx/components/datastax/astradb_cql.py +5 -31
  19. lfx/components/datastax/astradb_graph.py +9 -123
  20. lfx/components/datastax/astradb_tool.py +12 -52
  21. lfx/components/datastax/astradb_vectorstore.py +133 -976
  22. lfx/components/datastax/create_assistant.py +1 -0
  23. lfx/components/datastax/create_thread.py +1 -0
  24. lfx/components/datastax/dotenv.py +1 -0
  25. lfx/components/datastax/get_assistant.py +1 -0
  26. lfx/components/datastax/getenvvar.py +1 -0
  27. lfx/components/datastax/graph_rag.py +1 -1
  28. lfx/components/datastax/list_assistants.py +1 -0
  29. lfx/components/datastax/run.py +1 -0
  30. lfx/components/knowledge_bases/ingestion.py +17 -9
  31. lfx/components/knowledge_bases/retrieval.py +16 -8
  32. lfx/components/mistral/mistral_embeddings.py +1 -1
  33. lfx/components/openrouter/openrouter.py +49 -147
  34. lfx/components/vectorstores/__init__.py +0 -6
  35. lfx/custom/custom_component/component.py +3 -2
  36. lfx/graph/edge/base.py +2 -2
  37. lfx/graph/graph/base.py +1 -1
  38. lfx/graph/graph/schema.py +3 -2
  39. lfx/graph/vertex/vertex_types.py +1 -1
  40. {lfx_nightly-0.1.13.dev2.dist-info → lfx_nightly-0.1.13.dev4.dist-info}/METADATA +1 -1
  41. {lfx_nightly-0.1.13.dev2.dist-info → lfx_nightly-0.1.13.dev4.dist-info}/RECORD +44 -65
  42. lfx/components/datastax/astra_db.py +0 -77
  43. lfx/components/datastax/cassandra.py +0 -92
  44. lfx/components/vectorstores/astradb_graph.py +0 -326
  45. lfx/components/vectorstores/cassandra.py +0 -264
  46. lfx/components/vectorstores/cassandra_graph.py +0 -238
  47. lfx/components/vectorstores/chroma.py +0 -167
  48. lfx/components/vectorstores/clickhouse.py +0 -135
  49. lfx/components/vectorstores/couchbase.py +0 -102
  50. lfx/components/vectorstores/elasticsearch.py +0 -267
  51. lfx/components/vectorstores/faiss.py +0 -111
  52. lfx/components/vectorstores/graph_rag.py +0 -141
  53. lfx/components/vectorstores/hcd.py +0 -314
  54. lfx/components/vectorstores/milvus.py +0 -115
  55. lfx/components/vectorstores/mongodb_atlas.py +0 -213
  56. lfx/components/vectorstores/opensearch.py +0 -243
  57. lfx/components/vectorstores/pgvector.py +0 -72
  58. lfx/components/vectorstores/pinecone.py +0 -134
  59. lfx/components/vectorstores/qdrant.py +0 -109
  60. lfx/components/vectorstores/supabase.py +0 -76
  61. lfx/components/vectorstores/upstash.py +0 -124
  62. lfx/components/vectorstores/vectara.py +0 -97
  63. lfx/components/vectorstores/vectara_rag.py +0 -164
  64. lfx/components/vectorstores/weaviate.py +0 -89
  65. /lfx/components/datastax/{astra_vectorize.py → astradb_vectorize.py} +0 -0
  66. {lfx_nightly-0.1.13.dev2.dist-info → lfx_nightly-0.1.13.dev4.dist-info}/WHEEL +0 -0
  67. {lfx_nightly-0.1.13.dev2.dist-info → lfx_nightly-0.1.13.dev4.dist-info}/entry_points.txt +0 -0
lfx/base/io/chat.py CHANGED
@@ -6,8 +6,9 @@ class ChatComponent(Component):
6
6
  description = "Use as base for chat components."
7
7
 
8
8
  def get_properties_from_source_component(self):
9
- if hasattr(self, "_vertex") and hasattr(self._vertex, "incoming_edges") and self._vertex.incoming_edges:
10
- source_id = self._vertex.incoming_edges[0].source_id
9
+ vertex = self.get_vertex()
10
+ if vertex and hasattr(vertex, "incoming_edges") and vertex.incoming_edges:
11
+ source_id = vertex.incoming_edges[0].source_id
11
12
  source_vertex = self.graph.get_vertex(source_id)
12
13
  component = source_vertex.custom_component
13
14
  source = component.display_name
@@ -15,6 +16,6 @@ class ChatComponent(Component):
15
16
  possible_attributes = ["model_name", "model_id", "model"]
16
17
  for attribute in possible_attributes:
17
18
  if hasattr(component, attribute) and getattr(component, attribute):
18
- return getattr(component, attribute), icon, source, component._id
19
- return source, icon, component.display_name, component._id
19
+ return getattr(component, attribute), icon, source, component.get_id()
20
+ return source, icon, component.display_name, component.get_id()
20
21
  return None, None, None, None
lfx/base/mcp/util.py CHANGED
@@ -35,13 +35,33 @@ HTTP_INTERNAL_SERVER_ERROR = 500
35
35
  HTTP_UNAUTHORIZED = 401
36
36
  HTTP_FORBIDDEN = 403
37
37
 
38
- # MCP Session Manager constants
39
- settings = get_settings_service().settings
40
- MAX_SESSIONS_PER_SERVER = (
41
- settings.mcp_max_sessions_per_server
42
- ) # Maximum number of sessions per server to prevent resource exhaustion
43
- SESSION_IDLE_TIMEOUT = settings.mcp_session_idle_timeout # 5 minutes idle timeout for sessions
44
- SESSION_CLEANUP_INTERVAL = settings.mcp_session_cleanup_interval # Cleanup interval in seconds
38
+ # MCP Session Manager constants - lazy loaded
39
+ _mcp_settings_cache: dict[str, Any] = {}
40
+
41
+
42
+ def _get_mcp_setting(key: str, default: Any = None) -> Any:
43
+ """Lazy load MCP settings from settings service."""
44
+ if key not in _mcp_settings_cache:
45
+ settings = get_settings_service().settings
46
+ _mcp_settings_cache[key] = getattr(settings, key, default)
47
+ return _mcp_settings_cache[key]
48
+
49
+
50
+ def get_max_sessions_per_server() -> int:
51
+ """Get maximum number of sessions per server to prevent resource exhaustion."""
52
+ return _get_mcp_setting("mcp_max_sessions_per_server")
53
+
54
+
55
+ def get_session_idle_timeout() -> int:
56
+ """Get 5 minutes idle timeout for sessions."""
57
+ return _get_mcp_setting("mcp_session_idle_timeout")
58
+
59
+
60
+ def get_session_cleanup_interval() -> int:
61
+ """Get cleanup interval in seconds."""
62
+ return _get_mcp_setting("mcp_session_cleanup_interval")
63
+
64
+
45
65
  # RFC 7230 compliant header name pattern: token = 1*tchar
46
66
  # tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
47
67
  # "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
@@ -65,6 +85,46 @@ ALLOWED_HEADERS = {
65
85
  }
66
86
 
67
87
 
88
+ def create_mcp_http_client_with_ssl_option(
89
+ headers: dict[str, str] | None = None,
90
+ timeout: httpx.Timeout | None = None,
91
+ auth: httpx.Auth | None = None,
92
+ *,
93
+ verify_ssl: bool = True,
94
+ ) -> httpx.AsyncClient:
95
+ """Create an httpx AsyncClient with configurable SSL verification.
96
+
97
+ This is a custom factory that extends the standard MCP client factory
98
+ to support disabling SSL verification for self-signed certificates.
99
+
100
+ Args:
101
+ headers: Optional headers to include with all requests.
102
+ timeout: Request timeout as httpx.Timeout object.
103
+ auth: Optional authentication handler.
104
+ verify_ssl: Whether to verify SSL certificates (default: True).
105
+
106
+ Returns:
107
+ Configured httpx.AsyncClient instance.
108
+ """
109
+ kwargs: dict[str, Any] = {
110
+ "follow_redirects": True,
111
+ "verify": verify_ssl,
112
+ }
113
+
114
+ if timeout is None:
115
+ kwargs["timeout"] = httpx.Timeout(30.0)
116
+ else:
117
+ kwargs["timeout"] = timeout
118
+
119
+ if headers is not None:
120
+ kwargs["headers"] = headers
121
+
122
+ if auth is not None:
123
+ kwargs["auth"] = auth
124
+
125
+ return httpx.AsyncClient(**kwargs)
126
+
127
+
68
128
  def validate_headers(headers: dict[str, str]) -> dict[str, str]:
69
129
  """Validate and sanitize HTTP headers according to RFC 7230.
70
130
 
@@ -432,7 +492,7 @@ class MCPSessionManager:
432
492
  """Periodically clean up idle sessions."""
433
493
  while True:
434
494
  try:
435
- await asyncio.sleep(SESSION_CLEANUP_INTERVAL)
495
+ await asyncio.sleep(get_session_cleanup_interval())
436
496
  await self._cleanup_idle_sessions()
437
497
  except asyncio.CancelledError:
438
498
  break
@@ -450,7 +510,7 @@ class MCPSessionManager:
450
510
  sessions_to_remove = []
451
511
 
452
512
  for session_id, session_info in list(sessions.items()):
453
- if current_time - session_info["last_used"] > SESSION_IDLE_TIMEOUT:
513
+ if current_time - session_info["last_used"] > get_session_idle_timeout():
454
514
  sessions_to_remove.append(session_id)
455
515
 
456
516
  # Clean up idle sessions
@@ -573,7 +633,7 @@ class MCPSessionManager:
573
633
  await self._cleanup_session_by_id(server_key, session_id)
574
634
 
575
635
  # Check if we've reached the maximum number of sessions for this server
576
- if len(sessions) >= MAX_SESSIONS_PER_SERVER:
636
+ if len(sessions) >= get_max_sessions_per_server():
577
637
  # Remove the oldest session
578
638
  oldest_session_id = min(sessions.keys(), key=lambda x: sessions[x]["last_used"])
579
639
  await logger.ainfo(
@@ -675,7 +735,7 @@ class MCPSessionManager:
675
735
 
676
736
  Args:
677
737
  session_id: Unique identifier for this session
678
- connection_params: Connection parameters including URL, headers, timeouts
738
+ connection_params: Connection parameters including URL, headers, timeouts, verify_ssl
679
739
  preferred_transport: If set to "sse", skip Streamable HTTP and go directly to SSE
680
740
 
681
741
  Returns:
@@ -691,6 +751,19 @@ class MCPSessionManager:
691
751
  # Track which transport succeeded
692
752
  used_transport: list[str] = []
693
753
 
754
+ # Get verify_ssl option from connection params, default to True
755
+ verify_ssl = connection_params.get("verify_ssl", True)
756
+
757
+ # Create custom httpx client factory with SSL verification option
758
+ def custom_httpx_factory(
759
+ headers: dict[str, str] | None = None,
760
+ timeout: httpx.Timeout | None = None,
761
+ auth: httpx.Auth | None = None,
762
+ ) -> httpx.AsyncClient:
763
+ return create_mcp_http_client_with_ssl_option(
764
+ headers=headers, timeout=timeout, auth=auth, verify_ssl=verify_ssl
765
+ )
766
+
694
767
  async def session_task():
695
768
  """Background task that keeps the session alive."""
696
769
  streamable_error = None
@@ -705,6 +778,7 @@ class MCPSessionManager:
705
778
  url=connection_params["url"],
706
779
  headers=connection_params["headers"],
707
780
  timeout=connection_params["timeout_seconds"],
781
+ httpx_client_factory=custom_httpx_factory,
708
782
  ) as (read, write, _):
709
783
  session = ClientSession(read, write)
710
784
  async with session:
@@ -745,6 +819,7 @@ class MCPSessionManager:
745
819
  connection_params["headers"],
746
820
  connection_params["timeout_seconds"],
747
821
  sse_read_timeout,
822
+ httpx_client_factory=custom_httpx_factory,
748
823
  ) as (read, write):
749
824
  session = ClientSession(read, write)
750
825
  async with session:
@@ -1196,6 +1271,8 @@ class MCPStreamableHttpClient:
1196
1271
  headers: dict[str, str] | None = None,
1197
1272
  timeout_seconds: int = 30,
1198
1273
  sse_read_timeout_seconds: int = 30,
1274
+ *,
1275
+ verify_ssl: bool = True,
1199
1276
  ) -> list[StructuredTool]:
1200
1277
  """Connect to MCP server using Streamable HTTP transport with SSE fallback (SDK style)."""
1201
1278
  # Validate and sanitize headers early
@@ -1213,12 +1290,13 @@ class MCPStreamableHttpClient:
1213
1290
  msg = f"Invalid Streamable HTTP or SSE URL ({url}): {error_msg}"
1214
1291
  raise ValueError(msg)
1215
1292
  # Store connection parameters for later use in run_tool
1216
- # Include SSE read timeout for fallback
1293
+ # Include SSE read timeout for fallback and SSL verification option
1217
1294
  self._connection_params = {
1218
1295
  "url": url,
1219
1296
  "headers": validated_headers,
1220
1297
  "timeout_seconds": timeout_seconds,
1221
1298
  "sse_read_timeout_seconds": sse_read_timeout_seconds,
1299
+ "verify_ssl": verify_ssl,
1222
1300
  }
1223
1301
  elif headers:
1224
1302
  self._connection_params["headers"] = validated_headers
@@ -1238,11 +1316,18 @@ class MCPStreamableHttpClient:
1238
1316
  return response.tools
1239
1317
 
1240
1318
  async def connect_to_server(
1241
- self, url: str, headers: dict[str, str] | None = None, sse_read_timeout_seconds: int = 30
1319
+ self,
1320
+ url: str,
1321
+ headers: dict[str, str] | None = None,
1322
+ sse_read_timeout_seconds: int = 30,
1323
+ *,
1324
+ verify_ssl: bool = True,
1242
1325
  ) -> list[StructuredTool]:
1243
1326
  """Connect to MCP server using Streamable HTTP with SSE fallback transport (SDK style)."""
1244
1327
  return await asyncio.wait_for(
1245
- self._connect_to_server(url, headers, sse_read_timeout_seconds=sse_read_timeout_seconds),
1328
+ self._connect_to_server(
1329
+ url, headers, sse_read_timeout_seconds=sse_read_timeout_seconds, verify_ssl=verify_ssl
1330
+ ),
1246
1331
  timeout=get_settings_service().settings.mcp_server_timeout,
1247
1332
  )
1248
1333
 
@@ -1473,7 +1558,8 @@ async def update_tools(
1473
1558
  client = mcp_stdio_client
1474
1559
  elif mode in ["Streamable_HTTP", "SSE"]:
1475
1560
  # Streamable HTTP connection with SSE fallback
1476
- tools = await mcp_streamable_http_client.connect_to_server(url, headers=headers)
1561
+ verify_ssl = server_config.get("verify_ssl", True)
1562
+ tools = await mcp_streamable_http_client.connect_to_server(url, headers=headers, verify_ssl=verify_ssl)
1477
1563
  client = mcp_streamable_http_client
1478
1564
  else:
1479
1565
  logger.error(f"Invalid MCP server mode for '{server_name}': {mode}")
lfx/cli/commands.py CHANGED
@@ -43,7 +43,7 @@ def serve_command(
43
43
  host: str = typer.Option("127.0.0.1", "--host", "-h", help="Host to bind the server to"),
44
44
  port: int = typer.Option(8000, "--port", "-p", help="Port to bind the server to"),
45
45
  verbose: bool = typer.Option(False, "--verbose", "-v", help="Show diagnostic output and execution details"), # noqa: FBT001, FBT003
46
- env_file: Path | None = typer.Option( # noqa: B008
46
+ env_file: Path | None = typer.Option(
47
47
  None,
48
48
  "--env-file",
49
49
  help="Path to the .env file containing environment variables",
@@ -161,7 +161,7 @@ class AgentComponent(ToolCallingAgentComponent):
161
161
  },
162
162
  ],
163
163
  ),
164
- *LCToolsAgentComponent._base_inputs,
164
+ *LCToolsAgentComponent.get_base_inputs(),
165
165
  # removed memory inputs from agent component
166
166
  # *memory_inputs,
167
167
  BoolInput(
@@ -185,7 +185,7 @@ class CugaComponent(ToolCallingAgentComponent):
185
185
  },
186
186
  ],
187
187
  ),
188
- *LCToolsAgentComponent._base_inputs,
188
+ *LCToolsAgentComponent.get_base_inputs(),
189
189
  BoolInput(
190
190
  name="add_current_date_tool",
191
191
  display_name="Current Date",
@@ -61,6 +61,7 @@ class MCPToolsComponent(ComponentWithCache):
61
61
  "mcp_server",
62
62
  "tool",
63
63
  "use_cache",
64
+ "verify_ssl",
64
65
  ]
65
66
 
66
67
  display_name = "MCP Tools"
@@ -86,6 +87,16 @@ class MCPToolsComponent(ComponentWithCache):
86
87
  value=False,
87
88
  advanced=True,
88
89
  ),
90
+ BoolInput(
91
+ name="verify_ssl",
92
+ display_name="Verify SSL Certificate",
93
+ info=(
94
+ "Enable SSL certificate verification for HTTPS connections. "
95
+ "Disable only for development/testing with self-signed certificates."
96
+ ),
97
+ value=True,
98
+ advanced=True,
99
+ ),
89
100
  DropdownInput(
90
101
  name="tool",
91
102
  display_name="Tool",
@@ -210,6 +221,11 @@ class MCPToolsComponent(ComponentWithCache):
210
221
  self.tools = []
211
222
  return [], {"name": server_name, "config": server_config}
212
223
 
224
+ # Add verify_ssl option to server config if not present
225
+ if "verify_ssl" not in server_config:
226
+ verify_ssl = getattr(self, "verify_ssl", True)
227
+ server_config["verify_ssl"] = verify_ssl
228
+
213
229
  _, tool_list, tool_cache = await update_tools(
214
230
  server_name=server_name,
215
231
  server_config=server_config,
@@ -16,7 +16,7 @@ class AmazonBedrockConverseComponent(LCModelComponent):
16
16
  beta = True
17
17
 
18
18
  inputs = [
19
- *LCModelComponent._base_inputs,
19
+ *LCModelComponent.get_base_inputs(),
20
20
  DropdownInput(
21
21
  name="model_id",
22
22
  display_name="Model ID",
@@ -92,7 +92,7 @@ class ApifyActorsComponent(Component):
92
92
  """Run the Actor and return node output."""
93
93
  input_ = json.loads(self.run_input)
94
94
  fields = ApifyActorsComponent.parse_dataset_fields(self.dataset_fields) if self.dataset_fields else None
95
- res = self._run_actor(self.actor_id, input_, fields=fields)
95
+ res = self.run_actor(self.actor_id, input_, fields=fields)
96
96
  if self.flatten_dataset:
97
97
  res = [ApifyActorsComponent.flatten(item) for item in res]
98
98
  data = [Data(data=item) for item in res]
@@ -159,7 +159,7 @@ class ApifyActorsComponent(Component):
159
159
  # retrieve if nested, just in case
160
160
  input_dict = input_dict.get("run_input", input_dict)
161
161
 
162
- res = parent._run_actor(actor_id, input_dict)
162
+ res = parent.run_actor(actor_id, input_dict)
163
163
  return "\n\n".join([ApifyActorsComponent.dict_to_json_str(item) for item in res])
164
164
 
165
165
  return ApifyActorRun
@@ -256,7 +256,7 @@ class ApifyActorsComponent(Component):
256
256
  valid_chars = string.ascii_letters + string.digits + "_-"
257
257
  return "".join(char if char in valid_chars else "_" for char in actor_id)
258
258
 
259
- def _run_actor(self, actor_id: str, run_input: dict, fields: list[str] | None = None) -> list[dict]:
259
+ def run_actor(self, actor_id: str, run_input: dict, fields: list[str] | None = None) -> list[dict]:
260
260
  """Run an Apify Actor and return the output dataset.
261
261
 
262
262
  Args:
@@ -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
22
  documentation: str = "https://docs.langflow.org/bundles-datastax#astra-db-cql"
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: