MindsDB 25.7.2.0__py3-none-any.whl → 25.7.4.0__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 MindsDB might be problematic. Click here for more details.

Files changed (69) hide show
  1. mindsdb/__about__.py +1 -1
  2. mindsdb/__main__.py +1 -1
  3. mindsdb/api/a2a/common/server/server.py +16 -6
  4. mindsdb/api/executor/command_executor.py +213 -137
  5. mindsdb/api/executor/datahub/datanodes/integration_datanode.py +5 -1
  6. mindsdb/api/executor/datahub/datanodes/project_datanode.py +14 -3
  7. mindsdb/api/executor/planner/plan_join.py +3 -0
  8. mindsdb/api/executor/planner/plan_join_ts.py +117 -100
  9. mindsdb/api/executor/planner/query_planner.py +1 -0
  10. mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +54 -85
  11. mindsdb/api/http/initialize.py +16 -43
  12. mindsdb/api/http/namespaces/agents.py +24 -21
  13. mindsdb/api/http/namespaces/chatbots.py +83 -120
  14. mindsdb/api/http/namespaces/file.py +1 -1
  15. mindsdb/api/http/namespaces/jobs.py +38 -60
  16. mindsdb/api/http/namespaces/tree.py +69 -61
  17. mindsdb/api/mcp/start.py +2 -0
  18. mindsdb/api/mysql/mysql_proxy/utilities/dump.py +3 -2
  19. mindsdb/integrations/handlers/autogluon_handler/requirements.txt +1 -1
  20. mindsdb/integrations/handlers/autosklearn_handler/requirements.txt +1 -1
  21. mindsdb/integrations/handlers/bigquery_handler/bigquery_handler.py +25 -5
  22. mindsdb/integrations/handlers/chromadb_handler/chromadb_handler.py +3 -3
  23. mindsdb/integrations/handlers/flaml_handler/requirements.txt +1 -1
  24. mindsdb/integrations/handlers/google_calendar_handler/google_calendar_tables.py +82 -73
  25. mindsdb/integrations/handlers/hubspot_handler/requirements.txt +1 -1
  26. mindsdb/integrations/handlers/langchain_handler/langchain_handler.py +83 -76
  27. mindsdb/integrations/handlers/lightwood_handler/requirements.txt +4 -4
  28. mindsdb/integrations/handlers/litellm_handler/litellm_handler.py +16 -3
  29. mindsdb/integrations/handlers/litellm_handler/settings.py +2 -1
  30. mindsdb/integrations/handlers/llama_index_handler/requirements.txt +1 -1
  31. mindsdb/integrations/handlers/pgvector_handler/pgvector_handler.py +106 -90
  32. mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +41 -39
  33. mindsdb/integrations/handlers/s3_handler/s3_handler.py +72 -70
  34. mindsdb/integrations/handlers/salesforce_handler/constants.py +208 -0
  35. mindsdb/integrations/handlers/salesforce_handler/salesforce_handler.py +142 -81
  36. mindsdb/integrations/handlers/salesforce_handler/salesforce_tables.py +12 -4
  37. mindsdb/integrations/handlers/slack_handler/slack_tables.py +141 -161
  38. mindsdb/integrations/handlers/tpot_handler/requirements.txt +1 -1
  39. mindsdb/integrations/handlers/web_handler/urlcrawl_helpers.py +32 -17
  40. mindsdb/integrations/handlers/web_handler/web_handler.py +19 -22
  41. mindsdb/integrations/handlers/youtube_handler/youtube_tables.py +183 -55
  42. mindsdb/integrations/libs/vectordatabase_handler.py +10 -1
  43. mindsdb/integrations/utilities/handler_utils.py +32 -12
  44. mindsdb/interfaces/agents/agents_controller.py +169 -110
  45. mindsdb/interfaces/agents/langchain_agent.py +10 -3
  46. mindsdb/interfaces/data_catalog/data_catalog_loader.py +22 -8
  47. mindsdb/interfaces/database/database.py +38 -13
  48. mindsdb/interfaces/database/integrations.py +20 -5
  49. mindsdb/interfaces/database/projects.py +63 -16
  50. mindsdb/interfaces/database/views.py +86 -60
  51. mindsdb/interfaces/jobs/jobs_controller.py +103 -110
  52. mindsdb/interfaces/knowledge_base/controller.py +33 -5
  53. mindsdb/interfaces/knowledge_base/evaluate.py +53 -9
  54. mindsdb/interfaces/knowledge_base/executor.py +24 -0
  55. mindsdb/interfaces/knowledge_base/llm_client.py +3 -3
  56. mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +21 -13
  57. mindsdb/interfaces/query_context/context_controller.py +100 -133
  58. mindsdb/interfaces/skills/skills_controller.py +18 -6
  59. mindsdb/interfaces/storage/db.py +40 -6
  60. mindsdb/interfaces/variables/variables_controller.py +8 -15
  61. mindsdb/utilities/config.py +3 -3
  62. mindsdb/utilities/functions.py +72 -60
  63. mindsdb/utilities/log.py +38 -6
  64. mindsdb/utilities/ps.py +7 -7
  65. {mindsdb-25.7.2.0.dist-info → mindsdb-25.7.4.0.dist-info}/METADATA +262 -263
  66. {mindsdb-25.7.2.0.dist-info → mindsdb-25.7.4.0.dist-info}/RECORD +69 -68
  67. {mindsdb-25.7.2.0.dist-info → mindsdb-25.7.4.0.dist-info}/WHEEL +0 -0
  68. {mindsdb-25.7.2.0.dist-info → mindsdb-25.7.4.0.dist-info}/licenses/LICENSE +0 -0
  69. {mindsdb-25.7.2.0.dist-info → mindsdb-25.7.4.0.dist-info}/top_level.txt +0 -0
@@ -11,6 +11,7 @@ from mindsdb.integrations.libs.response import (
11
11
  RESPONSE_TYPE,
12
12
  )
13
13
  from mindsdb.integrations.handlers.salesforce_handler.salesforce_tables import create_table_class
14
+ from mindsdb.integrations.handlers.salesforce_handler.constants import get_soql_instructions
14
15
  from mindsdb.utilities import log
15
16
 
16
17
 
@@ -72,7 +73,7 @@ class SalesforceHandler(MetaAPIHandler):
72
73
 
73
74
  resource_tables = self._get_resource_names()
74
75
  for resource_name in resource_tables:
75
- table_class = create_table_class(resource_name)
76
+ table_class = create_table_class(resource_name.lower())
76
77
  self._register_table(resource_name, table_class(self))
77
78
 
78
79
  return self.connection
@@ -156,91 +157,152 @@ class SalesforceHandler(MetaAPIHandler):
156
157
 
157
158
  def _get_resource_names(self) -> List[str]:
158
159
  """
159
- Retrieves the names of the Salesforce resources, with more aggressive filtering to remove tables.
160
+ Retrieves the names of the Salesforce resources with optimized pre-filtering.
160
161
  Returns:
161
162
  List[str]: A list of filtered resource names.
162
163
  """
163
164
  if not self.resource_names:
164
- all_resources = [
165
- resource["name"]
166
- for resource in self.connection.sobjects.describe()["sobjects"]
167
- if resource.get("queryable", False)
168
- ]
165
+ # Check for user-specified table filtering first
166
+ include_tables = self.connection_data.get("include_tables") or self.connection_data.get("tables")
167
+ exclude_tables = self.connection_data.get("exclude_tables", [])
168
+
169
+ if include_tables:
170
+ # OPTIMIZATION: Skip expensive global describe() call
171
+ # Only validate the specified tables
172
+ logger.info(f"Using pre-filtered table list: {include_tables}")
173
+ self.resource_names = self._validate_specified_tables(include_tables, exclude_tables)
174
+ else:
175
+ # Fallback to full discovery with hard-coded filtering
176
+ logger.info("No table filter specified, performing full discovery...")
177
+ self.resource_names = self._discover_all_tables_with_filtering(exclude_tables)
169
178
 
170
- # Define patterns for tables to be filtered out.
171
- # Expanded suffixes and prefixes and exact matches
172
- ignore_suffixes = ("Share", "History", "Feed", "ChangeEvent", "Tag", "Permission", "Setup", "Consent")
173
- ignore_prefixes = (
174
- "Apex",
175
- "CommPlatform",
176
- "Lightning",
177
- "Flow",
178
- "Transaction",
179
- "AI",
180
- "Aura",
181
- "ContentWorkspace",
182
- "Collaboration",
183
- "Datacloud",
184
- )
185
- ignore_exact = {
186
- "EntityDefinition",
187
- "FieldDefinition",
188
- "RecordType",
189
- "CaseStatus",
190
- "UserRole",
191
- "UserLicense",
192
- "UserPermissionAccess",
193
- "UserRecordAccess",
194
- "Folder",
195
- "Group",
196
- "Note",
197
- "ProcessDefinition",
198
- "ProcessInstance",
199
- "ContentFolder",
200
- "ContentDocumentSubscription",
201
- "DashboardComponent",
202
- "Report",
203
- "Dashboard",
204
- "Topic",
205
- "TopicAssignment",
206
- "Period",
207
- "Partner",
208
- "PackageLicense",
209
- "ColorDefinition",
210
- "DataUsePurpose",
211
- "DataUseLegalBasis",
212
- }
213
-
214
- ignore_substrings = (
215
- "CleanInfo",
216
- "Template",
217
- "Rule",
218
- "Definition",
219
- "Status",
220
- "Policy",
221
- "Setting",
222
- "Access",
223
- "Config",
224
- "Subscription",
225
- "DataType",
226
- "MilestoneType",
227
- "Entitlement",
228
- "Auth",
229
- )
230
-
231
- filtered = []
232
- for r in all_resources:
233
- if (
234
- not r.endswith(ignore_suffixes)
235
- and not r.startswith(ignore_prefixes)
236
- and not any(sub in r for sub in ignore_substrings)
237
- and r not in ignore_exact
238
- ):
239
- filtered.append(r)
240
-
241
- self.resource_names = [r for r in filtered]
242
179
  return self.resource_names
243
180
 
181
+ def _validate_specified_tables(self, include_tables: List[str], exclude_tables: List[str]) -> List[str]:
182
+ """
183
+ Validate user-specified tables without expensive global describe() call.
184
+
185
+ Args:
186
+ include_tables: List of table names to include
187
+ exclude_tables: List of table names to exclude
188
+
189
+ Returns:
190
+ List[str]: Validated and filtered table names
191
+ """
192
+ validated_tables = []
193
+
194
+ for table_name in include_tables:
195
+ # Skip if explicitly excluded
196
+ if table_name in exclude_tables:
197
+ logger.info(f"Skipping excluded table: {table_name}")
198
+ continue
199
+
200
+ try:
201
+ # Quick validation: check if table exists and is queryable
202
+ # This is much faster than global describe()
203
+ metadata = getattr(self.connection.sobjects, table_name).describe()
204
+ if metadata.get("queryable", False):
205
+ validated_tables.append(table_name)
206
+ logger.debug(f"Validated table: {table_name}")
207
+ else:
208
+ logger.warning(f"Table {table_name} is not queryable, skipping")
209
+ except Exception as e:
210
+ logger.warning(f"Table {table_name} not found or accessible: {e}")
211
+
212
+ logger.info(f"Validated {len(validated_tables)} tables from include_tables")
213
+ return validated_tables
214
+
215
+ def _discover_all_tables_with_filtering(self, exclude_tables: List[str]) -> List[str]:
216
+ """
217
+ Fallback method: discover all tables with hard-coded filtering.
218
+
219
+ Args:
220
+ exclude_tables: List of table names to exclude
221
+
222
+ Returns:
223
+ List[str]: Filtered table names
224
+ """
225
+ # This is the original expensive approach - only used when no include_tables specified
226
+ all_resources = [
227
+ resource["name"]
228
+ for resource in self.connection.sobjects.describe()["sobjects"]
229
+ if resource.get("queryable", False)
230
+ ]
231
+
232
+ # Apply hard-coded filtering (existing logic)
233
+ ignore_suffixes = ("Share", "History", "Feed", "ChangeEvent", "Tag", "Permission", "Setup", "Consent")
234
+ ignore_prefixes = (
235
+ "Apex",
236
+ "CommPlatform",
237
+ "Lightning",
238
+ "Flow",
239
+ "Transaction",
240
+ "AI",
241
+ "Aura",
242
+ "ContentWorkspace",
243
+ "Collaboration",
244
+ "Datacloud",
245
+ )
246
+ ignore_exact = {
247
+ "EntityDefinition",
248
+ "FieldDefinition",
249
+ "RecordType",
250
+ "CaseStatus",
251
+ "UserRole",
252
+ "UserLicense",
253
+ "UserPermissionAccess",
254
+ "UserRecordAccess",
255
+ "Folder",
256
+ "Group",
257
+ "Note",
258
+ "ProcessDefinition",
259
+ "ProcessInstance",
260
+ "ContentFolder",
261
+ "ContentDocumentSubscription",
262
+ "DashboardComponent",
263
+ "Report",
264
+ "Dashboard",
265
+ "Topic",
266
+ "TopicAssignment",
267
+ "Period",
268
+ "Partner",
269
+ "PackageLicense",
270
+ "ColorDefinition",
271
+ "DataUsePurpose",
272
+ "DataUseLegalBasis",
273
+ }
274
+
275
+ ignore_substrings = (
276
+ "CleanInfo",
277
+ "Template",
278
+ "Rule",
279
+ "Definition",
280
+ "Status",
281
+ "Policy",
282
+ "Setting",
283
+ "Access",
284
+ "Config",
285
+ "Subscription",
286
+ "DataType",
287
+ "MilestoneType",
288
+ "Entitlement",
289
+ "Auth",
290
+ )
291
+
292
+ # Apply hard-coded filtering
293
+ filtered = []
294
+ for r in all_resources:
295
+ if (
296
+ not r.endswith(ignore_suffixes)
297
+ and not r.startswith(ignore_prefixes)
298
+ and not any(sub in r for sub in ignore_substrings)
299
+ and r not in ignore_exact
300
+ and r not in exclude_tables # Apply user exclusions
301
+ ):
302
+ filtered.append(r)
303
+
304
+ return filtered
305
+
244
306
  def meta_get_handler_info(self, **kwargs) -> str:
245
307
  """
246
308
  Retrieves information about the design and implementation of the API handler.
@@ -254,8 +316,7 @@ class SalesforceHandler(MetaAPIHandler):
254
316
  Returns:
255
317
  str: A string containing information about the API handler's design and implementation.
256
318
  """
257
- # TODO: Relationships? Aliases?
258
- return "When filtering on a Date or DateTime field, the value MUST be an unquoted literal in YYYY-MM-DD or YYYY-MM-DDThh:mm:ssZ format. For example, CloseDate >= 2025-05-28 is correct; CloseDate >= '2025-05-28' is incorrect."
319
+ return get_soql_instructions(self.name)
259
320
 
260
321
  def meta_get_tables(self, table_names: Optional[List[str]] = None) -> Response:
261
322
  """
@@ -164,10 +164,18 @@ def create_table_class(resource_name: Text) -> MetaAPIResource:
164
164
  """
165
165
  client = self.handler.connect()
166
166
 
167
- resource_metadata = next(
168
- (resource for resource in main_metadata if resource["name"].lower() == resource_name),
169
- )
170
-
167
+ try:
168
+ resource_metadata = next(
169
+ (resource for resource in main_metadata if resource["name"].lower() == resource_name),
170
+ )
171
+ except Exception as e:
172
+ logger.warning(f"Failed to get resource metadata for {resource_name}: {e}")
173
+ return {
174
+ "table_name": table_name,
175
+ "table_type": "BASE TABLE",
176
+ "table_description": "",
177
+ "row_count": None,
178
+ }
171
179
  # Get row count if Id column is aggregatable.
172
180
  row_count = None
173
181
  # if next(field for field in resource_metadata['fields'] if field['name'] == 'Id').get('aggregatable', False):