MindsDB 25.5.3.0__py3-none-any.whl → 25.5.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 (310) hide show
  1. mindsdb/__about__.py +1 -1
  2. mindsdb/__main__.py +127 -79
  3. mindsdb/api/a2a/__init__.py +0 -0
  4. mindsdb/api/a2a/__main__.py +114 -0
  5. mindsdb/api/a2a/a2a_client.py +439 -0
  6. mindsdb/api/a2a/agent.py +308 -0
  7. mindsdb/api/a2a/common/__init__.py +0 -0
  8. mindsdb/api/a2a/common/client/__init__.py +4 -0
  9. mindsdb/api/a2a/common/client/card_resolver.py +21 -0
  10. mindsdb/api/a2a/common/client/client.py +86 -0
  11. mindsdb/api/a2a/common/server/__init__.py +4 -0
  12. mindsdb/api/a2a/common/server/server.py +164 -0
  13. mindsdb/api/a2a/common/server/task_manager.py +287 -0
  14. mindsdb/api/a2a/common/server/utils.py +28 -0
  15. mindsdb/api/a2a/common/types.py +365 -0
  16. mindsdb/api/a2a/constants.py +9 -0
  17. mindsdb/api/a2a/run_a2a.py +129 -0
  18. mindsdb/api/a2a/task_manager.py +594 -0
  19. mindsdb/api/executor/command_executor.py +47 -27
  20. mindsdb/api/executor/datahub/classes/response.py +5 -2
  21. mindsdb/api/executor/datahub/datanodes/integration_datanode.py +39 -72
  22. mindsdb/api/executor/planner/query_planner.py +10 -1
  23. mindsdb/api/executor/sql_query/result_set.py +185 -52
  24. mindsdb/api/executor/sql_query/sql_query.py +1 -1
  25. mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +9 -12
  26. mindsdb/api/executor/sql_query/steps/fetch_dataframe.py +8 -10
  27. mindsdb/api/executor/sql_query/steps/fetch_dataframe_partition.py +5 -44
  28. mindsdb/api/executor/sql_query/steps/insert_step.py +24 -15
  29. mindsdb/api/executor/sql_query/steps/join_step.py +1 -1
  30. mindsdb/api/executor/sql_query/steps/project_step.py +1 -1
  31. mindsdb/api/executor/sql_query/steps/sql_steps.py +1 -1
  32. mindsdb/api/executor/sql_query/steps/subselect_step.py +4 -8
  33. mindsdb/api/executor/sql_query/steps/union_step.py +1 -3
  34. mindsdb/api/http/initialize.py +99 -83
  35. mindsdb/api/http/namespaces/analysis.py +3 -3
  36. mindsdb/api/http/namespaces/file.py +8 -2
  37. mindsdb/api/http/namespaces/sql.py +13 -27
  38. mindsdb/api/mcp/start.py +42 -5
  39. mindsdb/api/mysql/mysql_proxy/data_types/mysql_packet.py +0 -1
  40. mindsdb/api/mysql/mysql_proxy/data_types/mysql_packets/binary_resultset_row_package.py +52 -19
  41. mindsdb/api/mysql/mysql_proxy/executor/mysql_executor.py +8 -10
  42. mindsdb/api/mysql/mysql_proxy/libs/constants/mysql.py +54 -38
  43. mindsdb/api/mysql/mysql_proxy/mysql_proxy.py +82 -115
  44. mindsdb/api/mysql/mysql_proxy/utilities/dump.py +351 -0
  45. mindsdb/api/postgres/postgres_proxy/executor/executor.py +1 -1
  46. mindsdb/api/postgres/postgres_proxy/postgres_proxy.py +5 -6
  47. mindsdb/integrations/handlers/altibase_handler/altibase_handler.py +26 -27
  48. mindsdb/integrations/handlers/altibase_handler/connection_args.py +13 -13
  49. mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler.py +8 -8
  50. mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler_dsn.py +13 -13
  51. mindsdb/integrations/handlers/anthropic_handler/__init__.py +2 -2
  52. mindsdb/integrations/handlers/anthropic_handler/anthropic_handler.py +1 -3
  53. mindsdb/integrations/handlers/aurora_handler/aurora_handler.py +1 -0
  54. mindsdb/integrations/handlers/autosklearn_handler/autosklearn_handler.py +1 -1
  55. mindsdb/integrations/handlers/autosklearn_handler/config.py +0 -1
  56. mindsdb/integrations/handlers/bigquery_handler/bigquery_handler.py +1 -1
  57. mindsdb/integrations/handlers/bigquery_handler/tests/test_bigquery_handler.py +1 -1
  58. mindsdb/integrations/handlers/binance_handler/binance_handler.py +1 -0
  59. mindsdb/integrations/handlers/binance_handler/binance_tables.py +3 -4
  60. mindsdb/integrations/handlers/byom_handler/__init__.py +0 -1
  61. mindsdb/integrations/handlers/ckan_handler/ckan_handler.py +3 -0
  62. mindsdb/integrations/handlers/clickhouse_handler/__init__.py +1 -1
  63. mindsdb/integrations/handlers/cloud_spanner_handler/tests/test_cloud_spanner_handler.py +0 -2
  64. mindsdb/integrations/handlers/cloud_sql_handler/cloud_sql_handler.py +0 -1
  65. mindsdb/integrations/handlers/cohere_handler/__init__.py +1 -1
  66. mindsdb/integrations/handlers/cohere_handler/cohere_handler.py +11 -13
  67. mindsdb/integrations/handlers/confluence_handler/confluence_tables.py +6 -0
  68. mindsdb/integrations/handlers/databend_handler/connection_args.py +1 -1
  69. mindsdb/integrations/handlers/databend_handler/databend_handler.py +4 -4
  70. mindsdb/integrations/handlers/databend_handler/tests/__init__.py +0 -1
  71. mindsdb/integrations/handlers/databend_handler/tests/test_databend_handler.py +1 -1
  72. mindsdb/integrations/handlers/derby_handler/connection_args.py +1 -1
  73. mindsdb/integrations/handlers/derby_handler/derby_handler.py +14 -22
  74. mindsdb/integrations/handlers/derby_handler/tests/test_derby_handler.py +6 -6
  75. mindsdb/integrations/handlers/discord_handler/discord_handler.py +5 -5
  76. mindsdb/integrations/handlers/discord_handler/discord_tables.py +3 -3
  77. mindsdb/integrations/handlers/discord_handler/tests/test_discord.py +5 -3
  78. mindsdb/integrations/handlers/dockerhub_handler/dockerhub.py +3 -3
  79. mindsdb/integrations/handlers/dockerhub_handler/dockerhub_handler.py +2 -2
  80. mindsdb/integrations/handlers/dockerhub_handler/dockerhub_tables.py +57 -54
  81. mindsdb/integrations/handlers/dremio_handler/__init__.py +2 -2
  82. mindsdb/integrations/handlers/druid_handler/__init__.py +1 -1
  83. mindsdb/integrations/handlers/druid_handler/druid_handler.py +2 -2
  84. mindsdb/integrations/handlers/edgelessdb_handler/tests/test_edgelessdb_handler.py +9 -9
  85. mindsdb/integrations/handlers/email_handler/email_client.py +1 -1
  86. mindsdb/integrations/handlers/email_handler/email_ingestor.py +1 -1
  87. mindsdb/integrations/handlers/email_handler/email_tables.py +0 -1
  88. mindsdb/integrations/handlers/email_handler/settings.py +0 -1
  89. mindsdb/integrations/handlers/eventstoredb_handler/eventstoredb_handler.py +2 -1
  90. mindsdb/integrations/handlers/firebird_handler/firebird_handler.py +1 -1
  91. mindsdb/integrations/handlers/flaml_handler/flaml_handler.py +9 -9
  92. mindsdb/integrations/handlers/frappe_handler/frappe_client.py +5 -5
  93. mindsdb/integrations/handlers/frappe_handler/frappe_handler.py +6 -5
  94. mindsdb/integrations/handlers/frappe_handler/frappe_tables.py +2 -2
  95. mindsdb/integrations/handlers/github_handler/connection_args.py +2 -2
  96. mindsdb/integrations/handlers/github_handler/github_handler.py +1 -8
  97. mindsdb/integrations/handlers/github_handler/github_tables.py +13 -24
  98. mindsdb/integrations/handlers/gitlab_handler/gitlab_handler.py +2 -1
  99. mindsdb/integrations/handlers/gitlab_handler/gitlab_tables.py +1 -4
  100. mindsdb/integrations/handlers/gmail_handler/gmail_handler.py +6 -13
  101. mindsdb/integrations/handlers/google_books_handler/google_books_handler.py +2 -1
  102. mindsdb/integrations/handlers/google_books_handler/google_books_tables.py +0 -3
  103. mindsdb/integrations/handlers/google_calendar_handler/google_calendar_handler.py +4 -4
  104. mindsdb/integrations/handlers/google_calendar_handler/google_calendar_tables.py +2 -6
  105. mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_handler.py +3 -2
  106. mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_tables.py +0 -3
  107. mindsdb/integrations/handlers/google_fit_handler/google_fit_handler.py +10 -12
  108. mindsdb/integrations/handlers/google_fit_handler/google_fit_tables.py +11 -13
  109. mindsdb/integrations/handlers/google_search_handler/google_search_handler.py +2 -1
  110. mindsdb/integrations/handlers/google_search_handler/google_search_tables.py +0 -3
  111. mindsdb/integrations/handlers/groq_handler/__init__.py +3 -3
  112. mindsdb/integrations/handlers/hackernews_handler/hn_handler.py +5 -7
  113. mindsdb/integrations/handlers/hackernews_handler/hn_table.py +6 -7
  114. mindsdb/integrations/handlers/hive_handler/tests/test_hive_handler.py +1 -1
  115. mindsdb/integrations/handlers/hsqldb_handler/connection_args.py +6 -6
  116. mindsdb/integrations/handlers/hsqldb_handler/hsqldb_handler.py +4 -3
  117. mindsdb/integrations/handlers/huggingface_api_handler/exceptions.py +1 -1
  118. mindsdb/integrations/handlers/huggingface_api_handler/huggingface_api_handler.py +1 -8
  119. mindsdb/integrations/handlers/huggingface_handler/huggingface_handler.py +6 -6
  120. mindsdb/integrations/handlers/huggingface_handler/requirements.txt +1 -1
  121. mindsdb/integrations/handlers/huggingface_handler/requirements_cpu.txt +1 -1
  122. mindsdb/integrations/handlers/ignite_handler/ignite_handler.py +2 -1
  123. mindsdb/integrations/handlers/impala_handler/impala_handler.py +9 -12
  124. mindsdb/integrations/handlers/impala_handler/tests/test_impala_handler.py +11 -11
  125. mindsdb/integrations/handlers/influxdb_handler/influxdb_handler.py +10 -13
  126. mindsdb/integrations/handlers/influxdb_handler/influxdb_tables.py +20 -20
  127. mindsdb/integrations/handlers/informix_handler/__about__.py +8 -8
  128. mindsdb/integrations/handlers/informix_handler/__init__.py +12 -5
  129. mindsdb/integrations/handlers/informix_handler/informix_handler.py +99 -133
  130. mindsdb/integrations/handlers/informix_handler/tests/test_informix_handler.py +13 -11
  131. mindsdb/integrations/handlers/ingres_handler/__about__.py +0 -1
  132. mindsdb/integrations/handlers/ingres_handler/ingres_handler.py +1 -0
  133. mindsdb/integrations/handlers/jira_handler/jira_handler.py +4 -4
  134. mindsdb/integrations/handlers/jira_handler/jira_tables.py +9 -9
  135. mindsdb/integrations/handlers/kinetica_handler/__init__.py +0 -1
  136. mindsdb/integrations/handlers/langchain_handler/langchain_handler.py +4 -4
  137. mindsdb/integrations/handlers/langchain_handler/tools.py +9 -10
  138. mindsdb/integrations/handlers/leonardoai_handler/__init__.py +1 -1
  139. mindsdb/integrations/handlers/lightwood_handler/functions.py +2 -2
  140. mindsdb/integrations/handlers/lightwood_handler/lightwood_handler.py +0 -1
  141. mindsdb/integrations/handlers/lightwood_handler/tests/test_lightwood_handler.py +11 -11
  142. mindsdb/integrations/handlers/llama_index_handler/llama_index_handler.py +4 -4
  143. mindsdb/integrations/handlers/llama_index_handler/settings.py +10 -9
  144. mindsdb/integrations/handlers/materialize_handler/tests/test_materialize_handler.py +8 -10
  145. mindsdb/integrations/handlers/matrixone_handler/matrixone_handler.py +4 -4
  146. mindsdb/integrations/handlers/matrixone_handler/tests/test_matrixone_handler.py +8 -9
  147. mindsdb/integrations/handlers/maxdb_handler/connection_args.py +25 -25
  148. mindsdb/integrations/handlers/maxdb_handler/maxdb_handler.py +1 -0
  149. mindsdb/integrations/handlers/mediawiki_handler/mediawiki_handler.py +3 -2
  150. mindsdb/integrations/handlers/mediawiki_handler/mediawiki_tables.py +1 -1
  151. mindsdb/integrations/handlers/mendeley_handler/__about__.py +1 -1
  152. mindsdb/integrations/handlers/mendeley_handler/__init__.py +2 -2
  153. mindsdb/integrations/handlers/mendeley_handler/mendeley_handler.py +48 -56
  154. mindsdb/integrations/handlers/mendeley_handler/mendeley_tables.py +24 -29
  155. mindsdb/integrations/handlers/mendeley_handler/tests/test_mendeley_handler.py +19 -17
  156. mindsdb/integrations/handlers/merlion_handler/merlion_handler.py +5 -4
  157. mindsdb/integrations/handlers/minds_endpoint_handler/__init__.py +3 -3
  158. mindsdb/integrations/handlers/mlflow_handler/mlflow_handler.py +58 -36
  159. mindsdb/integrations/handlers/monetdb_handler/__about__.py +8 -8
  160. mindsdb/integrations/handlers/monetdb_handler/__init__.py +15 -5
  161. mindsdb/integrations/handlers/monetdb_handler/connection_args.py +17 -18
  162. mindsdb/integrations/handlers/monetdb_handler/monetdb_handler.py +40 -57
  163. mindsdb/integrations/handlers/monetdb_handler/tests/test_monetdb_handler.py +7 -8
  164. mindsdb/integrations/handlers/monetdb_handler/utils/monet_get_id.py +13 -14
  165. mindsdb/integrations/handlers/monkeylearn_handler/__about__.py +1 -1
  166. mindsdb/integrations/handlers/monkeylearn_handler/__init__.py +1 -1
  167. mindsdb/integrations/handlers/monkeylearn_handler/monkeylearn_handler.py +2 -5
  168. mindsdb/integrations/handlers/ms_one_drive_handler/ms_graph_api_one_drive_client.py +1 -0
  169. mindsdb/integrations/handlers/ms_one_drive_handler/ms_one_drive_handler.py +1 -1
  170. mindsdb/integrations/handlers/ms_teams_handler/ms_graph_api_teams_client.py +23 -23
  171. mindsdb/integrations/handlers/ms_teams_handler/ms_teams_handler.py +3 -3
  172. mindsdb/integrations/handlers/ms_teams_handler/ms_teams_tables.py +10 -5
  173. mindsdb/integrations/handlers/mssql_handler/mssql_handler.py +73 -8
  174. mindsdb/integrations/handlers/mysql_handler/__about__.py +8 -8
  175. mindsdb/integrations/handlers/mysql_handler/__init__.py +15 -5
  176. mindsdb/integrations/handlers/mysql_handler/connection_args.py +43 -47
  177. mindsdb/integrations/handlers/mysql_handler/mysql_handler.py +101 -34
  178. mindsdb/integrations/handlers/mysql_handler/settings.py +15 -13
  179. mindsdb/integrations/handlers/neuralforecast_handler/neuralforecast_handler.py +1 -1
  180. mindsdb/integrations/handlers/newsapi_handler/newsapi_handler.py +1 -1
  181. mindsdb/integrations/handlers/newsapi_handler/tests/test_newsapi_handler.py +4 -4
  182. mindsdb/integrations/handlers/nuo_jdbc_handler/connection_args.py +2 -2
  183. mindsdb/integrations/handlers/nuo_jdbc_handler/nuo_jdbc_handler.py +28 -36
  184. mindsdb/integrations/handlers/nuo_jdbc_handler/tests/test_nuo_handler.py +5 -5
  185. mindsdb/integrations/handlers/oceanbase_handler/oceanbase_handler.py +0 -1
  186. mindsdb/integrations/handlers/oceanbase_handler/tests/test_oceanbase_handler.py +8 -10
  187. mindsdb/integrations/handlers/ollama_handler/ollama_handler.py +3 -3
  188. mindsdb/integrations/handlers/opengauss_handler/tests/test_opengauss_handler.py +1 -2
  189. mindsdb/integrations/handlers/openstreetmap_handler/__init__.py +7 -7
  190. mindsdb/integrations/handlers/oracle_handler/connection_args.py +6 -0
  191. mindsdb/integrations/handlers/oracle_handler/oracle_handler.py +77 -11
  192. mindsdb/integrations/handlers/orioledb_handler/tests/test_orioledb_handler.py +8 -10
  193. mindsdb/integrations/handlers/palm_handler/__about__.py +1 -1
  194. mindsdb/integrations/handlers/palm_handler/__init__.py +1 -1
  195. mindsdb/integrations/handlers/palm_handler/palm_handler.py +1 -3
  196. mindsdb/integrations/handlers/paypal_handler/paypal_handler.py +2 -2
  197. mindsdb/integrations/handlers/paypal_handler/paypal_tables.py +15 -14
  198. mindsdb/integrations/handlers/pgvector_handler/pgvector_handler.py +53 -10
  199. mindsdb/integrations/handlers/phoenix_handler/__init__.py +1 -1
  200. mindsdb/integrations/handlers/phoenix_handler/phoenix_handler.py +1 -0
  201. mindsdb/integrations/handlers/pinot_handler/__init__.py +1 -1
  202. mindsdb/integrations/handlers/pinot_handler/pinot_handler.py +3 -2
  203. mindsdb/integrations/handlers/plaid_handler/plaid_handler.py +13 -13
  204. mindsdb/integrations/handlers/plaid_handler/plaid_tables.py +10 -12
  205. mindsdb/integrations/handlers/plaid_handler/utils.py +4 -6
  206. mindsdb/integrations/handlers/planetscale_handler/planetscale_handler.py +1 -4
  207. mindsdb/integrations/handlers/portkey_handler/__init__.py +2 -2
  208. mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +105 -24
  209. mindsdb/integrations/handlers/postgres_handler/tests/test_postgres_handler.py +11 -6
  210. mindsdb/integrations/handlers/questdb_handler/questdb_handler.py +1 -2
  211. mindsdb/integrations/handlers/questdb_handler/tests/test_questdb_handler.py +2 -3
  212. mindsdb/integrations/handlers/quickbooks_handler/quickbooks_handler.py +6 -8
  213. mindsdb/integrations/handlers/quickbooks_handler/quickbooks_table.py +10 -10
  214. mindsdb/integrations/handlers/rag_handler/ingest.py +2 -2
  215. mindsdb/integrations/handlers/rag_handler/rag_handler.py +1 -1
  216. mindsdb/integrations/handlers/rag_handler/settings.py +1 -1
  217. mindsdb/integrations/handlers/reddit_handler/reddit_handler.py +2 -7
  218. mindsdb/integrations/handlers/reddit_handler/reddit_tables.py +2 -3
  219. mindsdb/integrations/handlers/replicate_handler/replicate_handler.py +6 -6
  220. mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_handler.py +1 -2
  221. mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_tables.py +0 -3
  222. mindsdb/integrations/handlers/rockset_handler/connection_args.py +14 -14
  223. mindsdb/integrations/handlers/rockset_handler/tests/test_rockset_handler.py +1 -0
  224. mindsdb/integrations/handlers/scylla_handler/scylla_handler.py +6 -5
  225. mindsdb/integrations/handlers/sendinblue_handler/sendinblue_handler.py +2 -1
  226. mindsdb/integrations/handlers/sendinblue_handler/sendinblue_tables.py +16 -16
  227. mindsdb/integrations/handlers/sentence_transformers_handler/__init__.py +1 -1
  228. mindsdb/integrations/handlers/sheets_handler/connection_args.py +1 -1
  229. mindsdb/integrations/handlers/shopify_handler/shopify_handler.py +7 -6
  230. mindsdb/integrations/handlers/shopify_handler/shopify_tables.py +38 -41
  231. mindsdb/integrations/handlers/singlestore_handler/__about__.py +1 -1
  232. mindsdb/integrations/handlers/singlestore_handler/__init__.py +0 -1
  233. mindsdb/integrations/handlers/singlestore_handler/singlestore_handler.py +1 -0
  234. mindsdb/integrations/handlers/singlestore_handler/tests/test_singlestore_handler.py +3 -3
  235. mindsdb/integrations/handlers/slack_handler/__init__.py +3 -3
  236. mindsdb/integrations/handlers/snowflake_handler/snowflake_handler.py +100 -6
  237. mindsdb/integrations/handlers/solr_handler/connection_args.py +7 -7
  238. mindsdb/integrations/handlers/solr_handler/solr_handler.py +2 -1
  239. mindsdb/integrations/handlers/solr_handler/tests/test_solr_handler.py +2 -1
  240. mindsdb/integrations/handlers/sqlany_handler/sqlany_handler.py +3 -2
  241. mindsdb/integrations/handlers/sqlite_handler/sqlite_handler.py +1 -0
  242. mindsdb/integrations/handlers/sqreamdb_handler/connection_args.py +1 -1
  243. mindsdb/integrations/handlers/sqreamdb_handler/sqreamdb_handler.py +15 -20
  244. mindsdb/integrations/handlers/sqreamdb_handler/tests/test_sqreamdb_handler.py +4 -4
  245. mindsdb/integrations/handlers/stabilityai_handler/__init__.py +1 -1
  246. mindsdb/integrations/handlers/starrocks_handler/starrocks_handler.py +0 -1
  247. mindsdb/integrations/handlers/starrocks_handler/tests/test_starrocks_handler.py +8 -10
  248. mindsdb/integrations/handlers/statsforecast_handler/statsforecast_handler.py +2 -2
  249. mindsdb/integrations/handlers/strava_handler/strava_handler.py +4 -8
  250. mindsdb/integrations/handlers/strava_handler/strava_tables.py +22 -30
  251. mindsdb/integrations/handlers/stripe_handler/stripe_handler.py +3 -2
  252. mindsdb/integrations/handlers/stripe_handler/stripe_tables.py +11 -27
  253. mindsdb/integrations/handlers/supabase_handler/tests/test_supabase_handler.py +1 -1
  254. mindsdb/integrations/handlers/surrealdb_handler/surrealdb_handler.py +4 -4
  255. mindsdb/integrations/handlers/tdengine_handler/tdengine_handler.py +25 -27
  256. mindsdb/integrations/handlers/tdengine_handler/tests/test_tdengine_handler.py +8 -8
  257. mindsdb/integrations/handlers/tidb_handler/tests/test_tidb_handler.py +1 -2
  258. mindsdb/integrations/handlers/timegpt_handler/timegpt_handler.py +5 -5
  259. mindsdb/integrations/handlers/tpot_handler/tpot_handler.py +21 -26
  260. mindsdb/integrations/handlers/trino_handler/trino_handler.py +14 -14
  261. mindsdb/integrations/handlers/twitter_handler/twitter_handler.py +2 -4
  262. mindsdb/integrations/handlers/unify_handler/tests/test_unify_handler.py +7 -8
  263. mindsdb/integrations/handlers/unify_handler/unify_handler.py +9 -9
  264. mindsdb/integrations/handlers/vertex_handler/vertex_client.py +1 -1
  265. mindsdb/integrations/handlers/vertica_handler/tests/test_vertica_handler.py +11 -11
  266. mindsdb/integrations/handlers/vertica_handler/vertica_handler.py +11 -14
  267. mindsdb/integrations/handlers/vitess_handler/tests/test_vitess_handler.py +9 -11
  268. mindsdb/integrations/handlers/vitess_handler/vitess_handler.py +0 -1
  269. mindsdb/integrations/handlers/web_handler/web_handler.py +1 -0
  270. mindsdb/integrations/handlers/whatsapp_handler/__init__.py +3 -3
  271. mindsdb/integrations/handlers/writer_handler/evaluate.py +1 -1
  272. mindsdb/integrations/handlers/writer_handler/settings.py +0 -1
  273. mindsdb/integrations/handlers/writer_handler/writer_handler.py +1 -0
  274. mindsdb/integrations/handlers/youtube_handler/youtube_handler.py +5 -5
  275. mindsdb/integrations/handlers/youtube_handler/youtube_tables.py +26 -27
  276. mindsdb/integrations/handlers/yugabyte_handler/tests/test_yugabyte_handler.py +3 -3
  277. mindsdb/integrations/handlers/yugabyte_handler/yugabyte_handler.py +0 -6
  278. mindsdb/integrations/libs/response.py +67 -52
  279. mindsdb/integrations/libs/vectordatabase_handler.py +6 -0
  280. mindsdb/integrations/utilities/handler_utils.py +15 -3
  281. mindsdb/integrations/utilities/handlers/api_utilities/__init__.py +0 -1
  282. mindsdb/integrations/utilities/handlers/auth_utilities/__init__.py +0 -2
  283. mindsdb/integrations/utilities/utils.py +3 -3
  284. mindsdb/interfaces/agents/agents_controller.py +164 -1
  285. mindsdb/interfaces/agents/constants.py +15 -0
  286. mindsdb/interfaces/agents/langchain_agent.py +16 -4
  287. mindsdb/interfaces/agents/mindsdb_database_agent.py +101 -2
  288. mindsdb/interfaces/knowledge_base/controller.py +25 -0
  289. mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +13 -10
  290. mindsdb/interfaces/knowledge_base/preprocessing/json_chunker.py +434 -0
  291. mindsdb/interfaces/knowledge_base/preprocessing/models.py +54 -0
  292. mindsdb/interfaces/query_context/context_controller.py +66 -10
  293. mindsdb/interfaces/skills/custom/text2sql/mindsdb_kb_tools.py +190 -0
  294. mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +92 -0
  295. mindsdb/interfaces/skills/skill_tool.py +202 -57
  296. mindsdb/interfaces/skills/sql_agent.py +205 -17
  297. mindsdb/interfaces/storage/fs.py +1 -0
  298. mindsdb/interfaces/variables/__init__.py +0 -0
  299. mindsdb/interfaces/variables/variables_controller.py +97 -0
  300. mindsdb/migrations/env.py +5 -7
  301. mindsdb/migrations/migrate.py +47 -7
  302. mindsdb/migrations/versions/2025-05-21_9f150e4f9a05_checkpoint_1.py +360 -0
  303. mindsdb/utilities/config.py +331 -219
  304. mindsdb/utilities/starters.py +13 -0
  305. {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/METADATA +641 -695
  306. {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/RECORD +309 -288
  307. {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/WHEEL +1 -1
  308. mindsdb/integrations/handlers/monkeylearn_handler/requirements.txt +0 -1
  309. {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/licenses/LICENSE +0 -0
  310. {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/top_level.txt +0 -0
mindsdb/__about__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  __title__ = 'MindsDB'
2
2
  __package_name__ = 'mindsdb'
3
- __version__ = '25.5.3.0'
3
+ __version__ = '25.5.4.0'
4
4
  __description__ = "MindsDB's AI SQL Server enables developers to build AI tools that need access to real-time data to perform their tasks"
5
5
  __email__ = "jorge@mindsdb.com"
6
6
  __author__ = 'MindsDB Inc'
mindsdb/__main__.py CHANGED
@@ -25,8 +25,16 @@ logger.debug("Starting MindsDB...")
25
25
  from mindsdb.__about__ import __version__ as mindsdb_version
26
26
  from mindsdb.utilities.config import config
27
27
  from mindsdb.utilities.starters import (
28
- start_http, start_mysql, start_mongo, start_postgres, start_ml_task_queue,
29
- start_scheduler, start_tasks, start_mcp, start_litellm
28
+ start_http,
29
+ start_mysql,
30
+ start_mongo,
31
+ start_postgres,
32
+ start_ml_task_queue,
33
+ start_scheduler,
34
+ start_tasks,
35
+ start_mcp,
36
+ start_litellm,
37
+ start_a2a,
30
38
  )
31
39
  from mindsdb.utilities.ps import is_pid_listen_port, get_child_pids
32
40
  import mindsdb.interfaces.storage.db as db
@@ -40,9 +48,9 @@ try:
40
48
  except Exception:
41
49
  import multiprocessing as mp
42
50
  try:
43
- mp.set_start_method('spawn')
51
+ mp.set_start_method("spawn")
44
52
  except RuntimeError:
45
- logger.info('Torch multiprocessing context already set, ignoring...')
53
+ logger.info("Torch multiprocessing context already set, ignoring...")
46
54
 
47
55
  gc.enable()
48
56
 
@@ -50,15 +58,16 @@ _stop_event = threading.Event()
50
58
 
51
59
 
52
60
  class TrunkProcessEnum(Enum):
53
- HTTP = 'http'
54
- MYSQL = 'mysql'
55
- MONGODB = 'mongodb'
56
- POSTGRES = 'postgres'
57
- JOBS = 'jobs'
58
- TASKS = 'tasks'
59
- ML_TASK_QUEUE = 'ml_task_queue'
60
- MCP = 'mcp'
61
- LITELLM = 'litellm'
61
+ HTTP = "http"
62
+ MYSQL = "mysql"
63
+ MONGODB = "mongodb"
64
+ POSTGRES = "postgres"
65
+ JOBS = "jobs"
66
+ TASKS = "tasks"
67
+ ML_TASK_QUEUE = "ml_task_queue"
68
+ MCP = "mcp"
69
+ LITELLM = "litellm"
70
+ A2A = "a2a"
62
71
 
63
72
  @classmethod
64
73
  def _missing_(cls, value):
@@ -96,7 +105,8 @@ class TrunkProcessData:
96
105
  self._restarts_time.append(current_time_seconds)
97
106
  if self.max_restart_interval_seconds > 0:
98
107
  self._restarts_time = [
99
- x for x in self._restarts_time
108
+ x
109
+ for x in self._restarts_time
100
110
  if x >= (current_time_seconds - self.max_restart_interval_seconds)
101
111
  ]
102
112
  if len(self._restarts_time) > self.max_restart_count:
@@ -113,12 +123,17 @@ class TrunkProcessData:
113
123
  """
114
124
  if config.is_cloud:
115
125
  return False
116
- if sys.platform in ('linux', 'darwin'):
117
- return self.restart_on_failure and self.process.exitcode == -signal.SIGKILL.value
126
+ if sys.platform in ("linux", "darwin"):
127
+ return (
128
+ self.restart_on_failure
129
+ and self.process.exitcode == -signal.SIGKILL.value
130
+ )
118
131
  else:
119
132
  if self.max_restart_count == 0:
120
133
  # to prevent infinity restarts, max_restart_count should be > 0
121
- logger.warning('In the current OS, it is not possible to use `max_restart_count=0`')
134
+ logger.warning(
135
+ "In the current OS, it is not possible to use `max_restart_count=0`"
136
+ )
122
137
  return False
123
138
  return self.restart_on_failure
124
139
 
@@ -159,22 +174,25 @@ def set_error_model_status_by_pids(unexisting_pids: List[int]):
159
174
  db.session.query(db.Predictor)
160
175
  .filter(
161
176
  db.Predictor.deleted_at.is_(None),
162
- db.Predictor.status.not_in([
163
- db.PREDICTOR_STATUS.COMPLETE,
164
- db.PREDICTOR_STATUS.ERROR
165
- ])
177
+ db.Predictor.status.not_in(
178
+ [db.PREDICTOR_STATUS.COMPLETE, db.PREDICTOR_STATUS.ERROR]
179
+ ),
166
180
  )
167
181
  .all()
168
182
  )
169
183
  for predictor_record in predictor_records:
170
- predictor_process_id = (predictor_record.training_metadata or {}).get('process_id')
184
+ predictor_process_id = (predictor_record.training_metadata or {}).get(
185
+ "process_id"
186
+ )
171
187
  if predictor_process_id in unexisting_pids:
172
188
  predictor_record.status = db.PREDICTOR_STATUS.ERROR
173
189
  if isinstance(predictor_record.data, dict) is False:
174
190
  predictor_record.data = {}
175
- if 'error' not in predictor_record.data:
176
- predictor_record.data['error'] = 'The training process was terminated for unknown reasons'
177
- flag_modified(predictor_record, 'data')
191
+ if "error" not in predictor_record.data:
192
+ predictor_record.data["error"] = (
193
+ "The training process was terminated for unknown reasons"
194
+ )
195
+ flag_modified(predictor_record, "data")
178
196
  db.session.commit()
179
197
 
180
198
 
@@ -186,10 +204,9 @@ def set_error_model_status_for_unfinished():
186
204
  db.session.query(db.Predictor)
187
205
  .filter(
188
206
  db.Predictor.deleted_at.is_(None),
189
- db.Predictor.status.not_in([
190
- db.PREDICTOR_STATUS.COMPLETE,
191
- db.PREDICTOR_STATUS.ERROR
192
- ])
207
+ db.Predictor.status.not_in(
208
+ [db.PREDICTOR_STATUS.COMPLETE, db.PREDICTOR_STATUS.ERROR]
209
+ ),
193
210
  )
194
211
  .all()
195
212
  )
@@ -197,15 +214,14 @@ def set_error_model_status_for_unfinished():
197
214
  predictor_record.status = db.PREDICTOR_STATUS.ERROR
198
215
  if isinstance(predictor_record.data, dict) is False:
199
216
  predictor_record.data = {}
200
- if 'error' not in predictor_record.data:
201
- predictor_record.data['error'] = 'Unknown error'
202
- flag_modified(predictor_record, 'data')
217
+ if "error" not in predictor_record.data:
218
+ predictor_record.data["error"] = "Unknown error"
219
+ flag_modified(predictor_record, "data")
203
220
  db.session.commit()
204
221
 
205
222
 
206
223
  def do_clean_process_marks():
207
- """delete unexisting 'process marks'
208
- """
224
+ """delete unexisting 'process marks'"""
209
225
  while _stop_event.wait(timeout=5) is False:
210
226
  unexisting_pids = clean_unlinked_process_marks()
211
227
  if not config.is_cloud and len(unexisting_pids) > 0:
@@ -217,8 +233,12 @@ def create_permanent_integrations():
217
233
  Create permanent integrations, for now only the 'files' integration.
218
234
  NOTE: this is intentional to avoid importing integration_controller
219
235
  """
220
- integration_name = 'files'
221
- existing = db.session.query(db.Integration).filter_by(name=integration_name, company_id=None).first()
236
+ integration_name = "files"
237
+ existing = (
238
+ db.session.query(db.Integration)
239
+ .filter_by(name=integration_name, company_id=None)
240
+ .first()
241
+ )
222
242
  if existing is None:
223
243
  integration_record = db.Integration(
224
244
  name=integration_name,
@@ -230,7 +250,9 @@ def create_permanent_integrations():
230
250
  try:
231
251
  db.session.commit()
232
252
  except Exception as e:
233
- logger.error(f"Failed to commit permanent integration {integration_name}: {e}")
253
+ logger.error(
254
+ f"Failed to commit permanent integration {integration_name}: {e}"
255
+ )
234
256
  db.session.rollback()
235
257
 
236
258
 
@@ -240,38 +262,40 @@ def validate_default_project() -> None:
240
262
  'is_default' metadata. If it is not possible, then terminate the process with error.
241
263
  Note: this can be done using 'project_controller', but we want to save init time and used RAM.
242
264
  """
243
- new_default_project_name = config.get('default_project')
265
+ new_default_project_name = config.get("default_project")
244
266
  logger.debug(f"Checking if default project {new_default_project_name} exists")
245
267
  filter_company_id = ctx.company_id if ctx.company_id is not None else 0
246
268
 
247
- current_default_project: db.Project | None = (
248
- db.Project.query.filter(
249
- db.Project.company_id == filter_company_id,
250
- db.Project.metadata_['is_default'].as_boolean() == True # noqa
251
- ).first()
252
- )
269
+ current_default_project: db.Project | None = db.Project.query.filter(
270
+ db.Project.company_id == filter_company_id,
271
+ db.Project.metadata_["is_default"].as_boolean() == True, # noqa
272
+ ).first()
253
273
 
254
274
  if current_default_project is None:
255
275
  # Legacy: If the default project does not exist, mark the new one as default.
256
276
  existing_project = db.Project.query.filter(
257
277
  db.Project.company_id == filter_company_id,
258
- func.lower(db.Project.name) == func.lower(new_default_project_name)
278
+ func.lower(db.Project.name) == func.lower(new_default_project_name),
259
279
  ).first()
260
280
  if existing_project is None:
261
- logger.critical(f"A project with the name '{new_default_project_name}' does not exist")
281
+ logger.critical(
282
+ f"A project with the name '{new_default_project_name}' does not exist"
283
+ )
262
284
  sys.exit(1)
263
285
 
264
- existing_project.metadata_ = {'is_default': True}
265
- flag_modified(existing_project, 'metadata_')
286
+ existing_project.metadata_ = {"is_default": True}
287
+ flag_modified(existing_project, "metadata_")
266
288
  db.session.commit()
267
289
  elif current_default_project.name != new_default_project_name:
268
290
  # If the default project exists, but the name is different, update the name.
269
291
  existing_project = db.Project.query.filter(
270
292
  db.Project.company_id == filter_company_id,
271
- func.lower(db.Project.name) == func.lower(new_default_project_name)
293
+ func.lower(db.Project.name) == func.lower(new_default_project_name),
272
294
  ).first()
273
295
  if existing_project is not None:
274
- logger.critical(f"A project with the name '{new_default_project_name}' already exists")
296
+ logger.critical(
297
+ f"A project with the name '{new_default_project_name}' already exists"
298
+ )
275
299
  sys.exit(1)
276
300
  current_default_project.name = new_default_project_name
277
301
  db.session.commit()
@@ -289,7 +313,7 @@ def start_process(trunc_process_data: TrunkProcessData) -> None:
289
313
  trunc_process_data.process = mp_ctx.Process(
290
314
  target=trunc_process_data.entrypoint,
291
315
  args=trunc_process_data.args,
292
- name=trunc_process_data.name
316
+ name=trunc_process_data.name,
293
317
  )
294
318
  trunc_process_data.process.start()
295
319
  except Exception as e:
@@ -300,20 +324,21 @@ def start_process(trunc_process_data: TrunkProcessData) -> None:
300
324
  raise e
301
325
 
302
326
 
303
- if __name__ == '__main__':
327
+ if __name__ == "__main__":
304
328
  mp.freeze_support()
305
329
  # warn if less than 1Gb of free RAM
306
330
  if psutil.virtual_memory().available < (1 << 30):
307
331
  logger.warning(
308
- 'The system is running low on memory. '
309
- + 'This may impact the stability and performance of the program.'
332
+ "The system is running low on memory. "
333
+ + "This may impact the stability and performance of the program."
310
334
  )
311
335
 
312
336
  ctx.set_default()
313
337
 
314
338
  # ---- CHECK SYSTEM ----
315
339
  if not (sys.version_info[0] >= 3 and sys.version_info[1] >= 10):
316
- print("""
340
+ print(
341
+ """
317
342
  MindsDB requires Python >= 3.10 to run
318
343
 
319
344
  Once you have supported Python version installed you can start mindsdb as follows:
@@ -329,11 +354,12 @@ if __name__ == '__main__':
329
354
  python3 -m mindsdb
330
355
 
331
356
  More instructions in https://docs.mindsdb.com
332
- """)
357
+ """
358
+ )
333
359
  exit(1)
334
360
 
335
361
  if config.cmd_args.version:
336
- print(f'MindsDB {mindsdb_version}')
362
+ print(f"MindsDB {mindsdb_version}")
337
363
  sys.exit(0)
338
364
 
339
365
  config.raise_warnings(logger=logger)
@@ -342,18 +368,19 @@ if __name__ == '__main__':
342
368
  if os.environ.get("FLASK_SECRET_KEY") is None:
343
369
  os.environ["FLASK_SECRET_KEY"] = secrets.token_hex(32)
344
370
 
345
- if os.environ.get('ARROW_DEFAULT_MEMORY_POOL') is None:
371
+ if os.environ.get("ARROW_DEFAULT_MEMORY_POOL") is None:
346
372
  try:
347
373
  """It seems like snowflake handler have memory issue that related to pyarrow. Memory usage keep growing with
348
374
  requests. This is related to 'memory pool' that is 'mimalloc' by default: it is fastest but use a lot of ram
349
375
  """
350
376
  import pyarrow as pa
377
+
351
378
  try:
352
379
  pa.jemalloc_memory_pool()
353
- os.environ['ARROW_DEFAULT_MEMORY_POOL'] = 'jemalloc'
380
+ os.environ["ARROW_DEFAULT_MEMORY_POOL"] = "jemalloc"
354
381
  except NotImplementedError:
355
382
  pa.system_memory_pool()
356
- os.environ['ARROW_DEFAULT_MEMORY_POOL'] = 'system'
383
+ os.environ["ARROW_DEFAULT_MEMORY_POOL"] = "system"
357
384
  except Exception:
358
385
  pass
359
386
 
@@ -368,20 +395,18 @@ if __name__ == '__main__':
368
395
  elif environment != "local":
369
396
  try:
370
397
  aws_meta_data = get_aws_meta_data()
371
- config.update({
372
- 'aws_meta_data': aws_meta_data
373
- })
398
+ config.update({"aws_meta_data": aws_meta_data})
374
399
  except Exception:
375
400
  pass
376
401
 
377
- apis = os.getenv('MINDSDB_APIS') or config.cmd_args.api
402
+ apis = os.getenv("MINDSDB_APIS") or config.cmd_args.api
378
403
 
379
404
  if apis is None: # If "--api" option is not specified, start the default APIs
380
405
  api_arr = [TrunkProcessEnum.HTTP, TrunkProcessEnum.MYSQL]
381
406
  elif apis == "": # If "--api=" (blank) is specified, don't start any APIs
382
407
  api_arr = []
383
408
  else: # The user has provided a list of APIs to start
384
- api_arr = [TrunkProcessEnum(name) for name in apis.split(',')]
409
+ api_arr = [TrunkProcessEnum(name) for name in apis.split(",")]
385
410
 
386
411
  logger.info(f"Version: {mindsdb_version}")
387
412
  logger.info(f"Configuration file: {config.config_path or 'absent'}")
@@ -396,6 +421,7 @@ if __name__ == '__main__':
396
421
  logger.debug("Applying database migrations")
397
422
  try:
398
423
  from mindsdb.migrations import migrate
424
+
399
425
  migrate.migrate_to_head()
400
426
  except Exception as e:
401
427
  logger.error(f"Error! Something went wrong during DB migrations: {e}")
@@ -410,10 +436,11 @@ if __name__ == '__main__':
410
436
  clean_process_marks()
411
437
 
412
438
  # Get config values for APIs
413
- http_api_config = config.get('api', {}).get('http', {})
414
- mysql_api_config = config.get('api', {}).get('mysql', {})
415
- mcp_api_config = config.get('api', {}).get('mcp', {})
416
- litellm_api_config = config.get('api', {}).get('litellm', {})
439
+ http_api_config = config.get("api", {}).get("http", {})
440
+ mysql_api_config = config.get("api", {}).get("mysql", {})
441
+ mcp_api_config = config.get("api", {}).get("mcp", {})
442
+ litellm_api_config = config.get("api", {}).get("litellm", {})
443
+ a2a_api_config = config.get("a2a", {})
417
444
  trunc_processes_struct = {
418
445
  TrunkProcessEnum.HTTP: TrunkProcessData(
419
446
  name=TrunkProcessEnum.HTTP.value,
@@ -469,6 +496,7 @@ if __name__ == '__main__':
469
496
  entrypoint=start_mcp,
470
497
  port=mcp_api_config.get('port', 47337),
471
498
  args=(config.cmd_args.verbose,),
499
+ need_to_run=mcp_api_config.get('need_to_run', False),
472
500
  restart_on_failure=mcp_api_config.get('restart_on_failure', False),
473
501
  max_restart_count=mcp_api_config.get('max_restart_count', TrunkProcessData.max_restart_count),
474
502
  max_restart_interval_seconds=mcp_api_config.get(
@@ -485,6 +513,20 @@ if __name__ == '__main__':
485
513
  max_restart_interval_seconds=litellm_api_config.get(
486
514
  'max_restart_interval_seconds', TrunkProcessData.max_restart_interval_seconds
487
515
  )
516
+ ),
517
+ TrunkProcessEnum.A2A: TrunkProcessData(
518
+ name=TrunkProcessEnum.A2A.value,
519
+ entrypoint=start_a2a,
520
+ port=a2a_api_config.get('port', 8001),
521
+ args=(config.cmd_args.verbose,),
522
+ need_to_run=a2a_api_config.get('enabled', False),
523
+ restart_on_failure=a2a_api_config.get('restart_on_failure', True),
524
+ max_restart_count=a2a_api_config.get(
525
+ 'max_restart_count', TrunkProcessData.max_restart_count
526
+ ),
527
+ max_restart_interval_seconds=a2a_api_config.get(
528
+ 'max_restart_interval_seconds', TrunkProcessData.max_restart_interval_seconds
529
+ )
488
530
  )
489
531
  }
490
532
 
@@ -494,17 +536,20 @@ if __name__ == '__main__':
494
536
  else:
495
537
  logger.error(f"ERROR: {api_enum} API is not a valid api in config")
496
538
 
497
- if config['jobs']['disable'] is False:
539
+ if config["jobs"]["disable"] is False:
498
540
  trunc_processes_struct[TrunkProcessEnum.JOBS].need_to_run = True
499
541
 
500
- if config['tasks']['disable'] is False:
542
+ if config["tasks"]["disable"] is False:
501
543
  trunc_processes_struct[TrunkProcessEnum.TASKS].need_to_run = True
502
544
 
503
545
  if config.cmd_args.ml_task_queue_consumer is True:
504
546
  trunc_processes_struct[TrunkProcessEnum.ML_TASK_QUEUE].need_to_run = True
505
547
 
506
548
  for trunc_process_data in trunc_processes_struct.values():
507
- if trunc_process_data.started is True or trunc_process_data.need_to_run is False:
549
+ if (
550
+ trunc_process_data.started is True
551
+ or trunc_process_data.need_to_run is False
552
+ ):
508
553
  continue
509
554
  start_process(trunc_process_data)
510
555
 
@@ -524,10 +569,11 @@ if __name__ == '__main__':
524
569
  wait_api_start(
525
570
  trunc_process_data.name,
526
571
  trunc_process_data.process.pid,
527
- trunc_process_data.port
572
+ trunc_process_data.port,
528
573
  )
529
574
  for trunc_process_data in trunc_processes_struct.values()
530
- if trunc_process_data.port is not None and trunc_process_data.need_to_run is True
575
+ if trunc_process_data.port is not None
576
+ and trunc_process_data.need_to_run is True
531
577
  ]
532
578
  for future in asyncio.as_completed(futures):
533
579
  api_name, port, started = await future
@@ -550,7 +596,9 @@ if __name__ == '__main__':
550
596
  finally:
551
597
  if trunc_process_data.should_restart:
552
598
  if trunc_process_data.request_restart_attempt():
553
- logger.warning(f"{trunc_process_data.name} API: stopped unexpectedly, restarting")
599
+ logger.warning(
600
+ f"{trunc_process_data.name} API: stopped unexpectedly, restarting"
601
+ )
554
602
  trunc_process_data.process = None
555
603
  if trunc_process_data.name == TrunkProcessEnum.HTTP.value:
556
604
  # do not open GUI on HTTP API restart
@@ -559,7 +607,7 @@ if __name__ == '__main__':
559
607
  api_name, port, started = await wait_api_start(
560
608
  trunc_process_data.name,
561
609
  trunc_process_data.process.pid,
562
- trunc_process_data.port
610
+ trunc_process_data.port,
563
611
  )
564
612
  if started:
565
613
  logger.info(f"{api_name} API: started on {port}")
@@ -569,7 +617,7 @@ if __name__ == '__main__':
569
617
  finish = True
570
618
  logger.error(
571
619
  f'The "{trunc_process_data.name}" process could not restart after failure. '
572
- 'There will be no further attempts to restart.'
620
+ "There will be no further attempts to restart."
573
621
  )
574
622
  else:
575
623
  finish = True
@@ -582,13 +630,13 @@ if __name__ == '__main__':
582
630
  for trunc_process_data in trunc_processes_struct.values()
583
631
  if trunc_process_data.need_to_run is True
584
632
  ],
585
- return_exceptions=False
633
+ return_exceptions=False,
586
634
  )
587
635
 
588
636
  ioloop = asyncio.new_event_loop()
589
637
  ioloop.run_until_complete(wait_apis_start())
590
638
 
591
- threading.Thread(target=do_clean_process_marks, name='clean_process_marks').start()
639
+ threading.Thread(target=do_clean_process_marks, name="clean_process_marks").start()
592
640
 
593
641
  ioloop.run_until_complete(gather_apis())
594
642
  ioloop.close()
File without changes
@@ -0,0 +1,114 @@
1
+ import sys
2
+ import logging
3
+ import click
4
+ from dotenv import load_dotenv
5
+
6
+ # A2A specific imports
7
+ from .common.types import (
8
+ AgentCard,
9
+ AgentCapabilities,
10
+ AgentSkill,
11
+ MissingAPIKeyError,
12
+ )
13
+ from .common.server.server import A2AServer
14
+ from .task_manager import AgentTaskManager
15
+ from .agent import MindsDBAgent
16
+
17
+ logger = logging.getLogger(__name__)
18
+ logging.basicConfig(
19
+ level=logging.INFO,
20
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
21
+ )
22
+
23
+
24
+ @click.command()
25
+ @click.option("--host", default="localhost", help="A2A server host")
26
+ @click.option("--port", default=10002, help="A2A server port", type=int)
27
+ @click.option("--mindsdb-host", default="localhost", help="MindsDB server host")
28
+ @click.option("--mindsdb-port", default=47334, help="MindsDB server port", type=int)
29
+ @click.option("--project-name", default="mindsdb", help="MindsDB project name")
30
+ @click.option(
31
+ "--log-level",
32
+ default="INFO",
33
+ help="Logging level (DEBUG, INFO, WARNING, ERROR)",
34
+ )
35
+ def main(
36
+ host: str,
37
+ port: int,
38
+ mindsdb_host: str,
39
+ mindsdb_port: int,
40
+ project_name: str,
41
+ log_level: str,
42
+ ):
43
+ """Entry-point that starts an A2A compliant server which forwards tasks to an existing MindsDB agent."""
44
+
45
+ # Configure logging level
46
+ logging.getLogger().setLevel(getattr(logging, log_level.upper(), logging.INFO))
47
+
48
+ # Load .env if present
49
+ load_dotenv()
50
+
51
+ try:
52
+ logger.info(
53
+ "Starting MindsDB A2A connector on http://%s:%s (project=%s)",
54
+ host,
55
+ port,
56
+ project_name,
57
+ )
58
+
59
+ # --- 1. Prepare A2A artefacts (agent card & task-manager) --------------
60
+ capabilities = AgentCapabilities(streaming=True)
61
+ skill = AgentSkill(
62
+ id="mindsdb_query",
63
+ name="MindsDB Query",
64
+ description="Executes natural-language queries via MindsDB agents.",
65
+ tags=["database", "mindsdb", "query", "analytics"],
66
+ examples=[
67
+ "What trends exist in my sales data?",
68
+ "Generate insights from the support tickets dataset.",
69
+ ],
70
+ inputModes=MindsDBAgent.SUPPORTED_CONTENT_TYPES,
71
+ outputModes=MindsDBAgent.SUPPORTED_CONTENT_TYPES,
72
+ )
73
+
74
+ agent_card = AgentCard(
75
+ name="MindsDB Agent Connector",
76
+ description=(
77
+ "A2A connector that proxies requests to MindsDB agents "
78
+ f"in project '{project_name}'."
79
+ ),
80
+ url=f"http://{host}:{port}",
81
+ version="1.0.0",
82
+ defaultInputModes=MindsDBAgent.SUPPORTED_CONTENT_TYPES,
83
+ defaultOutputModes=MindsDBAgent.SUPPORTED_CONTENT_TYPES,
84
+ capabilities=capabilities,
85
+ skills=[skill],
86
+ )
87
+
88
+ task_manager = AgentTaskManager(
89
+ project_name=project_name,
90
+ mindsdb_host=mindsdb_host,
91
+ mindsdb_port=mindsdb_port,
92
+ )
93
+
94
+ # --- 2. Start A2A server ----------------------------------------------
95
+ logger.info("Starting A2A server…")
96
+ server = A2AServer(
97
+ agent_card=agent_card,
98
+ task_manager=task_manager,
99
+ host=host,
100
+ port=port,
101
+ endpoint="/a2a", # Keep the same route used by the client
102
+ )
103
+ server.start()
104
+
105
+ except MissingAPIKeyError as exc:
106
+ logger.error("Authentication error: %s", exc)
107
+ sys.exit(1)
108
+ except Exception as exc: # noqa: BLE001
109
+ logger.exception("Unexpected error: %s", exc)
110
+ sys.exit(1)
111
+
112
+
113
+ if __name__ == "__main__":
114
+ main()