MindsDB 25.3.2.0__py3-none-any.whl → 25.3.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 (45) hide show
  1. mindsdb/__about__.py +1 -1
  2. mindsdb/__main__.py +0 -1
  3. mindsdb/api/executor/datahub/datanodes/information_schema_datanode.py +2 -6
  4. mindsdb/api/executor/datahub/datanodes/mindsdb_tables.py +1 -1
  5. mindsdb/api/http/namespaces/agents.py +9 -5
  6. mindsdb/api/http/namespaces/chatbots.py +6 -5
  7. mindsdb/api/http/namespaces/databases.py +5 -6
  8. mindsdb/api/http/namespaces/skills.py +5 -4
  9. mindsdb/api/http/namespaces/views.py +6 -7
  10. mindsdb/integrations/handlers/chromadb_handler/chromadb_handler.py +23 -2
  11. mindsdb/integrations/handlers/dummy_data_handler/dummy_data_handler.py +16 -6
  12. mindsdb/integrations/handlers/file_handler/tests/test_file_handler.py +64 -83
  13. mindsdb/integrations/handlers/github_handler/generate_api.py +228 -0
  14. mindsdb/integrations/handlers/github_handler/github_handler.py +15 -8
  15. mindsdb/integrations/handlers/github_handler/requirements.txt +1 -1
  16. mindsdb/integrations/handlers/huggingface_handler/requirements.txt +5 -4
  17. mindsdb/integrations/handlers/huggingface_handler/requirements_cpu.txt +5 -5
  18. mindsdb/integrations/handlers/ms_one_drive_handler/ms_graph_api_one_drive_client.py +1 -1
  19. mindsdb/integrations/handlers/ms_teams_handler/ms_graph_api_teams_client.py +278 -0
  20. mindsdb/integrations/handlers/ms_teams_handler/ms_teams_handler.py +114 -70
  21. mindsdb/integrations/handlers/ms_teams_handler/ms_teams_tables.py +431 -0
  22. mindsdb/integrations/handlers/pgvector_handler/pgvector_handler.py +18 -4
  23. mindsdb/integrations/handlers/redshift_handler/redshift_handler.py +1 -0
  24. mindsdb/integrations/handlers/salesforce_handler/requirements.txt +1 -1
  25. mindsdb/integrations/handlers/salesforce_handler/salesforce_handler.py +20 -25
  26. mindsdb/integrations/handlers/salesforce_handler/salesforce_tables.py +2 -2
  27. mindsdb/integrations/handlers/timescaledb_handler/timescaledb_handler.py +11 -6
  28. mindsdb/integrations/libs/ml_handler_process/learn_process.py +9 -3
  29. mindsdb/integrations/libs/vectordatabase_handler.py +2 -2
  30. mindsdb/integrations/utilities/files/file_reader.py +3 -3
  31. mindsdb/integrations/utilities/handlers/api_utilities/microsoft/ms_graph_api_utilities.py +36 -2
  32. mindsdb/integrations/utilities/rag/settings.py +1 -0
  33. mindsdb/interfaces/chatbot/chatbot_controller.py +6 -4
  34. mindsdb/interfaces/jobs/jobs_controller.py +1 -4
  35. mindsdb/interfaces/knowledge_base/controller.py +9 -28
  36. mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +1 -1
  37. mindsdb/interfaces/skills/skills_controller.py +8 -7
  38. mindsdb/utilities/render/sqlalchemy_render.py +11 -5
  39. {mindsdb-25.3.2.0.dist-info → mindsdb-25.3.4.0.dist-info}/METADATA +236 -233
  40. {mindsdb-25.3.2.0.dist-info → mindsdb-25.3.4.0.dist-info}/RECORD +43 -42
  41. {mindsdb-25.3.2.0.dist-info → mindsdb-25.3.4.0.dist-info}/WHEEL +1 -1
  42. mindsdb/integrations/handlers/timescaledb_handler/tests/__init__.py +0 -0
  43. mindsdb/integrations/handlers/timescaledb_handler/tests/test_timescaledb_handler.py +0 -47
  44. {mindsdb-25.3.2.0.dist-info → mindsdb-25.3.4.0.dist-info/licenses}/LICENSE +0 -0
  45. {mindsdb-25.3.2.0.dist-info → mindsdb-25.3.4.0.dist-info}/top_level.txt +0 -0
@@ -87,7 +87,7 @@ class MSGraphAPIBaseClient:
87
87
 
88
88
  return response
89
89
 
90
- def fetch_paginated_data(self, endpoint: Text, params: Optional[Dict] = {}) -> Generator:
90
+ def fetch_paginated_data(self, endpoint: Text, params: Optional[Dict] = None) -> Generator:
91
91
  """
92
92
  Fetches data from the Microsoft Graph API by making the specified request and handling pagination.
93
93
 
@@ -98,6 +98,8 @@ class MSGraphAPIBaseClient:
98
98
  Yields:
99
99
  List: The data fetched from the Microsoft Graph API.
100
100
  """
101
+ if params is None:
102
+ params = {}
101
103
  api_url = self._get_api_url(endpoint)
102
104
 
103
105
  # Add the pagination count to the request parameters.
@@ -115,7 +117,7 @@ class MSGraphAPIBaseClient:
115
117
  api_url = response_json.get("@odata.nextLink", "")
116
118
  yield value
117
119
 
118
- def fetch_data(self, endpoint: str, params: Optional[Dict] = {}) -> Union[List, Dict, bytes]:
120
+ def _fetch_data(self, endpoint: str, params: Optional[Dict] = {}) -> Union[List, Dict, bytes]:
119
121
  """
120
122
  Fetches data from the Microsoft Graph API by making the specified request.
121
123
 
@@ -129,4 +131,36 @@ class MSGraphAPIBaseClient:
129
131
  api_url = self._get_api_url(endpoint)
130
132
 
131
133
  response = self._make_request(api_url, params)
134
+ return response
135
+
136
+ def fetch_data_content(self, endpoint: str, params: Optional[Dict] = {}) -> bytes:
137
+ """
138
+ Fetches data content from the Microsoft Graph API by making the specified request.
139
+
140
+ Args:
141
+ endpoint (str): The endpoint of the Microsoft Graph API to fetch data from.
142
+ params (Optional[Dict]): The parameters to include in the request.
143
+
144
+ Returns:
145
+ bytes: The data content fetched from the Microsoft Graph API.
146
+ """
147
+ response = self._fetch_data(endpoint, params)
132
148
  return response.content
149
+
150
+ def fetch_data_json(self, endpoint: str, params: Optional[Dict] = {}) -> Union[List, Dict]:
151
+ """
152
+ Fetches data from the Microsoft Graph API by making the specified request and returns the JSON response.
153
+
154
+ Args:
155
+ endpoint (str): The endpoint of the Microsoft Graph API to fetch data from.
156
+ params (Optional[Dict]): The parameters to include in the request.
157
+
158
+ Returns:
159
+ Union[List, Dict]: The JSON response fetched from the Microsoft Graph API.
160
+ """
161
+ response = self._fetch_data(endpoint, params)
162
+ response_json = response.json()
163
+
164
+ if "value" in response_json:
165
+ return response_json["value"]
166
+ return response_json
@@ -551,6 +551,7 @@ class ColumnSchema(BaseModel):
551
551
  Dict[Union[str, int, float], ValueSchema],
552
552
  ]
553
553
  ] = Field(
554
+ default=None,
554
555
  description="One of the following. A dict or ordered dict of {schema_value: ValueSchema, ...}, where schema value is the name given for this value description in the schema."
555
556
  )
556
557
  example_questions: Optional[List[LLMExample]] = Field(
@@ -1,14 +1,13 @@
1
1
  from typing import Dict, List
2
2
 
3
+ from mindsdb.api.executor.controllers.session_controller import SessionController
3
4
  from mindsdb.interfaces.agents.agents_controller import AgentsController
4
5
  from mindsdb.interfaces.chatbot.chatbot_task import ChatBotTask
5
6
  from mindsdb.interfaces.database.projects import ProjectController
6
7
  from mindsdb.interfaces.storage import db
7
8
  from mindsdb.interfaces.model.functions import get_project_records
8
-
9
+ from mindsdb.utilities.exception import EntityNotExistsError
9
10
  from mindsdb.utilities.context import context as ctx
10
-
11
- from mindsdb.api.executor.controllers.session_controller import SessionController
12
11
  from mindsdb.utilities.config import config
13
12
 
14
13
 
@@ -126,7 +125,7 @@ class ChatBotController:
126
125
  Gets all chatbots in a project.
127
126
 
128
127
  Parameters:
129
- project_name (str): The name of the containing project
128
+ project_name (str): The name of the containing project. If None, then return from all projects
130
129
 
131
130
  Returns:
132
131
  all_bots (List[db.ChatBots]): List of database chatbot object
@@ -138,6 +137,9 @@ class ChatBotController:
138
137
  continue
139
138
  project_names[project.id] = project.name
140
139
 
140
+ if project_name is not None and project_name not in project_names.values():
141
+ raise EntityNotExistsError(f'Project {project_name} not found')
142
+
141
143
  query = db.session.query(
142
144
  db.ChatBots, db.Tasks
143
145
  ).join(
@@ -340,10 +340,7 @@ class JobsController:
340
340
  data, columns = logs_db_controller.query(query)
341
341
 
342
342
  names = [i['name'] for i in columns]
343
- records = []
344
- for row in data:
345
- records.append(dict(zip(names, row)))
346
- return records
343
+ return data[names].to_dict(orient='records')
347
344
 
348
345
 
349
346
  class JobsExecutor:
@@ -26,9 +26,7 @@ from mindsdb.integrations.libs.vectordatabase_handler import (
26
26
  )
27
27
  from mindsdb.integrations.utilities.rag.rag_pipeline_builder import RAG
28
28
  from mindsdb.integrations.utilities.rag.config_loader import load_rag_config
29
- from mindsdb.integrations.utilities.sql_utils import (
30
- extract_comparison_conditions, filter_dataframe, FilterCondition, FilterOperator
31
- )
29
+
32
30
  from mindsdb.interfaces.agents.constants import DEFAULT_EMBEDDINGS_MODEL_CLASS
33
31
  from mindsdb.interfaces.agents.langchain_agent import create_chat_model, get_llm_provider
34
32
  from mindsdb.interfaces.database.projects import ProjectController
@@ -105,19 +103,9 @@ class KnowledgeBaseTable:
105
103
  db_handler = self.get_vector_db()
106
104
  logger.debug(f"Using vector db handler: {type(db_handler)}")
107
105
 
108
- vector_filters, outer_filters = [], []
109
- # update vector handlers, mark conditions as applied inside
110
- for op, arg1, arg2 in extract_comparison_conditions(query.where):
111
- condition = FilterCondition(arg1, FilterOperator(op.upper()), arg2)
112
- if arg1 in (TableField.ID.value, TableField.CONTENT.value, TableField.EMBEDDINGS.value):
113
- vector_filters.append(condition)
114
- else:
115
- outer_filters.append([op, arg1, arg2])
116
-
117
- df = db_handler.dispatch_select(query, conditions=vector_filters)
106
+ df = db_handler.dispatch_select(query)
118
107
 
119
108
  if df is not None:
120
- df = filter_dataframe(df, outer_filters)
121
109
 
122
110
  logger.debug(f"Query returned {len(df)} rows")
123
111
  logger.debug(f"Columns in response: {df.columns.tolist()}")
@@ -229,7 +217,7 @@ class KnowledgeBaseTable:
229
217
 
230
218
  # send to vectordb
231
219
  db_handler = self.get_vector_db()
232
- db_handler.query(query)
220
+ db_handler.dispatch_delete(query)
233
221
 
234
222
  def hybrid_search(
235
223
  self,
@@ -293,7 +281,6 @@ class KnowledgeBaseTable:
293
281
  **base_metadata,
294
282
  'original_row_id': str(row_id),
295
283
  'content_column': col,
296
- 'content_type': col.split('_')[-1] if '_' in col else 'text'
297
284
  }
298
285
 
299
286
  raw_documents.append(Document(
@@ -364,7 +351,7 @@ class KnowledgeBaseTable:
364
351
  logger.debug(f"Added IDs: {df_out[TableField.ID.value].tolist()}")
365
352
 
366
353
  # -- prepare content and metadata --
367
- content_columns = params.get('content_columns')
354
+ content_columns = params.get('content_columns', [TableField.CONTENT.value])
368
355
  metadata_columns = params.get('metadata_columns')
369
356
 
370
357
  logger.debug(f"Processing with: content_columns={content_columns}, metadata_columns={metadata_columns}")
@@ -399,17 +386,6 @@ class KnowledgeBaseTable:
399
386
  # all the rest columns
400
387
  metadata_columns = list(set(columns).difference(content_columns))
401
388
 
402
- elif metadata_columns is not None:
403
- metadata_columns = list(set(metadata_columns).intersection(columns))
404
- # use all unused columns is content
405
- content_columns = list(set(columns).difference(metadata_columns))
406
- elif TableField.METADATA.value in columns:
407
- metadata_columns = [TableField.METADATA.value]
408
- content_columns = list(set(columns).difference(metadata_columns))
409
- else:
410
- # all columns go to content
411
- content_columns = columns
412
-
413
389
  # Add content columns directly (don't combine them)
414
390
  for col in content_columns:
415
391
  df_out[col] = df[col]
@@ -429,6 +405,9 @@ class KnowledgeBaseTable:
429
405
  value = float(value)
430
406
  elif pd.api.types.is_bool_dtype(value):
431
407
  value = bool(value)
408
+ elif isinstance(value, dict):
409
+ metadata.update(value)
410
+ continue
432
411
  else:
433
412
  value = str(value)
434
413
  metadata[col] = value
@@ -852,6 +831,8 @@ class KnowledgeBaseController:
852
831
  # drop objects if they were created automatically
853
832
  if 'default_vector_storage' in kb.params:
854
833
  try:
834
+ handler = self.session.datahub.get(kb.params['default_vector_storage']).integration_handler
835
+ handler.drop_table(kb.vector_database_table)
855
836
  self.session.integration_controller.delete(kb.params['default_vector_storage'])
856
837
  except EntityNotExistsError:
857
838
  pass
@@ -98,7 +98,7 @@ class DocumentPreprocessor:
98
98
  provided_id: str = None,
99
99
  ) -> str:
100
100
  """Generate deterministic ID for a chunk"""
101
- base_id = self._generate_deterministic_id(content, content_column, provided_id)
101
+ base_id = provided_id
102
102
  chunk_id = (
103
103
  f"{base_id}_chunk_{chunk_index}" if chunk_index is not None else base_id
104
104
  )
@@ -42,12 +42,12 @@ class SkillsController:
42
42
  db.Skills.deleted_at == null()
43
43
  ).first()
44
44
 
45
- def get_skills(self, project_name: str) -> List[dict]:
45
+ def get_skills(self, project_name: Optional[str]) -> List[dict]:
46
46
  '''
47
47
  Gets all skills in a project.
48
48
 
49
49
  Parameters:
50
- project_name (str): The name of the containing project
50
+ project_name (Optional[str]): The name of the containing project
51
51
 
52
52
  Returns:
53
53
  all_skills (List[db.Skills]): List of database skill object
@@ -56,11 +56,12 @@ class SkillsController:
56
56
  ValueError: If `project_name` does not exist
57
57
  '''
58
58
 
59
- project_controller = ProjectController()
60
- projects = project_controller.get_list()
61
- if project_name is not None:
62
- projects = list([p for p in projects if p.name == project_name])
63
- project_ids = list([p.id for p in projects])
59
+ if project_name is None:
60
+ projects = self.project_controller.get_list()
61
+ project_ids = list([p.id for p in projects])
62
+ else:
63
+ project = self.project_controller.get(name=project_name)
64
+ project_ids = [project.id]
64
65
 
65
66
  query = (
66
67
  db.session.query(db.Skills)
@@ -483,7 +483,7 @@ class SqlalchemyRender:
483
483
 
484
484
  return schema, table_name
485
485
 
486
- def to_table(self, node):
486
+ def to_table(self, node, is_lateral=False):
487
487
  if isinstance(node, ast.Identifier):
488
488
  schema, table_name = self.get_table_name(node)
489
489
 
@@ -497,7 +497,10 @@ class SqlalchemyRender:
497
497
  alias = None
498
498
  if node.alias:
499
499
  alias = self.get_alias(node.alias)
500
- table = sub_stmt.subquery(alias)
500
+ if is_lateral:
501
+ table = sub_stmt.lateral(alias)
502
+ else:
503
+ table = sub_stmt.subquery(alias)
501
504
 
502
505
  else:
503
506
  # TODO tests are failing
@@ -526,8 +529,11 @@ class SqlalchemyRender:
526
529
 
527
530
  query = query.add_cte(stmt.cte(self.get_alias(alias), nesting=True))
528
531
 
529
- if node.distinct:
532
+ if node.distinct is True:
530
533
  query = query.distinct()
534
+ elif isinstance(node.distinct, list):
535
+ columns = [self.to_expression(c) for c in node.distinct]
536
+ query = query.distinct(*columns)
531
537
 
532
538
  if node.from_table is not None:
533
539
  from_table = node.from_table
@@ -541,7 +547,8 @@ class SqlalchemyRender:
541
547
  # other tables
542
548
  has_explicit_join = False
543
549
  for item in join_list[1:]:
544
- table = self.to_table(item['table'])
550
+ join_type = item['join_type']
551
+ table = self.to_table(item['table'], is_lateral=('LATERAL' in join_type))
545
552
  if item['is_implicit']:
546
553
  # add to from clause
547
554
  if has_explicit_join:
@@ -558,7 +565,6 @@ class SqlalchemyRender:
558
565
  else:
559
566
  condition = self.to_expression(item['condition'])
560
567
 
561
- join_type = item['join_type']
562
568
  if 'ASOF' in join_type:
563
569
  raise NotImplementedError(f'Unsupported join type: {join_type}')
564
570
  method = 'join'