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
@@ -0,0 +1,113 @@
1
+ """Extended embeddings class with available models metadata."""
2
+
3
+ from langchain_core.embeddings import Embeddings
4
+
5
+
6
+ class EmbeddingsWithModels(Embeddings):
7
+ """Extended Embeddings class that includes available models with dedicated instances.
8
+
9
+ This class inherits from LangChain Embeddings and provides a mapping of model names
10
+ to their dedicated embedding instances, enabling multi-model support without the need
11
+ for dynamic model switching.
12
+
13
+ Attributes:
14
+ embeddings: The primary LangChain Embeddings instance (used as fallback).
15
+ available_models: Dict mapping model names to their dedicated Embeddings instances.
16
+ Each model has its own pre-configured instance with specific parameters.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ embeddings: Embeddings,
22
+ available_models: dict[str, Embeddings] | None = None,
23
+ ):
24
+ """Initialize the EmbeddingsWithModels wrapper.
25
+
26
+ Args:
27
+ embeddings: The primary LangChain Embeddings instance (used as default/fallback).
28
+ available_models: Dict mapping model names to dedicated Embeddings instances.
29
+ Each value should be a fully configured Embeddings object ready to use.
30
+ Defaults to empty dict if not provided.
31
+ """
32
+ super().__init__()
33
+ self.embeddings = embeddings
34
+ self.available_models = available_models if available_models is not None else {}
35
+
36
+ def embed_documents(self, texts: list[str]) -> list[list[float]]:
37
+ """Embed search docs by delegating to the underlying embeddings instance.
38
+
39
+ Args:
40
+ texts: List of text to embed.
41
+
42
+ Returns:
43
+ List of embeddings.
44
+ """
45
+ return self.embeddings.embed_documents(texts)
46
+
47
+ def embed_query(self, text: str) -> list[float]:
48
+ """Embed query text by delegating to the underlying embeddings instance.
49
+
50
+ Args:
51
+ text: Text to embed.
52
+
53
+ Returns:
54
+ Embedding.
55
+ """
56
+ return self.embeddings.embed_query(text)
57
+
58
+ async def aembed_documents(self, texts: list[str]) -> list[list[float]]:
59
+ """Asynchronously embed search docs.
60
+
61
+ Args:
62
+ texts: List of text to embed.
63
+
64
+ Returns:
65
+ List of embeddings.
66
+ """
67
+ return await self.embeddings.aembed_documents(texts)
68
+
69
+ async def aembed_query(self, text: str) -> list[float]:
70
+ """Asynchronously embed query text.
71
+
72
+ Args:
73
+ text: Text to embed.
74
+
75
+ Returns:
76
+ Embedding.
77
+ """
78
+ return await self.embeddings.aembed_query(text)
79
+
80
+ def __call__(self, *args, **kwargs):
81
+ """Make the class callable by delegating to the underlying embeddings instance.
82
+
83
+ This handles cases where the embeddings object is used as a callable.
84
+
85
+ Args:
86
+ *args: Positional arguments to pass to the underlying embeddings instance.
87
+ **kwargs: Keyword arguments to pass to the underlying embeddings instance.
88
+
89
+ Returns:
90
+ The result of calling the underlying embeddings instance.
91
+ """
92
+ if callable(self.embeddings):
93
+ return self.embeddings(*args, **kwargs)
94
+ msg = f"'{type(self.embeddings).__name__}' object is not callable"
95
+ raise TypeError(msg)
96
+
97
+ def __getattr__(self, name: str):
98
+ """Delegate attribute access to the underlying embeddings instance.
99
+
100
+ This ensures full compatibility with any additional methods or attributes
101
+ that the underlying embeddings instance might have.
102
+
103
+ Args:
104
+ name: The attribute name to access.
105
+
106
+ Returns:
107
+ The attribute from the underlying embeddings instance.
108
+ """
109
+ return getattr(self.embeddings, name)
110
+
111
+ def __repr__(self) -> str:
112
+ """Return string representation of the wrapper."""
113
+ return f"EmbeddingsWithModels(embeddings={self.embeddings!r}, available_models={self.available_models!r})"
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}")
@@ -1,87 +1,91 @@
1
1
  from .model_metadata import create_model_metadata
2
2
 
3
- # Unified model metadata - single source of truth
3
+ # Unified model metadata
4
+ #
5
+ # NOTE: This file serves as a FALLBACK when the dynamic model discovery system
6
+ # (groq_model_discovery.py) cannot fetch fresh data from the Groq API.
7
+ #
8
+ # The dynamic system is the PRIMARY source and will:
9
+ # - Fetch available models directly from Groq API
10
+ # - Test each model for tool calling support automatically
11
+ # - Cache results for 24 hours
12
+ # - Always provide up-to-date model lists
13
+ #
14
+ # This fallback list should contain:
15
+ # - Minimal set of stable production models
16
+ # - Deprecated models for backwards compatibility
17
+ # - Non-LLM models (audio, TTS) marked as not_supported
18
+ #
19
+ # Last manually updated: 2025-01-06
20
+ #
4
21
  GROQ_MODELS_DETAILED = [
5
- # Production Models - Stable and reliable for production use
6
- create_model_metadata( # Google
7
- provider="Groq", name="gemma2-9b-it", icon="Groq", tool_calling=True
8
- ),
9
- create_model_metadata( # Meta
10
- provider="Groq", name="llama-3.3-70b-versatile", icon="Groq", tool_calling=True
11
- ),
12
- create_model_metadata( # Meta
13
- provider="Groq", name="llama-3.1-8b-instant", icon="Groq"
14
- ),
15
- create_model_metadata( # Meta
16
- provider="Groq", name="llama-guard-3-8b", icon="Groq"
22
+ # ===== FALLBACK PRODUCTION MODELS =====
23
+ # These are stable models that are very unlikely to be removed
24
+ create_model_metadata(provider="Groq", name="llama-3.1-8b-instant", icon="Groq", tool_calling=True),
25
+ create_model_metadata(provider="Groq", name="llama-3.3-70b-versatile", icon="Groq", tool_calling=True),
26
+ # ===== DEPRECATED MODELS =====
27
+ # Keep these for backwards compatibility - users may have flows using them
28
+ # These will appear in the list but show as deprecated in the UI
29
+ create_model_metadata( # Google - Removed
30
+ provider="Groq", name="gemma2-9b-it", icon="Groq", deprecated=True
17
31
  ),
18
- create_model_metadata( # Meta
19
- provider="Groq", name="llama3-70b-8192", icon="Groq"
20
- ),
21
- create_model_metadata( # Meta
22
- provider="Groq", name="llama3-8b-8192", icon="Groq"
23
- ),
24
- # Preview Models - For evaluation purposes only
25
- create_model_metadata( # Meta
26
- provider="Groq", name="meta-llama/llama-4-scout-17b-16e-instruct", icon="Groq", tool_calling=True, preview=True
32
+ create_model_metadata( # Google
33
+ provider="Groq", name="gemma-7b-it", icon="Groq", deprecated=True
27
34
  ),
28
- create_model_metadata( # Meta
29
- provider="Groq",
30
- name="meta-llama/llama-4-maverick-17b-128e-instruct",
31
- icon="Groq",
32
- tool_calling=True,
33
- preview=True,
35
+ create_model_metadata( # Meta - Removed
36
+ provider="Groq", name="llama3-70b-8192", icon="Groq", deprecated=True
34
37
  ),
35
- create_model_metadata( # Alibaba Cloud
36
- provider="Groq", name="qwen-qwq-32b", icon="Groq", tool_calling=True, preview=True
38
+ create_model_metadata( # Meta - Removed
39
+ provider="Groq", name="llama3-8b-8192", icon="Groq", deprecated=True
37
40
  ),
38
- create_model_metadata( # Alibaba Cloud
39
- provider="Groq", name="qwen-2.5-coder-32b", icon="Groq", tool_calling=True, preview=True
41
+ create_model_metadata( # Meta - Removed, replaced by llama-guard-4-12b
42
+ provider="Groq", name="llama-guard-3-8b", icon="Groq", deprecated=True
40
43
  ),
41
- create_model_metadata( # Alibaba Cloud
42
- provider="Groq", name="qwen-2.5-32b", icon="Groq", tool_calling=True, preview=True
44
+ create_model_metadata( # Meta - Removed
45
+ provider="Groq", name="llama-3.2-1b-preview", icon="Groq", deprecated=True
43
46
  ),
44
- create_model_metadata( # DeepSeek
45
- provider="Groq", name="deepseek-r1-distill-qwen-32b", icon="Groq", tool_calling=True, preview=True
47
+ create_model_metadata( # Meta - Removed
48
+ provider="Groq", name="llama-3.2-3b-preview", icon="Groq", deprecated=True
46
49
  ),
47
- create_model_metadata( # DeepSeek
48
- provider="Groq", name="deepseek-r1-distill-llama-70b", icon="Groq", preview=True
50
+ create_model_metadata( # Meta - Removed
51
+ provider="Groq", name="llama-3.2-11b-vision-preview", icon="Groq", deprecated=True
49
52
  ),
50
- create_model_metadata( # Meta
51
- provider="Groq", name="llama-3.3-70b-specdec", icon="Groq", tool_calling=True, preview=True
53
+ create_model_metadata( # Meta - Removed
54
+ provider="Groq", name="llama-3.2-90b-vision-preview", icon="Groq", deprecated=True
52
55
  ),
53
- create_model_metadata( # Meta
54
- provider="Groq", name="llama-3.2-1b-preview", icon="Groq", tool_calling=True, preview=True
56
+ create_model_metadata( # Meta - Removed
57
+ provider="Groq", name="llama-3.3-70b-specdec", icon="Groq", deprecated=True
55
58
  ),
56
- create_model_metadata( # Meta
57
- provider="Groq", name="llama-3.2-3b-preview", icon="Groq", tool_calling=True, preview=True
59
+ create_model_metadata( # Alibaba - Removed, replaced by qwen/qwen3-32b
60
+ provider="Groq", name="qwen-qwq-32b", icon="Groq", deprecated=True
58
61
  ),
59
- create_model_metadata( # Meta
60
- provider="Groq", name="llama-3.2-11b-vision-preview", icon="Groq", preview=True
62
+ create_model_metadata( # Alibaba - Removed
63
+ provider="Groq", name="qwen-2.5-coder-32b", icon="Groq", deprecated=True
61
64
  ),
62
- create_model_metadata( # Meta
63
- provider="Groq", name="llama-3.2-90b-vision-preview", icon="Groq", tool_calling=True, preview=True
65
+ create_model_metadata( # Alibaba - Removed
66
+ provider="Groq", name="qwen-2.5-32b", icon="Groq", deprecated=True
64
67
  ),
65
- create_model_metadata( # Saudi Data and AI Authority (SDAIA)
66
- provider="Groq", name="allam-2-7b", icon="Groq", preview=True
68
+ create_model_metadata( # DeepSeek - Removed
69
+ provider="Groq", name="deepseek-r1-distill-qwen-32b", icon="Groq", deprecated=True
67
70
  ),
68
- # Deprecated Models - Previously available but now removed
69
- create_model_metadata( # Google
70
- provider="Groq", name="gemma-7b-it", icon="Groq", tool_calling=True, deprecated=True
71
+ create_model_metadata( # DeepSeek - Removed
72
+ provider="Groq", name="deepseek-r1-distill-llama-70b", icon="Groq", deprecated=True
71
73
  ),
72
74
  create_model_metadata( # Groq
73
- provider="Groq", name="llama3-groq-70b-8192-tool-use-preview", icon="Groq", tool_calling=True, deprecated=True
75
+ provider="Groq", name="llama3-groq-70b-8192-tool-use-preview", icon="Groq", deprecated=True
74
76
  ),
75
77
  create_model_metadata( # Groq
76
- provider="Groq", name="llama3-groq-8b-8192-tool-use-preview", icon="Groq", tool_calling=True, deprecated=True
78
+ provider="Groq", name="llama3-groq-8b-8192-tool-use-preview", icon="Groq", deprecated=True
77
79
  ),
78
80
  create_model_metadata( # Meta
79
- provider="Groq", name="llama-3.1-70b-versatile", icon="Groq", tool_calling=True, deprecated=True
81
+ provider="Groq", name="llama-3.1-70b-versatile", icon="Groq", deprecated=True
80
82
  ),
81
83
  create_model_metadata( # Mistral
82
- provider="Groq", name="mixtral-8x7b-32768", icon="Groq", tool_calling=True, deprecated=True
84
+ provider="Groq", name="mixtral-8x7b-32768", icon="Groq", deprecated=True
83
85
  ),
84
- # Unsupported Models
86
+ # ===== UNSUPPORTED MODELS =====
87
+ # Audio/TTS/Guard models that should not appear in LLM model lists
88
+ # The dynamic system automatically filters these out
85
89
  create_model_metadata( # Mistral
86
90
  provider="Groq", name="mistral-saba-24b", icon="Groq", not_supported=True
87
91
  ),
@@ -100,6 +104,18 @@ GROQ_MODELS_DETAILED = [
100
104
  create_model_metadata( # Hugging Face
101
105
  provider="Groq", name="distil-whisper-large-v3-en", icon="Groq", not_supported=True
102
106
  ),
107
+ create_model_metadata( # Meta
108
+ provider="Groq", name="meta-llama/llama-guard-4-12b", icon="Groq", not_supported=True
109
+ ),
110
+ create_model_metadata( # Meta
111
+ provider="Groq", name="meta-llama/llama-prompt-guard-2-86m", icon="Groq", not_supported=True
112
+ ),
113
+ create_model_metadata( # Meta
114
+ provider="Groq", name="meta-llama/llama-prompt-guard-2-22m", icon="Groq", not_supported=True
115
+ ),
116
+ create_model_metadata( # OpenAI
117
+ provider="Groq", name="openai/gpt-oss-safeguard-20b", icon="Groq", not_supported=True
118
+ ),
103
119
  ]
104
120
 
105
121
  # Generate backwards-compatible lists from the metadata