MindsDB 25.5.3.0__py3-none-any.whl → 25.5.4.1__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 (313) hide show
  1. mindsdb/__about__.py +8 -8
  2. mindsdb/__main__.py +127 -79
  3. mindsdb/api/a2a/__init__.py +0 -0
  4. mindsdb/api/a2a/__main__.py +144 -0
  5. mindsdb/api/a2a/agent.py +308 -0
  6. mindsdb/api/a2a/common/__init__.py +0 -0
  7. mindsdb/api/a2a/common/server/__init__.py +4 -0
  8. mindsdb/api/a2a/common/server/server.py +164 -0
  9. mindsdb/api/a2a/common/server/task_manager.py +287 -0
  10. mindsdb/api/a2a/common/server/utils.py +28 -0
  11. mindsdb/api/a2a/common/types.py +365 -0
  12. mindsdb/api/a2a/constants.py +9 -0
  13. mindsdb/api/a2a/run_a2a.py +86 -0
  14. mindsdb/api/a2a/task_manager.py +560 -0
  15. mindsdb/api/executor/command_executor.py +185 -309
  16. mindsdb/api/executor/datahub/classes/response.py +5 -2
  17. mindsdb/api/executor/datahub/datanodes/integration_datanode.py +39 -72
  18. mindsdb/api/executor/planner/query_planner.py +10 -1
  19. mindsdb/api/executor/sql_query/result_set.py +185 -52
  20. mindsdb/api/executor/sql_query/sql_query.py +1 -1
  21. mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +9 -12
  22. mindsdb/api/executor/sql_query/steps/fetch_dataframe.py +8 -10
  23. mindsdb/api/executor/sql_query/steps/fetch_dataframe_partition.py +5 -44
  24. mindsdb/api/executor/sql_query/steps/insert_step.py +24 -15
  25. mindsdb/api/executor/sql_query/steps/join_step.py +1 -1
  26. mindsdb/api/executor/sql_query/steps/project_step.py +1 -1
  27. mindsdb/api/executor/sql_query/steps/sql_steps.py +1 -1
  28. mindsdb/api/executor/sql_query/steps/subselect_step.py +4 -8
  29. mindsdb/api/executor/sql_query/steps/union_step.py +1 -3
  30. mindsdb/api/http/initialize.py +99 -83
  31. mindsdb/api/http/namespaces/analysis.py +3 -3
  32. mindsdb/api/http/namespaces/config.py +61 -86
  33. mindsdb/api/http/namespaces/file.py +8 -2
  34. mindsdb/api/http/namespaces/sql.py +13 -27
  35. mindsdb/api/mcp/start.py +42 -5
  36. mindsdb/api/mysql/mysql_proxy/data_types/mysql_packet.py +0 -1
  37. mindsdb/api/mysql/mysql_proxy/data_types/mysql_packets/binary_resultset_row_package.py +52 -19
  38. mindsdb/api/mysql/mysql_proxy/executor/mysql_executor.py +8 -10
  39. mindsdb/api/mysql/mysql_proxy/libs/constants/mysql.py +54 -38
  40. mindsdb/api/mysql/mysql_proxy/mysql_proxy.py +82 -115
  41. mindsdb/api/mysql/mysql_proxy/utilities/dump.py +351 -0
  42. mindsdb/api/postgres/postgres_proxy/executor/executor.py +1 -1
  43. mindsdb/api/postgres/postgres_proxy/postgres_proxy.py +5 -6
  44. mindsdb/integrations/handlers/altibase_handler/altibase_handler.py +26 -27
  45. mindsdb/integrations/handlers/altibase_handler/connection_args.py +13 -13
  46. mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler.py +8 -8
  47. mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler_dsn.py +13 -13
  48. mindsdb/integrations/handlers/anthropic_handler/__init__.py +2 -2
  49. mindsdb/integrations/handlers/anthropic_handler/anthropic_handler.py +1 -3
  50. mindsdb/integrations/handlers/aurora_handler/aurora_handler.py +1 -0
  51. mindsdb/integrations/handlers/autosklearn_handler/autosklearn_handler.py +1 -1
  52. mindsdb/integrations/handlers/autosklearn_handler/config.py +0 -1
  53. mindsdb/integrations/handlers/bigquery_handler/bigquery_handler.py +1 -1
  54. mindsdb/integrations/handlers/bigquery_handler/tests/test_bigquery_handler.py +1 -1
  55. mindsdb/integrations/handlers/binance_handler/binance_handler.py +1 -0
  56. mindsdb/integrations/handlers/binance_handler/binance_tables.py +3 -4
  57. mindsdb/integrations/handlers/byom_handler/__init__.py +0 -1
  58. mindsdb/integrations/handlers/byom_handler/requirements.txt +1 -2
  59. mindsdb/integrations/handlers/ckan_handler/ckan_handler.py +3 -0
  60. mindsdb/integrations/handlers/clickhouse_handler/__init__.py +1 -1
  61. mindsdb/integrations/handlers/cloud_spanner_handler/tests/test_cloud_spanner_handler.py +0 -2
  62. mindsdb/integrations/handlers/cloud_sql_handler/cloud_sql_handler.py +0 -1
  63. mindsdb/integrations/handlers/cohere_handler/__init__.py +1 -1
  64. mindsdb/integrations/handlers/cohere_handler/cohere_handler.py +11 -13
  65. mindsdb/integrations/handlers/confluence_handler/confluence_tables.py +6 -0
  66. mindsdb/integrations/handlers/databend_handler/connection_args.py +1 -1
  67. mindsdb/integrations/handlers/databend_handler/databend_handler.py +4 -4
  68. mindsdb/integrations/handlers/databend_handler/tests/__init__.py +0 -1
  69. mindsdb/integrations/handlers/databend_handler/tests/test_databend_handler.py +1 -1
  70. mindsdb/integrations/handlers/derby_handler/connection_args.py +1 -1
  71. mindsdb/integrations/handlers/derby_handler/derby_handler.py +14 -22
  72. mindsdb/integrations/handlers/derby_handler/tests/test_derby_handler.py +6 -6
  73. mindsdb/integrations/handlers/discord_handler/discord_handler.py +5 -5
  74. mindsdb/integrations/handlers/discord_handler/discord_tables.py +3 -3
  75. mindsdb/integrations/handlers/discord_handler/tests/test_discord.py +5 -3
  76. mindsdb/integrations/handlers/dockerhub_handler/dockerhub.py +3 -3
  77. mindsdb/integrations/handlers/dockerhub_handler/dockerhub_handler.py +2 -2
  78. mindsdb/integrations/handlers/dockerhub_handler/dockerhub_tables.py +57 -54
  79. mindsdb/integrations/handlers/dremio_handler/__init__.py +2 -2
  80. mindsdb/integrations/handlers/druid_handler/__init__.py +1 -1
  81. mindsdb/integrations/handlers/druid_handler/druid_handler.py +2 -2
  82. mindsdb/integrations/handlers/edgelessdb_handler/tests/test_edgelessdb_handler.py +9 -9
  83. mindsdb/integrations/handlers/email_handler/email_client.py +1 -1
  84. mindsdb/integrations/handlers/email_handler/email_ingestor.py +1 -1
  85. mindsdb/integrations/handlers/email_handler/email_tables.py +0 -1
  86. mindsdb/integrations/handlers/email_handler/settings.py +0 -1
  87. mindsdb/integrations/handlers/eventstoredb_handler/eventstoredb_handler.py +2 -1
  88. mindsdb/integrations/handlers/firebird_handler/firebird_handler.py +1 -1
  89. mindsdb/integrations/handlers/flaml_handler/flaml_handler.py +9 -9
  90. mindsdb/integrations/handlers/frappe_handler/frappe_client.py +5 -5
  91. mindsdb/integrations/handlers/frappe_handler/frappe_handler.py +6 -5
  92. mindsdb/integrations/handlers/frappe_handler/frappe_tables.py +2 -2
  93. mindsdb/integrations/handlers/github_handler/connection_args.py +2 -2
  94. mindsdb/integrations/handlers/github_handler/github_handler.py +1 -8
  95. mindsdb/integrations/handlers/github_handler/github_tables.py +13 -24
  96. mindsdb/integrations/handlers/gitlab_handler/gitlab_handler.py +2 -1
  97. mindsdb/integrations/handlers/gitlab_handler/gitlab_tables.py +1 -4
  98. mindsdb/integrations/handlers/gmail_handler/gmail_handler.py +6 -13
  99. mindsdb/integrations/handlers/google_books_handler/google_books_handler.py +2 -1
  100. mindsdb/integrations/handlers/google_books_handler/google_books_tables.py +0 -3
  101. mindsdb/integrations/handlers/google_calendar_handler/google_calendar_handler.py +4 -4
  102. mindsdb/integrations/handlers/google_calendar_handler/google_calendar_tables.py +2 -6
  103. mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_handler.py +3 -2
  104. mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_tables.py +0 -3
  105. mindsdb/integrations/handlers/google_fit_handler/google_fit_handler.py +10 -12
  106. mindsdb/integrations/handlers/google_fit_handler/google_fit_tables.py +11 -13
  107. mindsdb/integrations/handlers/google_search_handler/google_search_handler.py +2 -1
  108. mindsdb/integrations/handlers/google_search_handler/google_search_tables.py +0 -3
  109. mindsdb/integrations/handlers/groq_handler/__init__.py +3 -3
  110. mindsdb/integrations/handlers/hackernews_handler/hn_handler.py +5 -7
  111. mindsdb/integrations/handlers/hackernews_handler/hn_table.py +6 -7
  112. mindsdb/integrations/handlers/hive_handler/tests/test_hive_handler.py +1 -1
  113. mindsdb/integrations/handlers/hsqldb_handler/connection_args.py +6 -6
  114. mindsdb/integrations/handlers/hsqldb_handler/hsqldb_handler.py +4 -3
  115. mindsdb/integrations/handlers/huggingface_api_handler/exceptions.py +1 -1
  116. mindsdb/integrations/handlers/huggingface_api_handler/huggingface_api_handler.py +1 -8
  117. mindsdb/integrations/handlers/huggingface_handler/huggingface_handler.py +6 -6
  118. mindsdb/integrations/handlers/huggingface_handler/requirements.txt +1 -1
  119. mindsdb/integrations/handlers/huggingface_handler/requirements_cpu.txt +1 -1
  120. mindsdb/integrations/handlers/ignite_handler/ignite_handler.py +2 -1
  121. mindsdb/integrations/handlers/impala_handler/impala_handler.py +9 -12
  122. mindsdb/integrations/handlers/impala_handler/tests/test_impala_handler.py +11 -11
  123. mindsdb/integrations/handlers/influxdb_handler/influxdb_handler.py +10 -13
  124. mindsdb/integrations/handlers/influxdb_handler/influxdb_tables.py +20 -20
  125. mindsdb/integrations/handlers/informix_handler/__about__.py +8 -8
  126. mindsdb/integrations/handlers/informix_handler/__init__.py +12 -5
  127. mindsdb/integrations/handlers/informix_handler/informix_handler.py +99 -133
  128. mindsdb/integrations/handlers/informix_handler/tests/test_informix_handler.py +13 -11
  129. mindsdb/integrations/handlers/ingres_handler/__about__.py +0 -1
  130. mindsdb/integrations/handlers/ingres_handler/ingres_handler.py +1 -0
  131. mindsdb/integrations/handlers/jira_handler/jira_handler.py +4 -4
  132. mindsdb/integrations/handlers/jira_handler/jira_tables.py +9 -9
  133. mindsdb/integrations/handlers/kinetica_handler/__init__.py +0 -1
  134. mindsdb/integrations/handlers/lancedb_handler/requirements.txt +0 -1
  135. mindsdb/integrations/handlers/langchain_handler/langchain_handler.py +4 -4
  136. mindsdb/integrations/handlers/langchain_handler/tools.py +9 -10
  137. mindsdb/integrations/handlers/leonardoai_handler/__init__.py +1 -1
  138. mindsdb/integrations/handlers/lightwood_handler/functions.py +2 -2
  139. mindsdb/integrations/handlers/lightwood_handler/lightwood_handler.py +0 -1
  140. mindsdb/integrations/handlers/lightwood_handler/tests/test_lightwood_handler.py +11 -11
  141. mindsdb/integrations/handlers/litellm_handler/litellm_handler.py +37 -20
  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/llm/config.py +13 -0
  279. mindsdb/integrations/libs/llm/utils.py +37 -65
  280. mindsdb/integrations/libs/response.py +67 -52
  281. mindsdb/integrations/libs/vectordatabase_handler.py +6 -0
  282. mindsdb/integrations/utilities/handler_utils.py +15 -3
  283. mindsdb/integrations/utilities/handlers/api_utilities/__init__.py +0 -1
  284. mindsdb/integrations/utilities/handlers/auth_utilities/__init__.py +0 -2
  285. mindsdb/integrations/utilities/rag/rerankers/base_reranker.py +230 -227
  286. mindsdb/integrations/utilities/utils.py +3 -3
  287. mindsdb/interfaces/agents/agents_controller.py +164 -1
  288. mindsdb/interfaces/agents/constants.py +32 -13
  289. mindsdb/interfaces/agents/langchain_agent.py +106 -95
  290. mindsdb/interfaces/agents/mindsdb_database_agent.py +101 -2
  291. mindsdb/interfaces/knowledge_base/controller.py +250 -216
  292. mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +13 -10
  293. mindsdb/interfaces/knowledge_base/preprocessing/json_chunker.py +434 -0
  294. mindsdb/interfaces/knowledge_base/preprocessing/models.py +54 -0
  295. mindsdb/interfaces/query_context/context_controller.py +66 -10
  296. mindsdb/interfaces/skills/custom/text2sql/mindsdb_kb_tools.py +190 -0
  297. mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +92 -0
  298. mindsdb/interfaces/skills/skill_tool.py +202 -57
  299. mindsdb/interfaces/skills/sql_agent.py +205 -17
  300. mindsdb/interfaces/storage/fs.py +1 -0
  301. mindsdb/interfaces/variables/__init__.py +0 -0
  302. mindsdb/interfaces/variables/variables_controller.py +97 -0
  303. mindsdb/migrations/env.py +5 -7
  304. mindsdb/migrations/migrate.py +47 -7
  305. mindsdb/migrations/versions/2025-05-21_9f150e4f9a05_checkpoint_1.py +360 -0
  306. mindsdb/utilities/config.py +287 -216
  307. mindsdb/utilities/starters.py +13 -0
  308. {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.1.dist-info}/METADATA +646 -698
  309. {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.1.dist-info}/RECORD +312 -295
  310. {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.1.dist-info}/WHEEL +1 -1
  311. mindsdb/integrations/handlers/monkeylearn_handler/requirements.txt +0 -1
  312. {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.1.dist-info}/licenses/LICENSE +0 -0
  313. {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.1.dist-info}/top_level.txt +0 -0
@@ -11,10 +11,8 @@ import pandas as pd
11
11
  from langchain.agents import AgentExecutor
12
12
  from langchain.agents.initialize import initialize_agent
13
13
  from langchain.chains.conversation.memory import ConversationSummaryBufferMemory
14
- from langchain_community.chat_models import (
15
- ChatAnyscale,
16
- ChatLiteLLM,
17
- ChatOllama)
14
+ from langchain_community.chat_models import ChatAnyscale, ChatLiteLLM, ChatOllama
15
+ from langchain_writer import ChatWriter
18
16
  from langchain_google_genai import ChatGoogleGenerativeAI
19
17
  from langchain_core.agents import AgentAction, AgentStep
20
18
  from langchain_core.callbacks.base import BaseCallbackHandler
@@ -27,7 +25,9 @@ from langchain_core.tools import Tool
27
25
  from mindsdb.integrations.libs.llm.utils import get_llm_config
28
26
  from mindsdb.integrations.utilities.handler_utils import get_api_key
29
27
  from mindsdb.integrations.utilities.rag.settings import DEFAULT_RAG_PROMPT_TEMPLATE
30
- from mindsdb.interfaces.agents.event_dispatch_callback_handler import EventDispatchCallbackHandler
28
+ from mindsdb.interfaces.agents.event_dispatch_callback_handler import (
29
+ EventDispatchCallbackHandler,
30
+ )
31
31
  from mindsdb.interfaces.agents.constants import AGENT_CHUNK_POLLING_INTERVAL_SECONDS
32
32
  from mindsdb.utilities import log
33
33
  from mindsdb.utilities.context_executor import ContextThreadPoolExecutor
@@ -54,7 +54,10 @@ from mindsdb.interfaces.agents.constants import (
54
54
  NVIDIA_NIM_CHAT_MODELS,
55
55
  USER_COLUMN,
56
56
  ASSISTANT_COLUMN,
57
- CONTEXT_COLUMN, TRACE_ID_COLUMN
57
+ CONTEXT_COLUMN,
58
+ TRACE_ID_COLUMN,
59
+ DEFAULT_AGENT_SYSTEM_PROMPT,
60
+ WRITER_CHAT_MODELS,
58
61
  )
59
62
  from mindsdb.interfaces.skills.skill_tool import skill_tool, SkillData
60
63
  from langchain_anthropic import ChatAnthropic
@@ -87,6 +90,9 @@ def get_llm_provider(args: Dict) -> str:
87
90
  return "nvidia_nim"
88
91
  if args["model_name"] in GOOGLE_GEMINI_CHAT_MODELS:
89
92
  return "google"
93
+ # Check for writer models
94
+ if args["model_name"] in WRITER_CHAT_MODELS:
95
+ return "writer"
90
96
 
91
97
  # For vLLM, require explicit provider specification
92
98
  raise ValueError("Invalid model name. Please define a supported llm provider")
@@ -100,21 +106,21 @@ def get_embedding_model_provider(args: Dict) -> str:
100
106
  # Check for explicit embedding model provider
101
107
  if "embedding_model_provider" in args:
102
108
  provider = args["embedding_model_provider"]
103
- if provider == 'vllm':
104
- if not (args.get('openai_api_base') and args.get('model')):
109
+ if provider == "vllm":
110
+ if not (args.get("openai_api_base") and args.get("model")):
105
111
  raise ValueError(
106
112
  "VLLM embeddings configuration error:\n"
107
113
  "- Missing required parameters: 'openai_api_base' and/or 'model'\n"
108
114
  "- Example: openai_api_base='http://localhost:8003/v1', model='your-model-name'"
109
115
  )
110
116
  logger.info("Using custom VLLMEmbeddings class")
111
- return 'vllm'
117
+ return "vllm"
112
118
  return provider
113
119
 
114
120
  # Check if LLM provider is vLLM
115
- llm_provider = args.get('provider', DEFAULT_EMBEDDINGS_MODEL_PROVIDER)
116
- if llm_provider == 'vllm':
117
- if not (args.get('openai_api_base') and args.get('model')):
121
+ llm_provider = args.get("provider", DEFAULT_EMBEDDINGS_MODEL_PROVIDER)
122
+ if llm_provider == "vllm":
123
+ if not (args.get("openai_api_base") and args.get("model")):
118
124
  raise ValueError(
119
125
  "VLLM embeddings configuration error:\n"
120
126
  "- Missing required parameters: 'openai_api_base' and/or 'model'\n"
@@ -122,7 +128,7 @@ def get_embedding_model_provider(args: Dict) -> str:
122
128
  "- Example: openai_api_base='http://localhost:8003/v1', model='your-model-name'"
123
129
  )
124
130
  logger.info("Using custom VLLMEmbeddings class")
125
- return 'vllm'
131
+ return "vllm"
126
132
 
127
133
  # Default to LLM provider
128
134
  return llm_provider
@@ -131,14 +137,15 @@ def get_embedding_model_provider(args: Dict) -> str:
131
137
  def get_chat_model_params(args: Dict) -> Dict:
132
138
  model_config = args.copy()
133
139
  # Include API keys.
134
- model_config["api_keys"] = {
135
- p: get_api_key(p, model_config, None, strict=False) for p in SUPPORTED_PROVIDERS
136
- }
137
- llm_config = get_llm_config(
138
- args.get("provider", get_llm_provider(args)), model_config
139
- )
140
- config_dict = llm_config.model_dump()
140
+ model_config["api_keys"] = {p: get_api_key(p, model_config, None, strict=False) for p in SUPPORTED_PROVIDERS}
141
+ llm_config = get_llm_config(args.get("provider", get_llm_provider(args)), model_config)
142
+ config_dict = llm_config.model_dump(by_alias=True)
141
143
  config_dict = {k: v for k, v in config_dict.items() if v is not None}
144
+
145
+ # If provider is writer, ensure the API key is passed as 'api_key'
146
+ if args.get("provider") == "writer" and "writer_api_key" in config_dict:
147
+ config_dict["api_key"] = config_dict.pop("writer_api_key")
148
+
142
149
  return config_dict
143
150
 
144
151
 
@@ -166,20 +173,26 @@ def create_chat_model(args: Dict):
166
173
  return ChatNVIDIA(**model_kwargs)
167
174
  if args["provider"] == "google":
168
175
  return ChatGoogleGenerativeAI(**model_kwargs)
176
+ if args["provider"] == "writer":
177
+ return ChatWriter(**model_kwargs)
169
178
  if args["provider"] == "mindsdb":
170
179
  return ChatMindsdb(**model_kwargs)
171
- raise ValueError(f'Unknown provider: {args["provider"]}')
180
+ raise ValueError(f"Unknown provider: {args['provider']}")
172
181
 
173
182
 
174
183
  def prepare_prompts(df, base_template, input_variables, user_column=USER_COLUMN):
175
184
  empty_prompt_ids = np.where(df[input_variables].isna().all(axis=1).values)[0]
176
- base_template = base_template.replace('{{', '{').replace('}}', '}')
185
+
186
+ # Combine system prompt with user-provided template
187
+ base_template = f"{DEFAULT_AGENT_SYSTEM_PROMPT}\n\n{base_template}"
188
+
189
+ base_template = base_template.replace("{{", "{").replace("}}", "}")
177
190
  prompts = []
178
191
 
179
192
  for i, row in df.iterrows():
180
193
  if i not in empty_prompt_ids:
181
194
  prompt = PromptTemplate(input_variables=input_variables, template=base_template)
182
- kwargs = {col: row[col] if row[col] is not None else '' for col in input_variables}
195
+ kwargs = {col: row[col] if row[col] is not None else "" for col in input_variables}
183
196
  prompts.append(prompt.format(**kwargs))
184
197
  elif row.get(user_column):
185
198
  prompts.append(row[user_column])
@@ -194,8 +207,9 @@ def prepare_callbacks(self, args):
194
207
  return callbacks, context_callback
195
208
 
196
209
 
197
- def handle_agent_error(e):
198
- error_message = f"An error occurred during agent execution: {str(e)}"
210
+ def handle_agent_error(e, error_message=None):
211
+ if error_message is None:
212
+ error_message = f"An error occurred during agent execution: {str(e)}"
199
213
  logger.error(error_message, exc_info=True)
200
214
  return error_message
201
215
 
@@ -212,9 +226,7 @@ def process_chunk(chunk):
212
226
 
213
227
 
214
228
  class LangchainAgent:
215
-
216
229
  def __init__(self, agent: db.Agents, model: dict = None):
217
-
218
230
  self.agent = agent
219
231
  self.model = model
220
232
 
@@ -237,18 +249,14 @@ class LangchainAgent:
237
249
  args = self.agent.params.copy()
238
250
  args["model_name"] = self.agent.model_name
239
251
  args["provider"] = self.agent.provider
240
- args["embedding_model_provider"] = args.get(
241
- "embedding_model", get_embedding_model_provider(args)
242
- )
252
+ args["embedding_model_provider"] = args.get("embedding_model", get_embedding_model_provider(args))
243
253
 
244
254
  # agent is using current langchain model
245
255
  if self.agent.provider == "mindsdb":
246
256
  args["model_name"] = self.agent.model_name
247
257
 
248
258
  # get prompt
249
- prompt_template = (
250
- self.model["problem_definition"].get("using", {}).get("prompt_template")
251
- )
259
+ prompt_template = self.model["problem_definition"].get("using", {}).get("prompt_template")
252
260
  if prompt_template is not None:
253
261
  # only update prompt_template if it is set on the model
254
262
  args["prompt_template"] = prompt_template
@@ -257,24 +265,23 @@ class LangchainAgent:
257
265
  if args.get("mode") == "retrieval":
258
266
  args["prompt_template"] = DEFAULT_RAG_PROMPT_TEMPLATE
259
267
  else:
260
- raise ValueError(
261
- "Please provide a `prompt_template` or set `mode=retrieval`"
262
- )
268
+ raise ValueError("Please provide a `prompt_template` or set `mode=retrieval`")
263
269
 
264
270
  return args
265
271
 
266
272
  def get_metadata(self) -> Dict:
267
273
  return {
268
- 'provider': self.provider,
269
- 'model_name': self.args["model_name"],
270
- 'embedding_model_provider': self.args.get('embedding_model_provider',
271
- get_embedding_model_provider(self.args)),
272
- 'skills': get_skills(self.agent),
273
- 'user_id': ctx.user_id,
274
- 'session_id': ctx.session_id,
275
- 'company_id': ctx.company_id,
276
- 'user_class': ctx.user_class,
277
- 'email_confirmed': ctx.email_confirmed
274
+ "provider": self.provider,
275
+ "model_name": self.args["model_name"],
276
+ "embedding_model_provider": self.args.get(
277
+ "embedding_model_provider", get_embedding_model_provider(self.args)
278
+ ),
279
+ "skills": get_skills(self.agent),
280
+ "user_id": ctx.user_id,
281
+ "session_id": ctx.session_id,
282
+ "company_id": ctx.company_id,
283
+ "user_class": ctx.user_class,
284
+ "email_confirmed": ctx.email_confirmed,
278
285
  }
279
286
 
280
287
  def get_tags(self) -> List:
@@ -283,14 +290,13 @@ class LangchainAgent:
283
290
  ]
284
291
 
285
292
  def get_completion(self, messages, stream: bool = False):
286
-
287
293
  # Get metadata and tags to be used in the trace
288
294
  metadata = self.get_metadata()
289
295
  tags = self.get_tags()
290
296
 
291
297
  # Set up trace for the API completion in Langfuse
292
298
  self.langfuse_client_wrapper.setup_trace(
293
- name='api-completion',
299
+ name="api-completion",
294
300
  input=messages,
295
301
  tags=tags,
296
302
  metadata=metadata,
@@ -299,9 +305,7 @@ class LangchainAgent:
299
305
  )
300
306
 
301
307
  # Set up trace for the run completion in Langfuse
302
- self.run_completion_span = self.langfuse_client_wrapper.start_span(
303
- name='run-completion',
304
- input=messages)
308
+ self.run_completion_span = self.langfuse_client_wrapper.start_span(name="run-completion", input=messages)
305
309
 
306
310
  if stream:
307
311
  return self._get_completion_stream(messages)
@@ -339,7 +343,7 @@ class LangchainAgent:
339
343
 
340
344
  df = pd.DataFrame(messages)
341
345
 
342
- self.embedding_model_provider = args.get('embedding_model_provider', get_embedding_model_provider(args))
346
+ self.embedding_model_provider = args.get("embedding_model_provider", get_embedding_model_provider(args))
343
347
  # Back compatibility for old models
344
348
  self.provider = args.get("provider", get_llm_provider(args))
345
349
 
@@ -392,7 +396,7 @@ class LangchainAgent:
392
396
  agent=agent_type,
393
397
  # Use custom output parser to handle flaky LLMs that don't ALWAYS conform to output format.
394
398
  agent_kwargs={"output_parser": SafeOutputParser()},
395
- # Calls the agents LLM Chain one final time to generate a final answer based on the previous steps
399
+ # Calls the agent's LLM Chain one final time to generate a final answer based on the previous steps
396
400
  early_stopping_method="generate",
397
401
  handle_parsing_errors=self._handle_parsing_errors,
398
402
  # Timeout per agent invocation.
@@ -400,11 +404,9 @@ class LangchainAgent:
400
404
  "timeout_seconds",
401
405
  args.get("timeout_seconds", DEFAULT_AGENT_TIMEOUT_SECONDS),
402
406
  ),
403
- max_iterations=args.get(
404
- "max_iterations", args.get("max_iterations", DEFAULT_MAX_ITERATIONS)
405
- ),
407
+ max_iterations=args.get("max_iterations", args.get("max_iterations", DEFAULT_MAX_ITERATIONS)),
406
408
  memory=memory,
407
- verbose=args.get("verbose", args.get("verbose", False))
409
+ verbose=args.get("verbose", args.get("verbose", False)),
408
410
  )
409
411
  return agent_executor
410
412
 
@@ -416,7 +418,7 @@ class LangchainAgent:
416
418
  type=rel.skill.type,
417
419
  params=rel.skill.params,
418
420
  project_id=rel.skill.project_id,
419
- agent_tables_list=(rel.parameters or {}).get('tables')
421
+ agent_tables_list=(rel.parameters or {}).get("tables"),
420
422
  )
421
423
  for rel in self.agent.skills_relationships
422
424
  ]
@@ -507,24 +509,34 @@ AI: {response}"""
507
509
  return f"Agent failed with error:\n{str(error)}..."
508
510
 
509
511
  def run_agent(self, df: pd.DataFrame, agent: AgentExecutor, args: Dict) -> pd.DataFrame:
510
- base_template = args.get('prompt_template', args['prompt_template'])
511
- return_context = args.get('return_context', True)
512
+ base_template = args.get("prompt_template", args["prompt_template"])
513
+ return_context = args.get("return_context", True)
512
514
  input_variables = re.findall(r"{{(.*?)}}", base_template)
513
515
 
514
- prompts, empty_prompt_ids = prepare_prompts(df, base_template, input_variables,
515
- args.get('user_column', USER_COLUMN))
516
+ prompts, empty_prompt_ids = prepare_prompts(
517
+ df, base_template, input_variables, args.get("user_column", USER_COLUMN)
518
+ )
516
519
 
517
520
  def _invoke_agent_executor_with_prompt(agent_executor, prompt):
518
521
  if not prompt:
519
522
  return {CONTEXT_COLUMN: [], ASSISTANT_COLUMN: ""}
520
523
  try:
521
524
  callbacks, context_callback = prepare_callbacks(self, args)
522
- result = agent_executor.invoke(prompt, config={'callbacks': callbacks})
525
+ result = agent_executor.invoke(prompt, config={"callbacks": callbacks})
523
526
  captured_context = context_callback.get_contexts()
524
- output = result['output'] if isinstance(result, dict) and 'output' in result else str(result)
527
+ output = result["output"] if isinstance(result, dict) and "output" in result else str(result)
525
528
  return {CONTEXT_COLUMN: captured_context, ASSISTANT_COLUMN: output}
526
529
  except Exception as e:
527
- return {CONTEXT_COLUMN: [], ASSISTANT_COLUMN: handle_agent_error(e)}
530
+ error_message = str(e)
531
+ # Special handling for API key errors
532
+ if "API key" in error_message and ("not found" in error_message or "missing" in error_message):
533
+ # Format API key error more clearly
534
+ logger.error(f"API Key Error: {error_message}")
535
+ error_message = f"API Key Error: {error_message}"
536
+ return {
537
+ CONTEXT_COLUMN: [],
538
+ ASSISTANT_COLUMN: handle_agent_error(e, error_message),
539
+ }
528
540
 
529
541
  completions = []
530
542
  contexts = []
@@ -533,10 +545,7 @@ AI: {response}"""
533
545
  agent_timeout_seconds = args.get("timeout", DEFAULT_AGENT_TIMEOUT_SECONDS)
534
546
 
535
547
  with ContextThreadPoolExecutor(max_workers=max_workers) as executor:
536
- futures = [
537
- executor.submit(_invoke_agent_executor_with_prompt, agent, prompt)
538
- for prompt in prompts
539
- ]
548
+ futures = [executor.submit(_invoke_agent_executor_with_prompt, agent, prompt) for prompt in prompts]
540
549
  try:
541
550
  for future in as_completed(futures, timeout=agent_timeout_seconds):
542
551
  result = future.result()
@@ -550,9 +559,7 @@ AI: {response}"""
550
559
  contexts.append(result[CONTEXT_COLUMN])
551
560
  except TimeoutError:
552
561
  timeout_message = "I'm sorry! I couldn't come up with a response in time. Please try again."
553
- logger.warning(
554
- f"Agent execution timed out after {agent_timeout_seconds} seconds"
555
- )
562
+ logger.warning(f"Agent execution timed out after {agent_timeout_seconds} seconds")
556
563
  for _ in range(len(futures) - len(completions)):
557
564
  completions.append(timeout_message)
558
565
  contexts.append([])
@@ -566,10 +573,8 @@ AI: {response}"""
566
573
  pred_df = pd.DataFrame(
567
574
  {
568
575
  ASSISTANT_COLUMN: completions,
569
- CONTEXT_COLUMN: [
570
- json.dumps(ctx) for ctx in contexts
571
- ], # Serialize context to JSON string
572
- TRACE_ID_COLUMN: self.langfuse_client_wrapper.get_trace_id()
576
+ CONTEXT_COLUMN: [json.dumps(ctx) for ctx in contexts], # Serialize context to JSON string
577
+ TRACE_ID_COLUMN: self.langfuse_client_wrapper.get_trace_id(),
573
578
  }
574
579
  )
575
580
 
@@ -579,17 +584,22 @@ AI: {response}"""
579
584
  return pred_df
580
585
 
581
586
  def add_chunk_metadata(self, chunk: Dict) -> Dict:
582
- logger.debug(f'Adding metadata to chunk: {chunk}')
583
- logger.debug(f'Trace ID: {self.langfuse_client_wrapper.get_trace_id()}')
587
+ logger.debug(f"Adding metadata to chunk: {chunk}")
588
+ logger.debug(f"Trace ID: {self.langfuse_client_wrapper.get_trace_id()}")
584
589
  chunk["trace_id"] = self.langfuse_client_wrapper.get_trace_id()
585
590
  return chunk
586
591
 
587
- def _stream_agent_executor(self, agent_executor: AgentExecutor, prompt: str, callbacks: List[BaseCallbackHandler]):
592
+ def _stream_agent_executor(
593
+ self,
594
+ agent_executor: AgentExecutor,
595
+ prompt: str,
596
+ callbacks: List[BaseCallbackHandler],
597
+ ):
588
598
  chunk_queue = queue.Queue()
589
599
  # Add event dispatch callback handler only to streaming completions.
590
600
  event_dispatch_callback_handler = EventDispatchCallbackHandler(chunk_queue)
591
601
  callbacks.append(event_dispatch_callback_handler)
592
- stream_iterator = agent_executor.stream(prompt, config={'callbacks': callbacks})
602
+ stream_iterator = agent_executor.stream(prompt, config={"callbacks": callbacks})
593
603
 
594
604
  agent_executor_finished_event = threading.Event()
595
605
 
@@ -604,7 +614,10 @@ AI: {response}"""
604
614
 
605
615
  # Enqueue Langchain agent streaming chunks in a separate thread to not block event chunks.
606
616
  executor_stream_thread = threading.Thread(
607
- target=stream_worker, daemon=True, args=(ctx.dump(),), name='LangchainAgent.stream_worker'
617
+ target=stream_worker,
618
+ daemon=True,
619
+ args=(ctx.dump(),),
620
+ name="LangchainAgent.stream_worker",
608
621
  )
609
622
  executor_stream_thread.start()
610
623
 
@@ -613,24 +626,24 @@ AI: {response}"""
613
626
  chunk = chunk_queue.get(block=True, timeout=AGENT_CHUNK_POLLING_INTERVAL_SECONDS)
614
627
  except queue.Empty:
615
628
  continue
616
- logger.debug(f'Processing streaming chunk {chunk}')
629
+ logger.debug(f"Processing streaming chunk {chunk}")
617
630
  processed_chunk = self.process_chunk(chunk)
618
- logger.info(f'Processed chunk: {processed_chunk}')
631
+ logger.info(f"Processed chunk: {processed_chunk}")
619
632
  yield self.add_chunk_metadata(processed_chunk)
620
633
  chunk_queue.task_done()
621
634
 
622
635
  def stream_agent(self, df: pd.DataFrame, agent_executor: AgentExecutor, args: Dict) -> Iterable[Dict]:
623
- base_template = args.get('prompt_template', args['prompt_template'])
636
+ base_template = args.get("prompt_template", args["prompt_template"])
624
637
  input_variables = re.findall(r"{{(.*?)}}", base_template)
625
- return_context = args.get('return_context', True)
638
+ return_context = args.get("return_context", True)
626
639
 
627
- prompts, _ = prepare_prompts(df, base_template, input_variables, args.get('user_column', USER_COLUMN))
640
+ prompts, _ = prepare_prompts(df, base_template, input_variables, args.get("user_column", USER_COLUMN))
628
641
 
629
642
  callbacks, context_callback = prepare_callbacks(self, args)
630
643
 
631
644
  yield self.add_chunk_metadata({"type": "start", "prompt": prompts[0]})
632
645
 
633
- if not hasattr(agent_executor, 'stream') or not callable(agent_executor.stream):
646
+ if not hasattr(agent_executor, "stream") or not callable(agent_executor.stream):
634
647
  raise AttributeError("The agent_executor does not have a 'stream' method")
635
648
 
636
649
  stream_iterator = self._stream_agent_executor(agent_executor, prompts[0], callbacks)
@@ -659,21 +672,19 @@ AI: {response}"""
659
672
  if isinstance(chunk, AgentAction):
660
673
  # Format agent actions properly for streaming.
661
674
  return {
662
- 'tool': LangchainAgent.process_chunk(chunk.tool),
663
- 'tool_input': LangchainAgent.process_chunk(chunk.tool_input),
664
- 'log': LangchainAgent.process_chunk(chunk.log)
675
+ "tool": LangchainAgent.process_chunk(chunk.tool),
676
+ "tool_input": LangchainAgent.process_chunk(chunk.tool_input),
677
+ "log": LangchainAgent.process_chunk(chunk.log),
665
678
  }
666
679
  if isinstance(chunk, AgentStep):
667
680
  # Format agent steps properly for streaming.
668
681
  return {
669
- 'action': LangchainAgent.process_chunk(chunk.action),
670
- 'observation': LangchainAgent.process_chunk(chunk.observation) if chunk.observation else ''
682
+ "action": LangchainAgent.process_chunk(chunk.action),
683
+ "observation": LangchainAgent.process_chunk(chunk.observation) if chunk.observation else "",
671
684
  }
672
685
  if issubclass(chunk.__class__, BaseMessage):
673
686
  # Extract content from message subclasses properly for streaming.
674
- return {
675
- 'content': chunk.content
676
- }
687
+ return {"content": chunk.content}
677
688
  if isinstance(chunk, (str, int, float, bool, type(None))):
678
689
  return chunk
679
690
  return str(chunk)
@@ -2,6 +2,7 @@
2
2
  Wrapper around MindsDB's executor and integration controller following the implementation of the original
3
3
  langchain.sql_database.SQLDatabase class to partly replicate its behavior.
4
4
  """
5
+ import traceback
5
6
  from typing import Any, Iterable, List, Optional
6
7
 
7
8
  from mindsdb.utilities import log
@@ -57,8 +58,20 @@ class MindsDBSQL(SQLDatabase):
57
58
  """Information about all tables in the database."""
58
59
  return self._sql_agent.get_table_info()
59
60
 
61
+ @property
62
+ def kb_info(self) -> str:
63
+ """Information about all knowledge bases in the database."""
64
+ return self._sql_agent.get_knowledge_base_info()
65
+
60
66
  def get_usable_table_names(self) -> Iterable[str]:
61
- return self._sql_agent.get_usable_table_names()
67
+ """Information about all tables in the database."""
68
+ try:
69
+ return self._sql_agent.get_usable_table_names()
70
+ except Exception as e:
71
+ # If there's an error accessing tables through the integration, handle it gracefully
72
+ logger.warning(f"Error getting usable table names: {str(e)}")
73
+ # Return an empty list instead of raising an exception
74
+ return []
62
75
 
63
76
  def get_table_info_no_throw(self, table_names: Optional[List[str]] = None) -> str:
64
77
  for i in range(len(table_names)):
@@ -66,5 +79,91 @@ class MindsDBSQL(SQLDatabase):
66
79
  return self._sql_agent.get_table_info_safe(table_names)
67
80
 
68
81
  def run_no_throw(self, command: str, fetch: str = "all") -> str:
82
+ """Execute a SQL command and return the result as a string.
83
+
84
+ This method catches any exceptions and returns an error message instead of raising an exception.
85
+
86
+ Args:
87
+ command: The SQL command to execute
88
+ fetch: Whether to fetch 'all' results or just 'one'
89
+
90
+ Returns:
91
+ A string representation of the result or an error message
92
+ """
69
93
  command = extract_essential(command)
70
- return self._sql_agent.query_safe(command)
94
+
95
+ try:
96
+
97
+ # Log the query for debugging
98
+ logger.info(f"Executing SQL query: {command}")
99
+
100
+ # remove backticks
101
+ command = command.replace('`', '')
102
+
103
+ # Parse the SQL string to an AST object first
104
+ from mindsdb_sql_parser import parse_sql
105
+ ast_query = parse_sql(command)
106
+
107
+ # Now execute the parsed query
108
+ result = self._sql_agent.skill_tool.get_command_executor().execute_command(ast_query, database_name="mindsdb")
109
+
110
+ # Convert ExecuteAnswer to a DataFrame for easier manipulation
111
+ df = None
112
+ if hasattr(result, 'data') and hasattr(result.data, 'data_frame'):
113
+ df = result.data.data_frame
114
+ else:
115
+ # Fallback to to_df when data_frame attr not available
116
+ try:
117
+ df = result.data.to_df()
118
+ except Exception:
119
+ df = None
120
+
121
+ # Default behaviour (string)
122
+ if df is not None:
123
+ if not df.empty:
124
+ return df.to_string(index=False)
125
+ else:
126
+ return "Query executed successfully, but returned no data."
127
+
128
+ return str(result)
129
+
130
+ except Exception as e:
131
+ logger.error(f"Error executing SQL command: {str(e)}\n{traceback.format_exc()}")
132
+ # If this is a knowledge base query, provide a more helpful error message
133
+ if "knowledge_base" in command.lower() or any(kb in command for kb in self._sql_agent.get_usable_knowledge_base_names()):
134
+ return f"Error executing knowledge base query: {str(e)}. Please check that the knowledge base exists and your query syntax is correct."
135
+ return f"Error: {str(e)}"
136
+
137
+ # def run_no_throw(self, command: str, fetch: str = "all") -> str:
138
+ # """Execute a SQL command and return the result as a string.
139
+ #
140
+ # This method catches any exceptions and returns an error message instead of raising an exception.
141
+ #
142
+ # Args:
143
+ # command: The SQL command to execute
144
+ # fetch: Whether to fetch 'all' results or just 'one'
145
+ #
146
+ # Returns:
147
+ # A string representation of the result or an error message
148
+ # """
149
+ # command = extract_essential(command)
150
+ # try:
151
+ # return self._sql_agent.query_safe(command)
152
+ # except Exception as e:
153
+ # logger.error(f"Error executing SQL command: {str(e)}")
154
+ # # If this is a knowledge base query, provide a more helpful error message
155
+ # if "knowledge_base" in command.lower() or any(kb in command for kb in self._sql_agent.get_usable_knowledge_base_names()):
156
+ # return f"Error executing knowledge base query: {str(e)}. Please check that the knowledge base exists and your query syntax is correct."
157
+ # return f"Error: {str(e)}"
158
+
159
+ def get_usable_knowledge_base_names(self) -> List[str]:
160
+ """Get a list of usable knowledge base names.
161
+
162
+ Returns:
163
+ A list of knowledge base names that can be used in queries
164
+ """
165
+ try:
166
+ return self._sql_agent.get_usable_knowledge_base_names()
167
+ except Exception as e:
168
+ logger.error(f"Error getting usable knowledge base names: {str(e)}")
169
+ return []