MindsDB 25.9.2.0a1__py3-none-any.whl → 25.10.0rc1__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 (163) hide show
  1. mindsdb/__about__.py +1 -1
  2. mindsdb/__main__.py +40 -29
  3. mindsdb/api/a2a/__init__.py +1 -1
  4. mindsdb/api/a2a/agent.py +16 -10
  5. mindsdb/api/a2a/common/server/server.py +7 -3
  6. mindsdb/api/a2a/common/server/task_manager.py +12 -5
  7. mindsdb/api/a2a/common/types.py +66 -0
  8. mindsdb/api/a2a/task_manager.py +65 -17
  9. mindsdb/api/common/middleware.py +10 -12
  10. mindsdb/api/executor/command_executor.py +51 -40
  11. mindsdb/api/executor/datahub/datanodes/datanode.py +2 -2
  12. mindsdb/api/executor/datahub/datanodes/information_schema_datanode.py +7 -13
  13. mindsdb/api/executor/datahub/datanodes/integration_datanode.py +101 -49
  14. mindsdb/api/executor/datahub/datanodes/project_datanode.py +8 -4
  15. mindsdb/api/executor/datahub/datanodes/system_tables.py +3 -2
  16. mindsdb/api/executor/exceptions.py +29 -10
  17. mindsdb/api/executor/planner/plan_join.py +17 -3
  18. mindsdb/api/executor/planner/query_prepare.py +2 -20
  19. mindsdb/api/executor/sql_query/sql_query.py +74 -74
  20. mindsdb/api/executor/sql_query/steps/fetch_dataframe.py +1 -2
  21. mindsdb/api/executor/sql_query/steps/subselect_step.py +0 -1
  22. mindsdb/api/executor/utilities/functions.py +6 -6
  23. mindsdb/api/executor/utilities/sql.py +37 -20
  24. mindsdb/api/http/gui.py +5 -11
  25. mindsdb/api/http/initialize.py +75 -61
  26. mindsdb/api/http/namespaces/agents.py +10 -15
  27. mindsdb/api/http/namespaces/analysis.py +13 -20
  28. mindsdb/api/http/namespaces/auth.py +1 -1
  29. mindsdb/api/http/namespaces/chatbots.py +0 -5
  30. mindsdb/api/http/namespaces/config.py +15 -11
  31. mindsdb/api/http/namespaces/databases.py +140 -201
  32. mindsdb/api/http/namespaces/file.py +17 -4
  33. mindsdb/api/http/namespaces/handlers.py +17 -7
  34. mindsdb/api/http/namespaces/knowledge_bases.py +28 -7
  35. mindsdb/api/http/namespaces/models.py +94 -126
  36. mindsdb/api/http/namespaces/projects.py +13 -22
  37. mindsdb/api/http/namespaces/sql.py +33 -25
  38. mindsdb/api/http/namespaces/tab.py +27 -37
  39. mindsdb/api/http/namespaces/views.py +1 -1
  40. mindsdb/api/http/start.py +16 -10
  41. mindsdb/api/mcp/__init__.py +2 -1
  42. mindsdb/api/mysql/mysql_proxy/executor/mysql_executor.py +15 -20
  43. mindsdb/api/mysql/mysql_proxy/mysql_proxy.py +26 -50
  44. mindsdb/api/mysql/mysql_proxy/utilities/__init__.py +0 -1
  45. mindsdb/api/mysql/mysql_proxy/utilities/dump.py +8 -2
  46. mindsdb/integrations/handlers/byom_handler/byom_handler.py +165 -190
  47. mindsdb/integrations/handlers/databricks_handler/databricks_handler.py +98 -46
  48. mindsdb/integrations/handlers/druid_handler/druid_handler.py +32 -40
  49. mindsdb/integrations/handlers/file_handler/file_handler.py +7 -0
  50. mindsdb/integrations/handlers/gitlab_handler/gitlab_handler.py +5 -2
  51. mindsdb/integrations/handlers/lightwood_handler/functions.py +45 -79
  52. mindsdb/integrations/handlers/mssql_handler/mssql_handler.py +438 -100
  53. mindsdb/integrations/handlers/mssql_handler/requirements_odbc.txt +3 -0
  54. mindsdb/integrations/handlers/mysql_handler/mysql_handler.py +235 -3
  55. mindsdb/integrations/handlers/oracle_handler/__init__.py +2 -0
  56. mindsdb/integrations/handlers/oracle_handler/connection_args.py +7 -1
  57. mindsdb/integrations/handlers/oracle_handler/oracle_handler.py +321 -16
  58. mindsdb/integrations/handlers/oracle_handler/requirements.txt +1 -1
  59. mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +14 -2
  60. mindsdb/integrations/handlers/shopify_handler/shopify_handler.py +25 -12
  61. mindsdb/integrations/handlers/snowflake_handler/snowflake_handler.py +2 -1
  62. mindsdb/integrations/handlers/statsforecast_handler/requirements.txt +1 -0
  63. mindsdb/integrations/handlers/statsforecast_handler/requirements_extra.txt +1 -0
  64. mindsdb/integrations/handlers/web_handler/urlcrawl_helpers.py +4 -4
  65. mindsdb/integrations/handlers/zendesk_handler/zendesk_tables.py +144 -111
  66. mindsdb/integrations/libs/api_handler.py +10 -10
  67. mindsdb/integrations/libs/base.py +4 -4
  68. mindsdb/integrations/libs/llm/utils.py +2 -2
  69. mindsdb/integrations/libs/ml_handler_process/create_engine_process.py +4 -7
  70. mindsdb/integrations/libs/ml_handler_process/func_call_process.py +2 -7
  71. mindsdb/integrations/libs/ml_handler_process/learn_process.py +37 -47
  72. mindsdb/integrations/libs/ml_handler_process/update_engine_process.py +4 -7
  73. mindsdb/integrations/libs/ml_handler_process/update_process.py +2 -7
  74. mindsdb/integrations/libs/process_cache.py +132 -140
  75. mindsdb/integrations/libs/response.py +18 -12
  76. mindsdb/integrations/libs/vectordatabase_handler.py +26 -0
  77. mindsdb/integrations/utilities/files/file_reader.py +6 -7
  78. mindsdb/integrations/utilities/handlers/auth_utilities/snowflake/__init__.py +1 -0
  79. mindsdb/integrations/utilities/handlers/auth_utilities/snowflake/snowflake_jwt_gen.py +151 -0
  80. mindsdb/integrations/utilities/rag/config_loader.py +37 -26
  81. mindsdb/integrations/utilities/rag/rerankers/base_reranker.py +83 -30
  82. mindsdb/integrations/utilities/rag/rerankers/reranker_compressor.py +4 -4
  83. mindsdb/integrations/utilities/rag/retrievers/sql_retriever.py +55 -133
  84. mindsdb/integrations/utilities/rag/settings.py +58 -133
  85. mindsdb/integrations/utilities/rag/splitters/file_splitter.py +5 -15
  86. mindsdb/interfaces/agents/agents_controller.py +2 -3
  87. mindsdb/interfaces/agents/constants.py +0 -2
  88. mindsdb/interfaces/agents/litellm_server.py +34 -58
  89. mindsdb/interfaces/agents/mcp_client_agent.py +10 -10
  90. mindsdb/interfaces/agents/mindsdb_database_agent.py +5 -5
  91. mindsdb/interfaces/agents/run_mcp_agent.py +12 -21
  92. mindsdb/interfaces/chatbot/chatbot_task.py +20 -23
  93. mindsdb/interfaces/chatbot/polling.py +30 -18
  94. mindsdb/interfaces/data_catalog/data_catalog_loader.py +16 -17
  95. mindsdb/interfaces/data_catalog/data_catalog_reader.py +15 -4
  96. mindsdb/interfaces/database/data_handlers_cache.py +190 -0
  97. mindsdb/interfaces/database/database.py +3 -3
  98. mindsdb/interfaces/database/integrations.py +7 -110
  99. mindsdb/interfaces/database/projects.py +2 -6
  100. mindsdb/interfaces/database/views.py +1 -4
  101. mindsdb/interfaces/file/file_controller.py +6 -6
  102. mindsdb/interfaces/functions/controller.py +1 -1
  103. mindsdb/interfaces/functions/to_markdown.py +2 -2
  104. mindsdb/interfaces/jobs/jobs_controller.py +5 -9
  105. mindsdb/interfaces/jobs/scheduler.py +3 -9
  106. mindsdb/interfaces/knowledge_base/controller.py +244 -128
  107. mindsdb/interfaces/knowledge_base/evaluate.py +36 -41
  108. mindsdb/interfaces/knowledge_base/executor.py +11 -0
  109. mindsdb/interfaces/knowledge_base/llm_client.py +51 -17
  110. mindsdb/interfaces/knowledge_base/preprocessing/json_chunker.py +40 -61
  111. mindsdb/interfaces/model/model_controller.py +172 -168
  112. mindsdb/interfaces/query_context/context_controller.py +14 -2
  113. mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +10 -14
  114. mindsdb/interfaces/skills/retrieval_tool.py +43 -50
  115. mindsdb/interfaces/skills/skill_tool.py +2 -2
  116. mindsdb/interfaces/skills/skills_controller.py +1 -4
  117. mindsdb/interfaces/skills/sql_agent.py +25 -19
  118. mindsdb/interfaces/storage/db.py +16 -6
  119. mindsdb/interfaces/storage/fs.py +114 -169
  120. mindsdb/interfaces/storage/json.py +19 -18
  121. mindsdb/interfaces/tabs/tabs_controller.py +49 -72
  122. mindsdb/interfaces/tasks/task_monitor.py +3 -9
  123. mindsdb/interfaces/tasks/task_thread.py +7 -9
  124. mindsdb/interfaces/triggers/trigger_task.py +7 -13
  125. mindsdb/interfaces/triggers/triggers_controller.py +47 -52
  126. mindsdb/migrations/migrate.py +16 -16
  127. mindsdb/utilities/api_status.py +58 -0
  128. mindsdb/utilities/config.py +68 -2
  129. mindsdb/utilities/exception.py +40 -1
  130. mindsdb/utilities/fs.py +0 -1
  131. mindsdb/utilities/hooks/profiling.py +17 -14
  132. mindsdb/utilities/json_encoder.py +24 -10
  133. mindsdb/utilities/langfuse.py +40 -45
  134. mindsdb/utilities/log.py +272 -0
  135. mindsdb/utilities/ml_task_queue/consumer.py +52 -58
  136. mindsdb/utilities/ml_task_queue/producer.py +26 -30
  137. mindsdb/utilities/render/sqlalchemy_render.py +22 -20
  138. mindsdb/utilities/starters.py +0 -10
  139. mindsdb/utilities/utils.py +2 -2
  140. {mindsdb-25.9.2.0a1.dist-info → mindsdb-25.10.0rc1.dist-info}/METADATA +293 -276
  141. {mindsdb-25.9.2.0a1.dist-info → mindsdb-25.10.0rc1.dist-info}/RECORD +144 -158
  142. mindsdb/api/mysql/mysql_proxy/utilities/exceptions.py +0 -14
  143. mindsdb/api/postgres/__init__.py +0 -0
  144. mindsdb/api/postgres/postgres_proxy/__init__.py +0 -0
  145. mindsdb/api/postgres/postgres_proxy/executor/__init__.py +0 -1
  146. mindsdb/api/postgres/postgres_proxy/executor/executor.py +0 -189
  147. mindsdb/api/postgres/postgres_proxy/postgres_packets/__init__.py +0 -0
  148. mindsdb/api/postgres/postgres_proxy/postgres_packets/errors.py +0 -322
  149. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_fields.py +0 -34
  150. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_message.py +0 -31
  151. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_message_formats.py +0 -1265
  152. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_message_identifiers.py +0 -31
  153. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_packets.py +0 -253
  154. mindsdb/api/postgres/postgres_proxy/postgres_proxy.py +0 -477
  155. mindsdb/api/postgres/postgres_proxy/utilities/__init__.py +0 -10
  156. mindsdb/api/postgres/start.py +0 -11
  157. mindsdb/integrations/handlers/mssql_handler/tests/__init__.py +0 -0
  158. mindsdb/integrations/handlers/mssql_handler/tests/test_mssql_handler.py +0 -169
  159. mindsdb/integrations/handlers/oracle_handler/tests/__init__.py +0 -0
  160. mindsdb/integrations/handlers/oracle_handler/tests/test_oracle_handler.py +0 -32
  161. {mindsdb-25.9.2.0a1.dist-info → mindsdb-25.10.0rc1.dist-info}/WHEEL +0 -0
  162. {mindsdb-25.9.2.0a1.dist-info → mindsdb-25.10.0rc1.dist-info}/licenses/LICENSE +0 -0
  163. {mindsdb-25.9.2.0a1.dist-info → mindsdb-25.10.0rc1.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,6 @@
1
1
  import os
2
2
  import mimetypes
3
3
  import threading
4
- import traceback
5
4
  import webbrowser
6
5
 
7
6
  from pathlib import Path
@@ -9,8 +8,7 @@ from http import HTTPStatus
9
8
 
10
9
 
11
10
  import requests
12
- from flask import Flask, url_for, make_response, request, send_from_directory
13
- from flask.json import dumps
11
+ from flask import Flask, url_for, request, send_from_directory
14
12
  from flask_compress import Compress
15
13
  from flask_restx import Api
16
14
  from werkzeug.exceptions import HTTPException
@@ -48,7 +46,7 @@ from mindsdb.metrics.server import init_metrics
48
46
  from mindsdb.utilities import log
49
47
  from mindsdb.utilities.config import config
50
48
  from mindsdb.utilities.context import context as ctx
51
- from mindsdb.utilities.json_encoder import CustomJSONProvider
49
+ from mindsdb.utilities.json_encoder import ORJSONProvider
52
50
  from mindsdb.utilities.ps import is_pid_listen_port, wait_func_is_true
53
51
  from mindsdb.utilities.sentry import sentry_sdk # noqa: F401
54
52
  from mindsdb.utilities.otel import trace # noqa: F401
@@ -89,14 +87,8 @@ class Swagger_Api(Api):
89
87
  return url_for(self.endpoint("specs"), _external=False)
90
88
 
91
89
 
92
- def custom_output_json(data, code, headers=None):
93
- resp = make_response(dumps(data, cls=CustomJSONProvider), code)
94
- resp.headers.extend(headers or {})
95
- return resp
96
-
97
-
98
90
  def get_last_compatible_gui_version() -> Version | bool:
99
- logger.debug("Getting last compatible frontend..")
91
+ logger.debug("Getting last compatible frontend...")
100
92
  try:
101
93
  res = requests.get(
102
94
  "https://mindsdb-web-builds.s3.amazonaws.com/compatible-config.json",
@@ -154,8 +146,8 @@ def get_last_compatible_gui_version() -> Version | bool:
154
146
  else:
155
147
  all_lower_versions = [parse_version(x) for x in lower_versions.keys()]
156
148
  gui_version_lv = gui_versions[all_lower_versions[-1].base_version]
157
- except Exception as e:
158
- logger.error(f"Error in compatible-config.json structure: {e}")
149
+ except Exception:
150
+ logger.exception("Error in compatible-config.json structure")
159
151
  return False
160
152
 
161
153
  logger.debug(f"Last compatible frontend version: {gui_version_lv}.")
@@ -179,7 +171,6 @@ def get_current_gui_version() -> Version:
179
171
 
180
172
 
181
173
  def initialize_static():
182
- logger.debug("Initializing static..")
183
174
  last_gui_version_lv = get_last_compatible_gui_version()
184
175
  current_gui_version_lv = get_current_gui_version()
185
176
  required_gui_version = config["gui"].get("version")
@@ -207,22 +198,28 @@ def initialize_static():
207
198
  return success
208
199
 
209
200
 
210
- def initialize_app():
201
+ def initialize_app(is_restart: bool = False):
211
202
  static_root = config["paths"]["static"]
212
203
  logger.debug(f"Static route: {static_root}")
213
- gui_exists = Path(static_root).joinpath("index.html").is_file()
214
- logger.debug(f"Does GUI already exist.. {'YES' if gui_exists else 'NO'}")
215
204
  init_static_thread = None
205
+ if not is_restart:
206
+ gui_exists = Path(static_root).joinpath("index.html").is_file()
207
+ logger.debug(f"Does GUI already exist.. {'YES' if gui_exists else 'NO'}")
208
+
209
+ if config["gui"]["autoupdate"] is True or (config["gui"]["open_on_start"] is True and gui_exists is False):
210
+ logger.debug("Initializing static...")
211
+ init_static_thread = threading.Thread(target=initialize_static, name="initialize_static")
212
+ init_static_thread.start()
213
+ else:
214
+ logger.debug(f"Skip initializing static: config['gui']={config['gui']}, gui_exists={gui_exists}")
216
215
 
217
- if config["gui"]["autoupdate"] is True or (config["gui"]["open_on_start"] is True and gui_exists is False):
218
- init_static_thread = threading.Thread(target=initialize_static, name="initialize_static")
219
- init_static_thread.start()
216
+ app, api = initialize_flask()
220
217
 
221
- # Wait for static initialization.
222
- if config["gui"]["open_on_start"] is True and init_static_thread is not None:
223
- init_static_thread.join()
218
+ if not is_restart and config["gui"]["open_on_start"]:
219
+ if init_static_thread is not None:
220
+ init_static_thread.join()
221
+ open_gui(init_static_thread)
224
222
 
225
- app, api = initialize_flask(config, init_static_thread)
226
223
  Compress(app)
227
224
 
228
225
  initialize_interfaces(app)
@@ -241,22 +238,30 @@ def initialize_app():
241
238
  "The endpoint you are trying to access does not exist on the server.",
242
239
  )
243
240
 
244
- # Normalize the path.
245
- full_path = os.path.normpath(os.path.join(static_root, path))
241
+ try:
242
+ # Ensure the requested path is within the static directory
243
+ # https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.is_relative_to
244
+ requested_path = (static_root / path).resolve()
245
+
246
+ if not requested_path.is_relative_to(static_root.resolve()):
247
+ return http_error(
248
+ HTTPStatus.FORBIDDEN,
249
+ "Forbidden",
250
+ "You are not allowed to access the requested resource.",
251
+ )
252
+
253
+ if requested_path.is_file():
254
+ return send_from_directory(static_root, path)
255
+ else:
256
+ return send_from_directory(static_root, "index.html")
246
257
 
247
- # Check for directory traversal attacks.
248
- if not full_path.startswith(str(static_root)):
258
+ except (ValueError, OSError):
249
259
  return http_error(
250
- HTTPStatus.FORBIDDEN,
251
- "Forbidden",
252
- "You are not allowed to access the requested resource.",
260
+ HTTPStatus.BAD_REQUEST,
261
+ "Bad Request",
262
+ "Invalid path requested.",
253
263
  )
254
264
 
255
- if os.path.isfile(full_path):
256
- return send_from_directory(static_root, path)
257
- else:
258
- return send_from_directory(static_root, "index.html")
259
-
260
265
  protected_namespaces = [
261
266
  tab_ns,
262
267
  utils_ns,
@@ -310,7 +315,6 @@ def initialize_app():
310
315
 
311
316
  @app.before_request
312
317
  def before_request():
313
- logger.debug(f"HTTP {request.method}: {request.path}")
314
318
  ctx.set_default()
315
319
 
316
320
  h = request.headers.get("Authorization")
@@ -371,8 +375,8 @@ def initialize_app():
371
375
  return app
372
376
 
373
377
 
374
- def initialize_flask(config, init_static_thread):
375
- logger.debug("Initializing flask..")
378
+ def initialize_flask():
379
+ logger.debug("Initializing flask...")
376
380
  # region required for windows https://github.com/mindsdb/mindsdb/issues/2526
377
381
  mimetypes.add_type("text/css", ".css")
378
382
  mimetypes.add_type("text/javascript", ".js")
@@ -393,7 +397,7 @@ def initialize_flask(config, init_static_thread):
393
397
 
394
398
  app.config["SEND_FILE_MAX_AGE_DEFAULT"] = 60
395
399
  app.config["SWAGGER_HOST"] = "http://localhost:8000/mindsdb"
396
- app.json = CustomJSONProvider()
400
+ app.json = ORJSONProvider(app)
397
401
 
398
402
  authorizations = {"apikey": {"type": "apiKey", "in": "header", "name": "Authorization"}}
399
403
 
@@ -407,30 +411,41 @@ def initialize_flask(config, init_static_thread):
407
411
  doc="/doc/",
408
412
  )
409
413
 
410
- api.representations["application/json"] = custom_output_json
414
+ def __output_json_orjson(data, code, headers=None):
415
+ from flask import current_app, make_response
411
416
 
412
- port = config["api"]["http"]["port"]
413
- host = config["api"]["http"]["host"]
417
+ dumped = current_app.json.dumps(data)
418
+ resp = make_response(dumped, code)
419
+ if headers:
420
+ resp.headers.extend(headers)
421
+ resp.mimetype = "application/json"
422
+ return resp
414
423
 
415
- if config["gui"]["open_on_start"]:
416
- if host in ("", "0.0.0.0"):
417
- url = f"http://127.0.0.1:{port}/"
418
- else:
419
- url = f"http://{host}:{port}/"
420
- logger.info(f" - GUI available at {url}")
421
-
422
- pid = os.getpid()
423
- thread = threading.Thread(
424
- target=_open_webbrowser,
425
- args=(url, pid, port, init_static_thread, config["paths"]["static"]),
426
- daemon=True,
427
- name="open_webbrowser",
428
- )
429
- thread.start()
424
+ api.representations["application/json"] = __output_json_orjson
430
425
 
431
426
  return app, api
432
427
 
433
428
 
429
+ def open_gui(init_static_thread):
430
+ port = config["api"]["http"]["port"]
431
+ host = config["api"]["http"]["host"]
432
+
433
+ if host in ("", "0.0.0.0"):
434
+ url = f"http://127.0.0.1:{port}/"
435
+ else:
436
+ url = f"http://{host}:{port}/"
437
+ logger.info(f" - GUI available at {url}")
438
+
439
+ pid = os.getpid()
440
+ thread = threading.Thread(
441
+ target=_open_webbrowser,
442
+ args=(url, pid, port, init_static_thread, config["paths"]["static"]),
443
+ daemon=True,
444
+ name="open_webbrowser",
445
+ )
446
+ thread.start()
447
+
448
+
434
449
  def initialize_interfaces(app):
435
450
  app.integration_controller = integration_controller
436
451
  app.database_controller = DatabaseController()
@@ -449,7 +464,6 @@ def _open_webbrowser(url: str, pid: int, port: int, init_static_thread, static_f
449
464
  is_http_active = wait_func_is_true(func=is_pid_listen_port, timeout=15, pid=pid, port=port)
450
465
  if is_http_active:
451
466
  webbrowser.open(url)
452
- except Exception as e:
453
- logger.error(f"Failed to open {url} in webbrowser with exception {e}")
454
- logger.error(traceback.format_exc())
467
+ except Exception:
468
+ logger.exception(f"Failed to open {url} in webbrowser with exception:")
455
469
  db.session.close()
@@ -1,6 +1,5 @@
1
1
  import os
2
2
  import json
3
- import traceback
4
3
  from http import HTTPStatus
5
4
  from typing import Dict, Iterable, List
6
5
 
@@ -27,9 +26,6 @@ def create_agent(project_name, name, agent):
27
26
  if name is None:
28
27
  return http_error(HTTPStatus.BAD_REQUEST, "Missing field", 'Missing "name" field for agent')
29
28
 
30
- if not name.islower():
31
- return http_error(HTTPStatus.BAD_REQUEST, "Wrong name", f"The name must be in lower case: {name}")
32
-
33
29
  model_name = agent.get("model_name")
34
30
  provider = agent.get("provider")
35
31
  skills = agent.get("skills", [])
@@ -307,10 +303,10 @@ def _completion_event_generator(agent_name: str, messages: List[Dict], project_n
307
303
 
308
304
  logger.info("Completion stream finished")
309
305
 
310
- except Exception as e:
311
- logger.error(f"Error in completion event generator: {e}")
312
- logger.error(traceback.format_exc())
313
- yield json_serialize({"error": "error in completion event generator"})
306
+ except Exception:
307
+ error_message = "Error in completion event generator"
308
+ logger.exception(error_message)
309
+ yield json_serialize({"error": error_message})
314
310
 
315
311
  finally:
316
312
  yield json_serialize({"type": "end"})
@@ -337,12 +333,12 @@ class AgentCompletionsStream(Resource):
337
333
  try:
338
334
  existing_agent = session.agents_controller.get_agent(agent_name, project_name=project_name)
339
335
  if existing_agent is None:
340
- logger.error(f"Agent {agent_name} not found in project {project_name}")
336
+ logger.warning(f"Agent {agent_name} not found in project {project_name}")
341
337
  return http_error(
342
338
  HTTPStatus.NOT_FOUND, "Agent not found", f"Agent with name {agent_name} does not exist"
343
339
  )
344
340
  except ValueError as e:
345
- logger.error(f"Project {project_name} not found: {str(e)}")
341
+ logger.warning(f"Project {project_name} not found: {e}")
346
342
  return http_error(
347
343
  HTTPStatus.NOT_FOUND, "Project not found", f"Project with name {project_name} does not exist"
348
344
  )
@@ -352,10 +348,9 @@ class AgentCompletionsStream(Resource):
352
348
  logger.info(f"Starting streaming response for agent {agent_name}")
353
349
  return Response(gen, mimetype="text/event-stream")
354
350
  except Exception as e:
355
- logger.error(f"Error during streaming for agent {agent_name}: {str(e)}")
356
- logger.error(traceback.format_exc())
351
+ logger.exception(f"Error during streaming for agent {agent_name}:")
357
352
  return http_error(
358
- HTTPStatus.INTERNAL_SERVER_ERROR, "Streaming error", f"An error occurred during streaming: {str(e)}"
353
+ HTTPStatus.INTERNAL_SERVER_ERROR, "Streaming error", f"An error occurred during streaming: {e}"
359
354
  )
360
355
 
361
356
 
@@ -416,8 +411,8 @@ class AgentCompletions(Resource):
416
411
  last_context = completion.iloc[-1]["context"]
417
412
  if last_context:
418
413
  context = json.loads(last_context)
419
- except (json.JSONDecodeError, IndexError) as e:
420
- logger.error(f"Error decoding context: {e}")
414
+ except (json.JSONDecodeError, IndexError):
415
+ logger.warning("Error decoding context:", exc_info=True)
421
416
  pass # Keeping context as an empty list in case of error
422
417
 
423
418
  response["message"]["context"] = context
@@ -36,6 +36,7 @@ def analyze_df(df: DataFrame) -> dict:
36
36
  df.columns = cols
37
37
 
38
38
  from dataprep_ml.insights import analyze_dataset
39
+
39
40
  analysis = analyze_dataset(df)
40
41
  return analysis.to_dict()
41
42
 
@@ -43,7 +44,7 @@ def analyze_df(df: DataFrame) -> dict:
43
44
  @ns_conf.route("/query")
44
45
  class QueryAnalysis(Resource):
45
46
  @ns_conf.doc("post_query_to_analyze")
46
- @api_endpoint_metrics('POST', '/analysis/query')
47
+ @api_endpoint_metrics("POST", "/analysis/query")
47
48
  def post(self):
48
49
  data = request.json
49
50
  query = data.get("query")
@@ -67,10 +68,8 @@ class QueryAnalysis(Resource):
67
68
  try:
68
69
  result = mysql_proxy.process_query(query)
69
70
  except Exception as e:
70
- import traceback
71
-
72
- logger.error(traceback.format_exc())
73
- return http_error(500, "Error", str(e))
71
+ logger.exception("Error during query analysis:")
72
+ return http_error(500, "Error", f"Unexpected error duting query analysis: {e}")
74
73
 
75
74
  if result.type == SQL_RESPONSE_TYPE.ERROR:
76
75
  return http_error(500, f"Error {result.error_code}", result.error_message)
@@ -83,14 +82,12 @@ class QueryAnalysis(Resource):
83
82
  analysis = analyze_df(df)
84
83
  except ImportError:
85
84
  return {
86
- 'analysis': {},
87
- 'timestamp': time.time(),
88
- 'error': 'To use this feature, please install the "dataprep_ml" package.'
85
+ "analysis": {},
86
+ "timestamp": time.time(),
87
+ "error": 'To use this feature, please install the "dataprep_ml" package.',
89
88
  }
90
89
 
91
- query_tables = [
92
- table.to_string() for table in get_query_tables(ast)
93
- ]
90
+ query_tables = [table.to_string() for table in get_query_tables(ast)]
94
91
 
95
92
  return {
96
93
  "analysis": analysis,
@@ -104,7 +101,7 @@ class QueryAnalysis(Resource):
104
101
  @ns_conf.route("/data")
105
102
  class DataAnalysis(Resource):
106
103
  @ns_conf.doc("post_data_to_analyze")
107
- @api_endpoint_metrics('POST', '/analysis/data')
104
+ @api_endpoint_metrics("POST", "/analysis/data")
108
105
  def post(self):
109
106
  payload = request.json
110
107
  column_names = payload.get("column_names")
@@ -116,15 +113,11 @@ class DataAnalysis(Resource):
116
113
  return {"analysis": analysis, "timestamp": time.time()}
117
114
  except ImportError:
118
115
  return {
119
- 'analysis': {},
120
- 'timestamp': timestamp,
121
- 'error': 'To use this feature, please install the "dataprep_ml" package.'
116
+ "analysis": {},
117
+ "timestamp": timestamp,
118
+ "error": 'To use this feature, please install the "dataprep_ml" package.',
122
119
  }
123
120
  except Exception as e:
124
121
  # Don't want analysis exceptions to show up on UI.
125
122
  # TODO: Fix analysis so it doesn't throw exceptions at all.
126
- return {
127
- 'analysis': {},
128
- 'timestamp': timestamp,
129
- 'error': str(e)
130
- }
123
+ return {"analysis": {}, "timestamp": timestamp, "error": str(e)}
@@ -117,7 +117,7 @@ class Auth(Resource):
117
117
  if resp.status_code != 200:
118
118
  logger.warning(f"Wrong response from cloud server: {resp.status_code}")
119
119
  except Exception as e:
120
- logger.warning(f"Cant't send request to cloud server: {e}")
120
+ logger.warning(f"Cant't send request to cloud server: {e}", exc_info=True)
121
121
 
122
122
  if request.path.endswith("/auth/callback/cloud_home"):
123
123
  return redirect(f"https://{auth_server}")
@@ -18,9 +18,6 @@ def create_chatbot(project_name, name, chatbot):
18
18
  if name is None:
19
19
  return http_error(HTTPStatus.BAD_REQUEST, "Missing field", 'Missing "name" field for chatbot')
20
20
 
21
- if not name.islower():
22
- return http_error(HTTPStatus.BAD_REQUEST, "Wrong name", f"The name must be in lower case: {name}")
23
-
24
21
  model_name = chatbot.get("model_name", None)
25
22
  agent_name = chatbot.get("agent_name", None)
26
23
  if model_name is None and agent_name is None:
@@ -241,8 +238,6 @@ class ChatBotResource(Resource):
241
238
  "Chatbot already exists",
242
239
  f"Chatbot with name {name} already exists. Please choose a different one.",
243
240
  )
244
- if not name.islower():
245
- return http_error(HTTPStatus.BAD_REQUEST, "Wrong name", f"The name must be in lower case: {name}")
246
241
 
247
242
  if existing_chatbot is None:
248
243
  # Create
@@ -11,6 +11,7 @@ from flask import current_app as ca
11
11
  from mindsdb.api.http.namespaces.configs.config import ns_conf
12
12
  from mindsdb.api.http.utils import http_error
13
13
  from mindsdb.metrics.metrics import api_endpoint_metrics
14
+ from mindsdb.utilities.api_status import get_api_status
14
15
  from mindsdb.utilities import log
15
16
  from mindsdb.utilities.functions import decrypt, encrypt
16
17
  from mindsdb.utilities.config import Config
@@ -32,6 +33,13 @@ class GetConfig(Resource):
32
33
  value = config.get(key)
33
34
  if value is not None:
34
35
  resp[key] = value
36
+
37
+ api_status = get_api_status()
38
+ api_configs = copy.deepcopy(config["api"])
39
+ for api_name, api_config in api_configs.items():
40
+ api_config["running"] = api_status.get(api_name, False)
41
+ resp["api"] = api_configs
42
+
35
43
  return resp
36
44
 
37
45
  @ns_conf.doc("put_config")
@@ -163,9 +171,7 @@ class Integration(Resource):
163
171
  )
164
172
 
165
173
  try:
166
- engine = params["type"]
167
- if engine is not None:
168
- del params["type"]
174
+ engine = params.pop("type", None)
169
175
  params.pop("publish", False)
170
176
  storage = params.pop("storage", None)
171
177
  ca.integration_controller.add(name, engine, params)
@@ -178,10 +184,10 @@ class Integration(Resource):
178
184
  handler.handler_storage.import_files(export)
179
185
 
180
186
  except Exception as e:
181
- logger.error(str(e))
187
+ logger.exception("An error occurred during the creation of the integration:")
182
188
  if temp_dir is not None:
183
189
  shutil.rmtree(temp_dir)
184
- return http_error(HTTPStatus.INTERNAL_SERVER_ERROR, "Error", f"Error during config update: {str(e)}")
190
+ return http_error(HTTPStatus.INTERNAL_SERVER_ERROR, "Error", f"Error during config update: {e}")
185
191
 
186
192
  if temp_dir is not None:
187
193
  shutil.rmtree(temp_dir)
@@ -198,8 +204,8 @@ class Integration(Resource):
198
204
  try:
199
205
  ca.integration_controller.delete(name)
200
206
  except Exception as e:
201
- logger.error(str(e))
202
- return http_error(HTTPStatus.INTERNAL_SERVER_ERROR, "Error", f"Error during integration delete: {str(e)}")
207
+ logger.exception("An error occurred while deleting the integration")
208
+ return http_error(HTTPStatus.INTERNAL_SERVER_ERROR, "Error", f"Error during integration delete: {e}")
203
209
  return "", 200
204
210
 
205
211
  @ns_conf.doc("modify_integration")
@@ -223,8 +229,6 @@ class Integration(Resource):
223
229
  ca.integration_controller.modify(name, params)
224
230
 
225
231
  except Exception as e:
226
- logger.error(str(e))
227
- return http_error(
228
- HTTPStatus.INTERNAL_SERVER_ERROR, "Error", f"Error during integration modification: {str(e)}"
229
- )
232
+ logger.exception("An error occurred while modifying the integration")
233
+ return http_error(HTTPStatus.INTERNAL_SERVER_ERROR, "Error", f"Error during integration modification: {e}")
230
234
  return "", 200