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
@@ -1,6 +1,7 @@
1
1
  import re
2
2
  import csv
3
3
  import inspect
4
+ import traceback
4
5
  from io import StringIO
5
6
  from typing import Iterable, List, Optional, Any
6
7
 
@@ -34,7 +35,7 @@ def list_to_csv_str(array: List[List[Any]]) -> str:
34
35
 
35
36
 
36
37
  def split_table_name(table_name: str) -> List[str]:
37
- """Split table name from llm to parst
38
+ """Split table name from llm to parts
38
39
 
39
40
  Args:
40
41
  table_name (str): input table name
@@ -72,34 +73,69 @@ def split_table_name(table_name: str) -> List[str]:
72
73
  if current:
73
74
  result.append(current.strip('`'))
74
75
 
76
+ # ensure we split the table name
77
+ result = [r.split(".") for r in result][0]
78
+
75
79
  return result
76
80
 
77
81
 
78
82
  class SQLAgent:
83
+ """
84
+ SQLAgent is a class that handles SQL queries for agents.
85
+ """
86
+
79
87
  def __init__(
80
- self,
81
- command_executor,
82
- databases: List[str],
83
- databases_struct: dict,
84
- include_tables: Optional[List[str]] = None,
85
- ignore_tables: Optional[List[str]] = None,
86
- sample_rows_in_table_info: int = 3,
87
- cache: Optional[dict] = None
88
+ self,
89
+ command_executor,
90
+ databases: List[str],
91
+ databases_struct: dict,
92
+ knowledge_base_database: str = 'mindsdb',
93
+ include_tables: Optional[List[str]] = None,
94
+ ignore_tables: Optional[List[str]] = None,
95
+ include_knowledge_bases: Optional[List[str]] = None,
96
+ ignore_knowledge_bases: Optional[List[str]] = None,
97
+ sample_rows_in_table_info: int = 3,
98
+ cache: Optional[dict] = None
88
99
  ):
100
+ """
101
+ Initialize SQLAgent.
102
+
103
+ Args:
104
+ command_executor: Executor for SQL commands
105
+ databases (List[str]): List of databases to use
106
+ databases_struct (dict): Dictionary of database structures
107
+ knowledge_base_database (str): Project name where knowledge bases are stored (defaults to 'mindsdb')
108
+ include_tables (List[str]): Tables to include
109
+ ignore_tables (List[str]): Tables to ignore
110
+ include_knowledge_bases (List[str]): Knowledge bases to include
111
+ ignore_knowledge_bases (List[str]): Knowledge bases to ignore
112
+ sample_rows_in_table_info (int): Number of sample rows to include in table info
113
+ cache (Optional[dict]): Cache for query results
114
+ """
89
115
  self._command_executor = command_executor
90
116
  self._mindsdb_db_struct = databases_struct
91
-
117
+ self.knowledge_base_database = knowledge_base_database # This is a project name, not a database connection
92
118
  self._sample_rows_in_table_info = int(sample_rows_in_table_info)
93
119
 
94
120
  self._tables_to_include = include_tables
95
121
  self._tables_to_ignore = []
122
+ self._knowledge_bases_to_include = include_knowledge_bases
123
+ self._knowledge_bases_to_ignore = []
96
124
  self._databases = databases
97
125
  if not self._tables_to_include:
98
126
  # ignore_tables and include_tables should not be used together.
99
127
  # include_tables takes priority if it's set.
100
128
  self._tables_to_ignore = ignore_tables or []
129
+ if not self._knowledge_bases_to_include:
130
+ # ignore_knowledge_bases and include_knowledge_bases should not be used together.
131
+ # include_knowledge_bases takes priority if it's set.
132
+ self._knowledge_bases_to_ignore = ignore_knowledge_bases or []
101
133
  self._cache = cache
102
134
 
135
+ from mindsdb.interfaces.skills.skill_tool import SkillToolController
136
+ # Initialize the skill tool controller from MindsDB
137
+ self.skill_tool = SkillToolController()
138
+
103
139
  def _call_engine(self, query: str, database=None):
104
140
  # switch database
105
141
  ast_query = parse_sql(query.strip('`'))
@@ -107,7 +143,10 @@ class SQLAgent:
107
143
 
108
144
  if database is None:
109
145
  # if we use tables with prefixes it should work for any database
110
- database = self._databases[0]
146
+ if self._databases is not None:
147
+ # if we have multiple databases, we need to check which one to use
148
+ # for now, we will just use the first one
149
+ database = self._databases[0] if self._databases else "mindsdb"
111
150
 
112
151
  ret = self._command_executor.execute_command(
113
152
  ast_query,
@@ -131,9 +170,28 @@ class SQLAgent:
131
170
 
132
171
  def _check_f(node, is_table=None, **kwargs):
133
172
  if is_table and isinstance(node, Identifier):
134
- if node.parts not in tables_parts:
135
- raise ValueError(f"Table {'.'.join(node.parts)} not found. Available tables: {', '.join(self._tables_to_include)}")
136
-
173
+ table_name = '.'.join(node.parts)
174
+
175
+ # Get the list of available knowledge bases
176
+ kb_names = self.get_usable_knowledge_base_names()
177
+
178
+ # Check if this table is a knowledge base
179
+ is_kb = table_name in kb_names
180
+
181
+ # If it's a knowledge base and we have knowledge base restrictions
182
+ if is_kb and self._knowledge_bases_to_include:
183
+ kb_parts = [split_table_name(x) for x in self._knowledge_bases_to_include]
184
+ if node.parts not in kb_parts:
185
+ raise ValueError(f"Knowledge base {table_name} not found. Available knowledge bases: {', '.join(self._knowledge_bases_to_include)}")
186
+ # Regular table check
187
+ elif not is_kb and self._tables_to_include and node.parts not in tables_parts:
188
+ raise ValueError(f"Table {table_name} not found. Available tables: {', '.join(self._tables_to_include)}")
189
+ # Check if it's a restricted knowledge base
190
+ elif is_kb and table_name in self._knowledge_bases_to_ignore:
191
+ raise ValueError(f"Knowledge base {table_name} is not allowed.")
192
+ # Check if it's a restricted table
193
+ elif not is_kb and table_name in self._tables_to_ignore:
194
+ raise ValueError(f"Table {table_name} is not allowed.")
137
195
  query_traversal(ast_query, _check_f)
138
196
 
139
197
  def get_usable_table_names(self) -> Iterable[str]:
@@ -200,6 +258,78 @@ class SQLAgent:
200
258
  self._cache.set(cache_key, set(result_tables))
201
259
  return result_tables
202
260
 
261
+ def get_usable_knowledge_base_names(self) -> Iterable[str]:
262
+ """Get a list of knowledge bases that the agent has access to.
263
+
264
+ Returns:
265
+ Iterable[str]: list with knowledge base names
266
+ """
267
+ cache_key = f'{ctx.company_id}_{self.knowledge_base_database}_knowledge_bases'
268
+
269
+ # todo we need to fix the cache, file cache can potentially store out of data information
270
+ # # first check cache and return if found
271
+ # if self._cache:
272
+ # cached_kbs = self._cache.get(cache_key)
273
+ # if cached_kbs:
274
+ # return cached_kbs
275
+
276
+ if self._knowledge_bases_to_include:
277
+ return self._knowledge_bases_to_include
278
+
279
+ try:
280
+ # Query to get all knowledge bases
281
+ query = f"SHOW KNOWLEDGE_BASES FROM {self.knowledge_base_database};"
282
+ try:
283
+ result = self._call_engine(query, database=self.knowledge_base_database)
284
+ except Exception as e:
285
+ # If the direct query fails, try a different approach
286
+ # This handles the case where knowledge_base_database is not a valid integration
287
+ logger.warning(f"Error querying knowledge bases from {self.knowledge_base_database}: {str(e)}")
288
+ # Try to get knowledge bases directly from the project database
289
+ try:
290
+ # Get knowledge bases from the project database
291
+ kb_controller = self._command_executor.session.kb_controller
292
+ kb_names = [kb['name'] for kb in kb_controller.list()]
293
+
294
+ # Filter knowledge bases based on include list
295
+ if self._knowledge_bases_to_include:
296
+ kb_names = [kb_name for kb_name in kb_names if kb_name in self._knowledge_bases_to_include]
297
+ if not kb_names:
298
+ logger.warning(f"No knowledge bases found in the include list: {self._knowledge_bases_to_include}")
299
+ return []
300
+
301
+ return kb_names
302
+
303
+ # Filter knowledge bases based on ignore list
304
+ kb_names = [kb_name for kb_name in kb_names if kb_name not in self._knowledge_bases_to_ignore]
305
+
306
+ if self._cache:
307
+ self._cache.set(cache_key, set(kb_names))
308
+
309
+ return kb_names
310
+ except Exception as inner_e:
311
+ logger.error(f"Error getting knowledge bases from kb_controller: {str(inner_e)}")
312
+ return []
313
+
314
+ if not result:
315
+ return []
316
+
317
+ # Filter knowledge bases based on ignore list
318
+ kb_names = []
319
+ for row in result:
320
+ kb_name = row['name']
321
+ if kb_name not in self._knowledge_bases_to_ignore:
322
+ kb_names.append(kb_name)
323
+
324
+ if self._cache:
325
+ self._cache.set(cache_key, set(kb_names))
326
+
327
+ return kb_names
328
+ except Exception as e:
329
+ # If there's an error, log it and return an empty list
330
+ logger.error(f"Error in get_usable_knowledge_base_names: {str(e)}")
331
+ return []
332
+
203
333
  def _resolve_table_names(self, table_names: List[str], all_tables: List[Identifier]) -> List[Identifier]:
204
334
  """
205
335
  Tries to find table (which comes directly from an LLM) by its name
@@ -237,6 +367,26 @@ class SQLAgent:
237
367
 
238
368
  return tables
239
369
 
370
+ def get_knowledge_base_info(self, kb_names: Optional[List[str]] = None) -> str:
371
+ """ Get information about specified knowledge bases.
372
+ Follows best practices as specified in: Rajkumar et al, 2022 (https://arxiv.org/abs/2204.00498)
373
+ If `sample_rows_in_table_info`, the specified number of sample rows will be
374
+ appended to each table description. This can increase performance as demonstrated in the paper.
375
+ """
376
+
377
+ kbs_info = []
378
+ for kb in kb_names:
379
+ key = f"{ctx.company_id}_{kb}_info"
380
+ kb_info = self._cache.get(key) if self._cache else None
381
+ if True or kb_info is None:
382
+ kb_info = self.get_kb_sample_rows(kb)
383
+ if self._cache:
384
+ self._cache.set(key, kb_info)
385
+
386
+ kbs_info.append(kb_info)
387
+
388
+ return "\n\n".join(kbs_info)
389
+
240
390
  def get_table_info(self, table_names: Optional[List[str]] = None) -> str:
241
391
  """ Get information about specified tables.
242
392
  Follows best practices as specified in: Rajkumar et al, 2022 (https://arxiv.org/abs/2204.00498)
@@ -244,10 +394,19 @@ class SQLAgent:
244
394
  appended to each table description. This can increase performance as demonstrated in the paper.
245
395
  """
246
396
 
247
- all_tables = [Identifier(name) for name in self.get_usable_table_names()]
397
+ all_tables = []
398
+ for name in self.get_usable_table_names():
399
+ # remove backticks
400
+ name = name.replace("`", "")
401
+
402
+ split = name.split(".")
403
+ if len(split) > 1:
404
+ all_tables.append(Identifier(parts=[split[0], split[1]]))
405
+ else:
406
+ all_tables.append(Identifier(name))
248
407
 
249
- if table_names is not None:
250
- all_tables = self._resolve_table_names(table_names, all_tables)
408
+ # if table_names is not None:
409
+ # all_tables = self._resolve_table_names(table_names, all_tables)
251
410
 
252
411
  tables_info = []
253
412
  for table in all_tables:
@@ -262,6 +421,34 @@ class SQLAgent:
262
421
 
263
422
  return "\n\n".join(tables_info)
264
423
 
424
+ def get_kb_sample_rows(self, kb_name: str) -> str:
425
+ """Get sample rows from a knowledge base.
426
+
427
+ Args:
428
+ kb_name (str): The name of the knowledge base.
429
+
430
+ Returns:
431
+ str: A string containing the sample rows from the knowledge base.
432
+ """
433
+ logger.info(f'_get_sample_rows: knowledge base={kb_name}')
434
+ command = f"select * from {kb_name} limit 10;"
435
+ try:
436
+ ret = self._call_engine(command)
437
+ sample_rows = ret.data.to_lists()
438
+
439
+ def truncate_value(val):
440
+ str_val = str(val)
441
+ return str_val if len(str_val) < 100 else (str_val[:100] + '...')
442
+
443
+ sample_rows = list(
444
+ map(lambda row: [truncate_value(value) for value in row], sample_rows))
445
+ sample_rows_str = "\n" + f"{kb_name}:" + list_to_csv_str(sample_rows)
446
+ except Exception as e:
447
+ logger.info(f'_get_sample_rows error: {e}')
448
+ sample_rows_str = "\n" + "\t [error] Couldn't retrieve sample rows!"
449
+
450
+ return sample_rows_str
451
+
265
452
  def _get_single_table_info(self, table: Identifier) -> str:
266
453
  if len(table.parts) < 2:
267
454
  raise ValueError(f"Database is required for table: {table}")
@@ -386,6 +573,7 @@ class SQLAgent:
386
573
  logger.info(f'query_safe (fetch={fetch}): {command}')
387
574
  return self.query(command, fetch)
388
575
  except Exception as e:
576
+ logger.error(f"Error in query_safe: {str(e)}\n{traceback.format_exc()}")
389
577
  logger.info(f'query_safe error: {e}')
390
578
  msg = f"Error: {e}"
391
579
  if 'does not exist' in msg and ' relation ' in msg:
@@ -37,6 +37,7 @@ class RESOURCE_GROUP:
37
37
  PREDICTOR = 'predictor'
38
38
  INTEGRATION = 'integration'
39
39
  TAB = 'tab'
40
+ SYSTEM = 'system'
40
41
 
41
42
 
42
43
  RESOURCE_GROUP = RESOURCE_GROUP()
File without changes
@@ -0,0 +1,97 @@
1
+ import os
2
+ from typing import Callable
3
+
4
+ from mindsdb_sql_parser import Function, Constant, Variable
5
+
6
+ from mindsdb.utilities import log
7
+ from mindsdb.interfaces.storage.fs import RESOURCE_GROUP
8
+ from mindsdb.interfaces.storage.json import get_json_storage
9
+
10
+
11
+ logger = log.getLogger(__name__)
12
+
13
+
14
+ ENV_VAR_PREFIX = "MDB_"
15
+
16
+
17
+ class VariablesController:
18
+
19
+ def __init__(self) -> None:
20
+ self._storage = get_json_storage(
21
+ resource_id=0,
22
+ resource_group=RESOURCE_GROUP.SYSTEM
23
+ )
24
+ self._store_key = 'variables'
25
+ self._data = None
26
+
27
+ def _get_data(self) -> dict:
28
+ if self._data is None:
29
+ self._data = self._storage.get(self._store_key)
30
+ if self._data is None:
31
+ self._data = {}
32
+ return self._data
33
+
34
+ def get_value(self, name: str):
35
+ data = self._get_data()
36
+ if name not in data:
37
+ raise ValueError(f"Variable {name} is not defined")
38
+ return data[name]
39
+
40
+ def set_value(self, name: str, value):
41
+ data = self._get_data()
42
+ data[name] = value
43
+ self._storage.set(self._store_key, data)
44
+
45
+ def _from_env(self, name: Constant) -> str:
46
+ # gets variable value from environment.
47
+ # available names are restricted by ENV_VAR_PREFIX to don't provide access to arbitrary venv variable
48
+
49
+ var_name = name.value
50
+ if not var_name.startswith(ENV_VAR_PREFIX):
51
+ raise ValueError(f"Can access only to variable names starting with {ENV_VAR_PREFIX}")
52
+ if var_name not in os.environ:
53
+ raise ValueError(f"Environment variable {var_name} is not defined")
54
+ return os.environ[var_name]
55
+
56
+ def _get_function(self, name: str) -> Callable:
57
+ if name == 'from_env':
58
+ return self._from_env
59
+ raise ValueError(f"Function {name} is not found")
60
+
61
+ def set_variable(self, name: str, value):
62
+ # store new value for variable in database
63
+ # if value is a function - extract value using this function
64
+
65
+ name = name.lower()
66
+ if isinstance(value, Function):
67
+ fnc = self._get_function(value.op)
68
+ value = fnc(*value.args)
69
+
70
+ elif isinstance(value, Constant):
71
+ value = value.value
72
+
73
+ else:
74
+ # ignore
75
+ return
76
+
77
+ self.set_value(name, value)
78
+
79
+ def fill_parameters(self, var):
80
+ # recursively check input and fill Variables if they exist there
81
+
82
+ if isinstance(var, Variable):
83
+ return self.get_value(var.value.lower())
84
+ elif isinstance(var, dict):
85
+ return {
86
+ key: self.fill_parameters(value)
87
+ for key, value in var.items()
88
+ }
89
+ elif isinstance(var, list):
90
+ return [
91
+ self.fill_parameters(value)
92
+ for value in var
93
+ ]
94
+ return var
95
+
96
+
97
+ variables_controller = VariablesController()
mindsdb/migrations/env.py CHANGED
@@ -1,5 +1,9 @@
1
1
  from alembic import context
2
2
  from sqlalchemy import engine_from_config, pool
3
+ import os
4
+
5
+ from mindsdb.interfaces.storage import db
6
+ from mindsdb.utilities.config import config as app_config
3
7
 
4
8
  # this is the Alembic Config object, which provides
5
9
  # access to the values within the .ini file in use.
@@ -10,12 +14,6 @@ config = context.config
10
14
  # from myapp import mymodel
11
15
  # target_metadata = mymodel.Base.metadata
12
16
 
13
-
14
- import os
15
-
16
- from mindsdb.interfaces.storage import db
17
- from mindsdb.utilities.config import config as app_config
18
-
19
17
  # initialize
20
18
 
21
19
  if "MINDSDB_CONFIG_PATH" not in os.environ:
@@ -25,7 +23,7 @@ db.init()
25
23
 
26
24
  target_metadata = db.Base.metadata
27
25
 
28
- config.set_main_option("sqlalchemy.url", app_config['storage_db'])
26
+ config.set_main_option("sqlalchemy.url", app_config["storage_db"])
29
27
 
30
28
 
31
29
  # other values from the config, defined by the needs of env.py,
@@ -4,13 +4,52 @@ from alembic.command import upgrade, autogen # noqa
4
4
  from alembic.config import Config
5
5
  from alembic.script import ScriptDirectory
6
6
  from alembic.script.revision import ResolutionError
7
+ from alembic.operations import Operations
7
8
  from alembic.migration import MigrationContext
9
+ from alembic import util
8
10
 
9
11
  import mindsdb.interfaces.storage.db as db
10
12
  from mindsdb.utilities import log
11
13
 
12
14
  logger = log.getLogger(__name__)
13
15
 
16
+ # This is a migration that is like a 'base version'. Applying only this
17
+ # migration to a fresh DB is equivalent to applying all previous migrations.
18
+ current_checkpoint = '9f150e4f9a05'
19
+
20
+
21
+ def apply_checkpoint_migration(script) -> None:
22
+ """Apply the checkpoint migration to the database.
23
+ """
24
+ with db.engine.begin() as connection:
25
+ context = MigrationContext.configure(
26
+ connection,
27
+ opts={
28
+ 'as_sql': False,
29
+ 'starting_rev': None, # ignore current version
30
+ 'destination_rev': current_checkpoint,
31
+ }
32
+ )
33
+ revision = script.get_revision(current_checkpoint)
34
+ if not revision:
35
+ raise util.CommandError(f"Migration {current_checkpoint} not found.")
36
+
37
+ op = Operations(context)
38
+ revision.module.upgrade(op)
39
+ context.stamp(script, current_checkpoint)
40
+ connection.commit()
41
+
42
+
43
+ def get_current_revision() -> str | None:
44
+ """ Get the current revision of the database.
45
+
46
+ Returns:
47
+ str | None: The current revision of the database.
48
+ """
49
+ with db.engine.begin() as conn:
50
+ mc = MigrationContext.configure(conn)
51
+ return mc.get_current_revision()
52
+
14
53
 
15
54
  def migrate_to_head():
16
55
  """ Trying to update database to head revision.
@@ -26,14 +65,15 @@ def migrate_to_head():
26
65
  config.set_main_option('script_location', str(script_location_abc))
27
66
 
28
67
  script = ScriptDirectory.from_config(config)
29
- with db.engine.begin() as conn:
30
- mc = MigrationContext.configure(conn)
31
- cur_revision = mc.get_current_revision()
68
+ cur_revision = get_current_revision()
69
+ if cur_revision is None:
70
+ apply_checkpoint_migration(script)
71
+ cur_revision = get_current_revision()
32
72
 
33
- try:
34
- script.revision_map.get_revision(cur_revision)
35
- except ResolutionError:
36
- raise Exception("Database version higher than application.")
73
+ try:
74
+ script.revision_map.get_revision(cur_revision)
75
+ except ResolutionError:
76
+ raise Exception("Database version higher than application.")
37
77
 
38
78
  head_rev = script.get_current_head()
39
79
  if cur_revision == head_rev: