MindsDB 25.4.5.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 (350) hide show
  1. mindsdb/__about__.py +1 -1
  2. mindsdb/__main__.py +215 -185
  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 +49 -28
  20. mindsdb/api/executor/datahub/classes/response.py +5 -2
  21. mindsdb/api/executor/datahub/datanodes/information_schema_datanode.py +8 -0
  22. mindsdb/api/executor/datahub/datanodes/integration_datanode.py +39 -72
  23. mindsdb/api/executor/datahub/datanodes/system_tables.py +10 -13
  24. mindsdb/api/executor/planner/query_planner.py +14 -2
  25. mindsdb/api/executor/sql_query/result_set.py +185 -52
  26. mindsdb/api/executor/sql_query/sql_query.py +1 -1
  27. mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +11 -13
  28. mindsdb/api/executor/sql_query/steps/fetch_dataframe.py +8 -10
  29. mindsdb/api/executor/sql_query/steps/fetch_dataframe_partition.py +5 -44
  30. mindsdb/api/executor/sql_query/steps/insert_step.py +24 -15
  31. mindsdb/api/executor/sql_query/steps/join_step.py +1 -1
  32. mindsdb/api/executor/sql_query/steps/project_step.py +1 -1
  33. mindsdb/api/executor/sql_query/steps/sql_steps.py +1 -1
  34. mindsdb/api/executor/sql_query/steps/subselect_step.py +4 -8
  35. mindsdb/api/executor/sql_query/steps/union_step.py +1 -3
  36. mindsdb/api/http/initialize.py +118 -85
  37. mindsdb/api/http/namespaces/analysis.py +17 -4
  38. mindsdb/api/http/namespaces/file.py +8 -2
  39. mindsdb/api/http/namespaces/sql.py +13 -27
  40. mindsdb/api/http/namespaces/tree.py +1 -1
  41. mindsdb/api/http/start.py +7 -2
  42. mindsdb/api/mcp/start.py +42 -5
  43. mindsdb/api/mysql/mysql_proxy/data_types/mysql_packet.py +0 -1
  44. mindsdb/api/mysql/mysql_proxy/data_types/mysql_packets/binary_resultset_row_package.py +52 -19
  45. mindsdb/api/mysql/mysql_proxy/executor/mysql_executor.py +8 -10
  46. mindsdb/api/mysql/mysql_proxy/libs/constants/mysql.py +54 -38
  47. mindsdb/api/mysql/mysql_proxy/mysql_proxy.py +86 -123
  48. mindsdb/api/mysql/mysql_proxy/utilities/dump.py +351 -0
  49. mindsdb/api/mysql/mysql_proxy/utilities/exceptions.py +0 -4
  50. mindsdb/api/postgres/postgres_proxy/executor/executor.py +1 -1
  51. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_message_formats.py +2 -2
  52. mindsdb/api/postgres/postgres_proxy/postgres_proxy.py +5 -6
  53. mindsdb/integrations/handlers/altibase_handler/altibase_handler.py +26 -27
  54. mindsdb/integrations/handlers/altibase_handler/connection_args.py +13 -13
  55. mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler.py +8 -8
  56. mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler_dsn.py +13 -13
  57. mindsdb/integrations/handlers/anthropic_handler/__init__.py +2 -2
  58. mindsdb/integrations/handlers/anthropic_handler/anthropic_handler.py +1 -3
  59. mindsdb/integrations/handlers/aurora_handler/aurora_handler.py +1 -0
  60. mindsdb/integrations/handlers/autosklearn_handler/autosklearn_handler.py +1 -1
  61. mindsdb/integrations/handlers/autosklearn_handler/config.py +0 -1
  62. mindsdb/integrations/handlers/bigquery_handler/bigquery_handler.py +1 -1
  63. mindsdb/integrations/handlers/bigquery_handler/requirements.txt +1 -0
  64. mindsdb/integrations/handlers/bigquery_handler/tests/test_bigquery_handler.py +1 -1
  65. mindsdb/integrations/handlers/binance_handler/binance_handler.py +1 -0
  66. mindsdb/integrations/handlers/binance_handler/binance_tables.py +3 -4
  67. mindsdb/integrations/handlers/byom_handler/__init__.py +0 -1
  68. mindsdb/integrations/handlers/chromadb_handler/requirements.txt +1 -0
  69. mindsdb/integrations/handlers/ckan_handler/ckan_handler.py +3 -0
  70. mindsdb/integrations/handlers/clickhouse_handler/__init__.py +1 -1
  71. mindsdb/integrations/handlers/cloud_spanner_handler/tests/test_cloud_spanner_handler.py +0 -2
  72. mindsdb/integrations/handlers/cloud_sql_handler/cloud_sql_handler.py +0 -1
  73. mindsdb/integrations/handlers/cohere_handler/__init__.py +1 -1
  74. mindsdb/integrations/handlers/cohere_handler/cohere_handler.py +11 -13
  75. mindsdb/integrations/handlers/confluence_handler/confluence_tables.py +6 -0
  76. mindsdb/integrations/handlers/databend_handler/connection_args.py +1 -1
  77. mindsdb/integrations/handlers/databend_handler/databend_handler.py +4 -4
  78. mindsdb/integrations/handlers/databend_handler/tests/__init__.py +0 -1
  79. mindsdb/integrations/handlers/databend_handler/tests/test_databend_handler.py +1 -1
  80. mindsdb/integrations/handlers/derby_handler/connection_args.py +1 -1
  81. mindsdb/integrations/handlers/derby_handler/derby_handler.py +14 -22
  82. mindsdb/integrations/handlers/derby_handler/tests/test_derby_handler.py +6 -6
  83. mindsdb/integrations/handlers/discord_handler/discord_handler.py +5 -5
  84. mindsdb/integrations/handlers/discord_handler/discord_tables.py +3 -3
  85. mindsdb/integrations/handlers/discord_handler/tests/test_discord.py +5 -3
  86. mindsdb/integrations/handlers/dockerhub_handler/dockerhub.py +3 -3
  87. mindsdb/integrations/handlers/dockerhub_handler/dockerhub_handler.py +2 -2
  88. mindsdb/integrations/handlers/dockerhub_handler/dockerhub_tables.py +57 -54
  89. mindsdb/integrations/handlers/dremio_handler/__init__.py +2 -2
  90. mindsdb/integrations/handlers/druid_handler/__init__.py +1 -1
  91. mindsdb/integrations/handlers/druid_handler/druid_handler.py +2 -2
  92. mindsdb/integrations/handlers/edgelessdb_handler/tests/test_edgelessdb_handler.py +9 -9
  93. mindsdb/integrations/handlers/email_handler/email_client.py +1 -1
  94. mindsdb/integrations/handlers/email_handler/email_ingestor.py +1 -1
  95. mindsdb/integrations/handlers/email_handler/email_tables.py +0 -1
  96. mindsdb/integrations/handlers/email_handler/settings.py +0 -1
  97. mindsdb/integrations/handlers/eventstoredb_handler/eventstoredb_handler.py +2 -1
  98. mindsdb/integrations/handlers/firebird_handler/firebird_handler.py +1 -1
  99. mindsdb/integrations/handlers/flaml_handler/flaml_handler.py +9 -9
  100. mindsdb/integrations/handlers/frappe_handler/frappe_client.py +5 -5
  101. mindsdb/integrations/handlers/frappe_handler/frappe_handler.py +6 -5
  102. mindsdb/integrations/handlers/frappe_handler/frappe_tables.py +2 -2
  103. mindsdb/integrations/handlers/github_handler/connection_args.py +2 -2
  104. mindsdb/integrations/handlers/github_handler/github_handler.py +1 -8
  105. mindsdb/integrations/handlers/github_handler/github_tables.py +13 -24
  106. mindsdb/integrations/handlers/gitlab_handler/gitlab_handler.py +2 -1
  107. mindsdb/integrations/handlers/gitlab_handler/gitlab_tables.py +1 -4
  108. mindsdb/integrations/handlers/gmail_handler/gmail_handler.py +6 -13
  109. mindsdb/integrations/handlers/gmail_handler/requirements.txt +1 -0
  110. mindsdb/integrations/handlers/google_analytics_handler/requirements.txt +2 -1
  111. mindsdb/integrations/handlers/google_books_handler/google_books_handler.py +2 -1
  112. mindsdb/integrations/handlers/google_books_handler/google_books_tables.py +0 -3
  113. mindsdb/integrations/handlers/google_books_handler/requirements.txt +1 -1
  114. mindsdb/integrations/handlers/google_calendar_handler/google_calendar_handler.py +4 -4
  115. mindsdb/integrations/handlers/google_calendar_handler/google_calendar_tables.py +2 -6
  116. mindsdb/integrations/handlers/google_calendar_handler/requirements.txt +1 -0
  117. mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_handler.py +3 -2
  118. mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_tables.py +0 -3
  119. mindsdb/integrations/handlers/google_content_shopping_handler/requirements.txt +1 -1
  120. mindsdb/integrations/handlers/google_fit_handler/google_fit_handler.py +10 -12
  121. mindsdb/integrations/handlers/google_fit_handler/google_fit_tables.py +11 -13
  122. mindsdb/integrations/handlers/google_fit_handler/requirements.txt +2 -0
  123. mindsdb/integrations/handlers/google_search_handler/google_search_handler.py +2 -1
  124. mindsdb/integrations/handlers/google_search_handler/google_search_tables.py +0 -3
  125. mindsdb/integrations/handlers/google_search_handler/requirements.txt +1 -1
  126. mindsdb/integrations/handlers/groq_handler/__init__.py +3 -3
  127. mindsdb/integrations/handlers/hackernews_handler/hn_handler.py +5 -7
  128. mindsdb/integrations/handlers/hackernews_handler/hn_table.py +6 -7
  129. mindsdb/integrations/handlers/hive_handler/tests/test_hive_handler.py +1 -1
  130. mindsdb/integrations/handlers/hsqldb_handler/connection_args.py +6 -6
  131. mindsdb/integrations/handlers/hsqldb_handler/hsqldb_handler.py +4 -3
  132. mindsdb/integrations/handlers/huggingface_api_handler/exceptions.py +1 -1
  133. mindsdb/integrations/handlers/huggingface_api_handler/huggingface_api_handler.py +1 -8
  134. mindsdb/integrations/handlers/huggingface_handler/huggingface_handler.py +6 -6
  135. mindsdb/integrations/handlers/huggingface_handler/requirements.txt +1 -1
  136. mindsdb/integrations/handlers/huggingface_handler/requirements_cpu.txt +1 -1
  137. mindsdb/integrations/handlers/ignite_handler/ignite_handler.py +2 -1
  138. mindsdb/integrations/handlers/impala_handler/impala_handler.py +9 -12
  139. mindsdb/integrations/handlers/impala_handler/tests/test_impala_handler.py +11 -11
  140. mindsdb/integrations/handlers/influxdb_handler/influxdb_handler.py +10 -13
  141. mindsdb/integrations/handlers/influxdb_handler/influxdb_tables.py +20 -20
  142. mindsdb/integrations/handlers/informix_handler/__about__.py +8 -8
  143. mindsdb/integrations/handlers/informix_handler/__init__.py +12 -5
  144. mindsdb/integrations/handlers/informix_handler/informix_handler.py +99 -133
  145. mindsdb/integrations/handlers/informix_handler/tests/test_informix_handler.py +13 -11
  146. mindsdb/integrations/handlers/ingres_handler/__about__.py +0 -1
  147. mindsdb/integrations/handlers/ingres_handler/ingres_handler.py +1 -0
  148. mindsdb/integrations/handlers/jira_handler/jira_handler.archived.py +75 -0
  149. mindsdb/integrations/handlers/jira_handler/jira_handler.py +113 -38
  150. mindsdb/integrations/handlers/jira_handler/jira_tables.py +229 -0
  151. mindsdb/integrations/handlers/jira_handler/requirements.txt +1 -0
  152. mindsdb/integrations/handlers/kinetica_handler/__init__.py +0 -1
  153. mindsdb/integrations/handlers/langchain_handler/langchain_handler.py +4 -4
  154. mindsdb/integrations/handlers/langchain_handler/tools.py +9 -10
  155. mindsdb/integrations/handlers/leonardoai_handler/__init__.py +1 -1
  156. mindsdb/integrations/handlers/lightfm_handler/requirements.txt +1 -0
  157. mindsdb/integrations/handlers/lightwood_handler/functions.py +2 -2
  158. mindsdb/integrations/handlers/lightwood_handler/lightwood_handler.py +0 -3
  159. mindsdb/integrations/handlers/lightwood_handler/requirements.txt +4 -4
  160. mindsdb/integrations/handlers/lightwood_handler/tests/test_lightwood_handler.py +11 -11
  161. mindsdb/integrations/handlers/lindorm_handler/requirements.txt +1 -0
  162. mindsdb/integrations/handlers/llama_index_handler/llama_index_handler.py +4 -4
  163. mindsdb/integrations/handlers/llama_index_handler/settings.py +10 -9
  164. mindsdb/integrations/handlers/materialize_handler/tests/test_materialize_handler.py +8 -10
  165. mindsdb/integrations/handlers/matrixone_handler/matrixone_handler.py +4 -4
  166. mindsdb/integrations/handlers/matrixone_handler/tests/test_matrixone_handler.py +8 -9
  167. mindsdb/integrations/handlers/maxdb_handler/connection_args.py +25 -25
  168. mindsdb/integrations/handlers/maxdb_handler/maxdb_handler.py +1 -0
  169. mindsdb/integrations/handlers/mediawiki_handler/mediawiki_handler.py +3 -2
  170. mindsdb/integrations/handlers/mediawiki_handler/mediawiki_tables.py +1 -1
  171. mindsdb/integrations/handlers/mendeley_handler/__about__.py +1 -1
  172. mindsdb/integrations/handlers/mendeley_handler/__init__.py +2 -2
  173. mindsdb/integrations/handlers/mendeley_handler/mendeley_handler.py +48 -56
  174. mindsdb/integrations/handlers/mendeley_handler/mendeley_tables.py +24 -29
  175. mindsdb/integrations/handlers/mendeley_handler/tests/test_mendeley_handler.py +19 -17
  176. mindsdb/integrations/handlers/merlion_handler/merlion_handler.py +5 -4
  177. mindsdb/integrations/handlers/minds_endpoint_handler/__init__.py +3 -3
  178. mindsdb/integrations/handlers/mlflow_handler/mlflow_handler.py +58 -36
  179. mindsdb/integrations/handlers/monetdb_handler/__about__.py +8 -8
  180. mindsdb/integrations/handlers/monetdb_handler/__init__.py +15 -5
  181. mindsdb/integrations/handlers/monetdb_handler/connection_args.py +17 -18
  182. mindsdb/integrations/handlers/monetdb_handler/monetdb_handler.py +40 -57
  183. mindsdb/integrations/handlers/monetdb_handler/tests/test_monetdb_handler.py +7 -8
  184. mindsdb/integrations/handlers/monetdb_handler/utils/monet_get_id.py +13 -14
  185. mindsdb/integrations/handlers/monkeylearn_handler/__about__.py +1 -1
  186. mindsdb/integrations/handlers/monkeylearn_handler/__init__.py +1 -1
  187. mindsdb/integrations/handlers/monkeylearn_handler/monkeylearn_handler.py +2 -5
  188. mindsdb/integrations/handlers/ms_one_drive_handler/ms_graph_api_one_drive_client.py +1 -0
  189. mindsdb/integrations/handlers/ms_one_drive_handler/ms_one_drive_handler.py +1 -1
  190. mindsdb/integrations/handlers/ms_one_drive_handler/requirements.txt +2 -0
  191. mindsdb/integrations/handlers/ms_teams_handler/ms_graph_api_teams_client.py +23 -23
  192. mindsdb/integrations/handlers/ms_teams_handler/ms_teams_handler.py +3 -3
  193. mindsdb/integrations/handlers/ms_teams_handler/ms_teams_tables.py +10 -5
  194. mindsdb/integrations/handlers/ms_teams_handler/requirements.txt +3 -1
  195. mindsdb/integrations/handlers/mssql_handler/mssql_handler.py +73 -8
  196. mindsdb/integrations/handlers/mysql_handler/__about__.py +8 -8
  197. mindsdb/integrations/handlers/mysql_handler/__init__.py +15 -5
  198. mindsdb/integrations/handlers/mysql_handler/connection_args.py +43 -47
  199. mindsdb/integrations/handlers/mysql_handler/mysql_handler.py +101 -34
  200. mindsdb/integrations/handlers/mysql_handler/settings.py +15 -13
  201. mindsdb/integrations/handlers/neuralforecast_handler/neuralforecast_handler.py +1 -1
  202. mindsdb/integrations/handlers/newsapi_handler/newsapi_handler.py +1 -1
  203. mindsdb/integrations/handlers/newsapi_handler/tests/test_newsapi_handler.py +4 -4
  204. mindsdb/integrations/handlers/nuo_jdbc_handler/connection_args.py +2 -2
  205. mindsdb/integrations/handlers/nuo_jdbc_handler/nuo_jdbc_handler.py +28 -36
  206. mindsdb/integrations/handlers/nuo_jdbc_handler/tests/test_nuo_handler.py +5 -5
  207. mindsdb/integrations/handlers/oceanbase_handler/oceanbase_handler.py +0 -1
  208. mindsdb/integrations/handlers/oceanbase_handler/tests/test_oceanbase_handler.py +8 -10
  209. mindsdb/integrations/handlers/ollama_handler/ollama_handler.py +3 -3
  210. mindsdb/integrations/handlers/openai_handler/openai_handler.py +5 -4
  211. mindsdb/integrations/handlers/opengauss_handler/tests/test_opengauss_handler.py +1 -2
  212. mindsdb/integrations/handlers/openstreetmap_handler/__init__.py +7 -7
  213. mindsdb/integrations/handlers/oracle_handler/connection_args.py +6 -0
  214. mindsdb/integrations/handlers/oracle_handler/oracle_handler.py +77 -11
  215. mindsdb/integrations/handlers/orioledb_handler/tests/test_orioledb_handler.py +8 -10
  216. mindsdb/integrations/handlers/palm_handler/__about__.py +1 -1
  217. mindsdb/integrations/handlers/palm_handler/__init__.py +1 -1
  218. mindsdb/integrations/handlers/palm_handler/palm_handler.py +1 -3
  219. mindsdb/integrations/handlers/paypal_handler/paypal_handler.py +2 -2
  220. mindsdb/integrations/handlers/paypal_handler/paypal_tables.py +15 -14
  221. mindsdb/integrations/handlers/pgvector_handler/pgvector_handler.py +53 -10
  222. mindsdb/integrations/handlers/phoenix_handler/__init__.py +1 -1
  223. mindsdb/integrations/handlers/phoenix_handler/phoenix_handler.py +1 -0
  224. mindsdb/integrations/handlers/pinot_handler/__init__.py +1 -1
  225. mindsdb/integrations/handlers/pinot_handler/pinot_handler.py +3 -2
  226. mindsdb/integrations/handlers/plaid_handler/plaid_handler.py +13 -13
  227. mindsdb/integrations/handlers/plaid_handler/plaid_tables.py +10 -12
  228. mindsdb/integrations/handlers/plaid_handler/utils.py +4 -6
  229. mindsdb/integrations/handlers/planetscale_handler/planetscale_handler.py +1 -4
  230. mindsdb/integrations/handlers/portkey_handler/__init__.py +2 -2
  231. mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +105 -24
  232. mindsdb/integrations/handlers/postgres_handler/tests/test_postgres_handler.py +11 -6
  233. mindsdb/integrations/handlers/questdb_handler/questdb_handler.py +1 -2
  234. mindsdb/integrations/handlers/questdb_handler/tests/test_questdb_handler.py +2 -3
  235. mindsdb/integrations/handlers/quickbooks_handler/quickbooks_handler.py +6 -8
  236. mindsdb/integrations/handlers/quickbooks_handler/quickbooks_table.py +10 -10
  237. mindsdb/integrations/handlers/rag_handler/ingest.py +2 -2
  238. mindsdb/integrations/handlers/rag_handler/rag_handler.py +1 -1
  239. mindsdb/integrations/handlers/rag_handler/settings.py +1 -1
  240. mindsdb/integrations/handlers/reddit_handler/reddit_handler.py +2 -7
  241. mindsdb/integrations/handlers/reddit_handler/reddit_tables.py +2 -3
  242. mindsdb/integrations/handlers/replicate_handler/replicate_handler.py +6 -6
  243. mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_handler.py +1 -2
  244. mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_tables.py +0 -3
  245. mindsdb/integrations/handlers/rockset_handler/connection_args.py +14 -14
  246. mindsdb/integrations/handlers/rockset_handler/tests/test_rockset_handler.py +1 -0
  247. mindsdb/integrations/handlers/scylla_handler/scylla_handler.py +6 -5
  248. mindsdb/integrations/handlers/sendinblue_handler/sendinblue_handler.py +2 -1
  249. mindsdb/integrations/handlers/sendinblue_handler/sendinblue_tables.py +16 -16
  250. mindsdb/integrations/handlers/sentence_transformers_handler/__init__.py +1 -1
  251. mindsdb/integrations/handlers/sheets_handler/connection_args.py +1 -1
  252. mindsdb/integrations/handlers/shopify_handler/shopify_handler.py +7 -6
  253. mindsdb/integrations/handlers/shopify_handler/shopify_tables.py +38 -41
  254. mindsdb/integrations/handlers/singlestore_handler/__about__.py +1 -1
  255. mindsdb/integrations/handlers/singlestore_handler/__init__.py +0 -1
  256. mindsdb/integrations/handlers/singlestore_handler/singlestore_handler.py +1 -0
  257. mindsdb/integrations/handlers/singlestore_handler/tests/test_singlestore_handler.py +3 -3
  258. mindsdb/integrations/handlers/slack_handler/__init__.py +3 -3
  259. mindsdb/integrations/handlers/snowflake_handler/requirements.txt +1 -1
  260. mindsdb/integrations/handlers/snowflake_handler/snowflake_handler.py +100 -6
  261. mindsdb/integrations/handlers/solr_handler/connection_args.py +7 -7
  262. mindsdb/integrations/handlers/solr_handler/solr_handler.py +2 -1
  263. mindsdb/integrations/handlers/solr_handler/tests/test_solr_handler.py +2 -1
  264. mindsdb/integrations/handlers/sqlany_handler/sqlany_handler.py +3 -2
  265. mindsdb/integrations/handlers/sqlite_handler/sqlite_handler.py +1 -0
  266. mindsdb/integrations/handlers/sqreamdb_handler/connection_args.py +1 -1
  267. mindsdb/integrations/handlers/sqreamdb_handler/sqreamdb_handler.py +15 -20
  268. mindsdb/integrations/handlers/sqreamdb_handler/tests/test_sqreamdb_handler.py +4 -4
  269. mindsdb/integrations/handlers/stabilityai_handler/__init__.py +1 -1
  270. mindsdb/integrations/handlers/starrocks_handler/starrocks_handler.py +0 -1
  271. mindsdb/integrations/handlers/starrocks_handler/tests/test_starrocks_handler.py +8 -10
  272. mindsdb/integrations/handlers/statsforecast_handler/statsforecast_handler.py +2 -2
  273. mindsdb/integrations/handlers/strava_handler/strava_handler.py +4 -8
  274. mindsdb/integrations/handlers/strava_handler/strava_tables.py +22 -30
  275. mindsdb/integrations/handlers/stripe_handler/stripe_handler.py +3 -2
  276. mindsdb/integrations/handlers/stripe_handler/stripe_tables.py +11 -27
  277. mindsdb/integrations/handlers/supabase_handler/tests/test_supabase_handler.py +1 -1
  278. mindsdb/integrations/handlers/surrealdb_handler/surrealdb_handler.py +4 -4
  279. mindsdb/integrations/handlers/tdengine_handler/tdengine_handler.py +25 -27
  280. mindsdb/integrations/handlers/tdengine_handler/tests/test_tdengine_handler.py +8 -8
  281. mindsdb/integrations/handlers/tidb_handler/tests/test_tidb_handler.py +1 -2
  282. mindsdb/integrations/handlers/timegpt_handler/timegpt_handler.py +5 -5
  283. mindsdb/integrations/handlers/tpot_handler/tpot_handler.py +21 -26
  284. mindsdb/integrations/handlers/trino_handler/trino_handler.py +14 -14
  285. mindsdb/integrations/handlers/twitter_handler/twitter_handler.py +2 -4
  286. mindsdb/integrations/handlers/unify_handler/tests/test_unify_handler.py +7 -8
  287. mindsdb/integrations/handlers/unify_handler/unify_handler.py +9 -9
  288. mindsdb/integrations/handlers/vertex_handler/requirements.txt +1 -0
  289. mindsdb/integrations/handlers/vertex_handler/vertex_client.py +1 -1
  290. mindsdb/integrations/handlers/vertica_handler/tests/test_vertica_handler.py +11 -11
  291. mindsdb/integrations/handlers/vertica_handler/vertica_handler.py +11 -14
  292. mindsdb/integrations/handlers/vitess_handler/tests/test_vitess_handler.py +9 -11
  293. mindsdb/integrations/handlers/vitess_handler/vitess_handler.py +0 -1
  294. mindsdb/integrations/handlers/web_handler/web_handler.py +1 -0
  295. mindsdb/integrations/handlers/whatsapp_handler/__init__.py +3 -3
  296. mindsdb/integrations/handlers/writer_handler/evaluate.py +1 -1
  297. mindsdb/integrations/handlers/writer_handler/settings.py +0 -1
  298. mindsdb/integrations/handlers/writer_handler/writer_handler.py +1 -0
  299. mindsdb/integrations/handlers/youtube_handler/requirements.txt +1 -0
  300. mindsdb/integrations/handlers/youtube_handler/youtube_handler.py +5 -5
  301. mindsdb/integrations/handlers/youtube_handler/youtube_tables.py +26 -27
  302. mindsdb/integrations/handlers/yugabyte_handler/tests/test_yugabyte_handler.py +3 -3
  303. mindsdb/integrations/handlers/yugabyte_handler/yugabyte_handler.py +0 -6
  304. mindsdb/integrations/libs/response.py +67 -52
  305. mindsdb/integrations/libs/vectordatabase_handler.py +6 -0
  306. mindsdb/integrations/utilities/files/file_reader.py +5 -2
  307. mindsdb/integrations/utilities/handler_utils.py +15 -3
  308. mindsdb/integrations/utilities/handlers/api_utilities/__init__.py +0 -1
  309. mindsdb/integrations/utilities/handlers/auth_utilities/__init__.py +0 -2
  310. mindsdb/integrations/utilities/utils.py +3 -3
  311. mindsdb/interfaces/agents/agents_controller.py +164 -1
  312. mindsdb/interfaces/agents/constants.py +29 -2
  313. mindsdb/interfaces/agents/langchain_agent.py +18 -8
  314. mindsdb/interfaces/agents/mindsdb_database_agent.py +101 -2
  315. mindsdb/interfaces/database/projects.py +1 -7
  316. mindsdb/interfaces/functions/controller.py +11 -14
  317. mindsdb/interfaces/functions/to_markdown.py +9 -124
  318. mindsdb/interfaces/knowledge_base/controller.py +47 -19
  319. mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +41 -15
  320. mindsdb/interfaces/knowledge_base/preprocessing/json_chunker.py +434 -0
  321. mindsdb/interfaces/knowledge_base/preprocessing/models.py +54 -0
  322. mindsdb/interfaces/knowledge_base/utils.py +10 -15
  323. mindsdb/interfaces/model/model_controller.py +0 -2
  324. mindsdb/interfaces/query_context/context_controller.py +66 -10
  325. mindsdb/interfaces/skills/custom/text2sql/mindsdb_kb_tools.py +190 -0
  326. mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +92 -0
  327. mindsdb/interfaces/skills/skill_tool.py +202 -57
  328. mindsdb/interfaces/skills/sql_agent.py +238 -28
  329. mindsdb/interfaces/storage/fs.py +1 -0
  330. mindsdb/interfaces/variables/__init__.py +0 -0
  331. mindsdb/interfaces/variables/variables_controller.py +97 -0
  332. mindsdb/migrations/env.py +5 -7
  333. mindsdb/migrations/migrate.py +47 -9
  334. mindsdb/migrations/versions/2025-05-21_9f150e4f9a05_checkpoint_1.py +360 -0
  335. mindsdb/utilities/config.py +333 -220
  336. mindsdb/utilities/context.py +1 -1
  337. mindsdb/utilities/functions.py +0 -36
  338. mindsdb/utilities/langfuse.py +19 -10
  339. mindsdb/utilities/otel/__init__.py +9 -193
  340. mindsdb/utilities/otel/metric_handlers/__init__.py +5 -1
  341. mindsdb/utilities/otel/prepare.py +198 -0
  342. mindsdb/utilities/sql.py +83 -0
  343. mindsdb/utilities/starters.py +13 -0
  344. {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/METADATA +351 -338
  345. {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/RECORD +348 -322
  346. {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/WHEEL +1 -1
  347. mindsdb/api/mysql/mysql_proxy/classes/sql_statement_parser.py +0 -151
  348. mindsdb/integrations/handlers/monkeylearn_handler/requirements.txt +0 -1
  349. {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/licenses/LICENSE +0 -0
  350. {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,594 @@
1
+ from typing import AsyncIterable
2
+ from .common.types import (
3
+ SendTaskRequest,
4
+ TaskSendParams,
5
+ Message,
6
+ TaskStatus,
7
+ Artifact,
8
+ TaskStatusUpdateEvent,
9
+ TaskArtifactUpdateEvent,
10
+ TaskState,
11
+ Task,
12
+ SendTaskResponse,
13
+ InternalError,
14
+ JSONRPCResponse,
15
+ SendTaskStreamingRequest,
16
+ SendTaskStreamingResponse,
17
+ InvalidRequestError,
18
+ )
19
+ from .common.server.task_manager import InMemoryTaskManager
20
+ from .agent import MindsDBAgent
21
+
22
+ from typing import Union
23
+ import logging
24
+ import asyncio
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ class AgentTaskManager(InMemoryTaskManager):
30
+
31
+ def __init__(
32
+ self,
33
+ project_name: str,
34
+ mindsdb_host: str,
35
+ mindsdb_port: int,
36
+ agent_name: str = None,
37
+ ):
38
+ super().__init__()
39
+ self.project_name = project_name
40
+ self.mindsdb_host = mindsdb_host
41
+ self.mindsdb_port = mindsdb_port
42
+ self.agent_name = agent_name
43
+ self.tasks = {} # Task storage
44
+ self.lock = asyncio.Lock() # Lock for task operations
45
+
46
+ def _create_agent(self, agent_name: str = None) -> MindsDBAgent:
47
+ """Create a new MindsDBAgent instance for the given agent name."""
48
+ if not agent_name:
49
+ raise ValueError(
50
+ "Agent name is required but was not provided in the request"
51
+ )
52
+
53
+ return MindsDBAgent(
54
+ agent_name=agent_name,
55
+ project_name=self.project_name,
56
+ host=self.mindsdb_host,
57
+ port=self.mindsdb_port,
58
+ )
59
+
60
+ async def _stream_generator(
61
+ self, request: SendTaskStreamingRequest
62
+ ) -> AsyncIterable[SendTaskStreamingResponse]:
63
+ task_send_params: TaskSendParams = request.params
64
+ query = self._get_user_query(task_send_params)
65
+ params = self._get_task_params(task_send_params)
66
+ agent_name = params["agent_name"]
67
+ streaming = params["streaming"]
68
+
69
+ # Create and store the task first to ensure it exists
70
+ try:
71
+ await self.upsert_task(task_send_params)
72
+ except Exception as e:
73
+ logger.error(f"Error creating task: {str(e)}")
74
+ yield SendTaskStreamingResponse(
75
+ id=request.id,
76
+ error=InternalError(message=f"Error creating task: {str(e)}"),
77
+ )
78
+ return # Early return from generator
79
+
80
+ agent = self._create_agent(agent_name)
81
+
82
+ if not streaming:
83
+ # If streaming is disabled, use invoke and return a single response
84
+ try:
85
+ result = agent.invoke(query, task_send_params.sessionId)
86
+
87
+ # Use the parts from the agent response if available, or create them
88
+ if "parts" in result:
89
+ parts = result["parts"]
90
+ else:
91
+ result_text = result.get("content", "No response from MindsDB")
92
+ parts = [{"type": "text", "text": result_text}]
93
+
94
+ # Check if we have structured data
95
+ if "data" in result and result["data"]:
96
+ parts.append(
97
+ {
98
+ "type": "data",
99
+ "data": result["data"],
100
+ "metadata": {"subtype": "json"},
101
+ }
102
+ )
103
+
104
+ # Create and yield the final response
105
+ task_state = TaskState.COMPLETED
106
+ artifact = Artifact(parts=parts, index=0, append=False)
107
+ task_status = TaskStatus(state=task_state)
108
+
109
+ # Update the task store
110
+ await self._update_store(task_send_params.id, task_status, [artifact])
111
+
112
+ # Yield the artifact update
113
+ yield SendTaskStreamingResponse(
114
+ id=request.id,
115
+ result=TaskArtifactUpdateEvent(
116
+ id=task_send_params.id, artifact=artifact
117
+ ),
118
+ )
119
+
120
+ # Yield the final status update
121
+ yield SendTaskStreamingResponse(
122
+ id=request.id,
123
+ result=TaskStatusUpdateEvent(
124
+ id=task_send_params.id,
125
+ status=TaskStatus(state=task_status.state),
126
+ final=True,
127
+ ),
128
+ )
129
+ return
130
+
131
+ except Exception as e:
132
+ logger.error(f"Error invoking agent: {e}")
133
+ yield JSONRPCResponse(
134
+ id=request.id,
135
+ error=InternalError(message=f"Error invoking agent: {str(e)}"),
136
+ )
137
+ return
138
+
139
+ # If streaming is enabled (default), use the streaming implementation
140
+ try:
141
+ # Track the chunks we've seen to avoid duplicates
142
+ seen_chunks = set()
143
+
144
+ async for item in agent.stream(query, task_send_params.sessionId):
145
+ # Ensure item has the required fields or provide defaults
146
+ is_task_complete = item.get("is_task_complete", False)
147
+
148
+ # Create a structured thought dictionary to encapsulate the agent's thought process
149
+ thought_dict = {}
150
+ parts = []
151
+
152
+ # Handle different chunk formats to extract text content
153
+ if "actions" in item:
154
+ # Extract thought process from actions
155
+ thought_dict["type"] = "thought"
156
+ thought_dict["actions"] = item["actions"]
157
+
158
+ for action in item.get("actions", []):
159
+ if "log" in action:
160
+ # Use "text" type for all parts, but add a thought_type in metadata
161
+ parts.append(
162
+ {
163
+ "type": "text",
164
+ "text": action["log"],
165
+ "metadata": {"thought_type": "thought"},
166
+ }
167
+ )
168
+ if "tool_input" in action:
169
+ # Include SQL queries
170
+ tool_input = action.get("tool_input", "")
171
+ if "$START$" in tool_input and "$STOP$" in tool_input:
172
+ sql = tool_input.replace("$START$", "").replace(
173
+ "$STOP$", ""
174
+ )
175
+ parts.append(
176
+ {
177
+ "type": "text",
178
+ "text": sql,
179
+ "metadata": {"thought_type": "sql"},
180
+ }
181
+ )
182
+
183
+ elif "steps" in item:
184
+ # Extract observations from steps
185
+ thought_dict["type"] = "observation"
186
+ thought_dict["steps"] = item["steps"]
187
+
188
+ for step in item.get("steps", []):
189
+ if "observation" in step:
190
+ parts.append(
191
+ {
192
+ "type": "text",
193
+ "text": step["observation"],
194
+ "metadata": {"thought_type": "observation"},
195
+ }
196
+ )
197
+ if "action" in step and "log" in step["action"]:
198
+ parts.append(
199
+ {
200
+ "type": "text",
201
+ "text": step["action"]["log"],
202
+ "metadata": {"thought_type": "thought"},
203
+ }
204
+ )
205
+
206
+ elif "output" in item:
207
+ # Final answer
208
+ thought_dict["type"] = "answer"
209
+ thought_dict["output"] = item["output"]
210
+ parts.append({"type": "text", "text": item["output"]})
211
+
212
+ elif "parts" in item and item["parts"]:
213
+ # Use existing parts, but ensure they have valid types
214
+ for part in item["parts"]:
215
+ if part.get("type") in ["text", "file", "data"]:
216
+ # Valid type, use as is
217
+ parts.append(part)
218
+ else:
219
+ # Invalid type, convert to text
220
+ text_content = part.get("text", "")
221
+ if not text_content and "content" in part:
222
+ text_content = part["content"]
223
+
224
+ new_part = {"type": "text", "text": text_content}
225
+
226
+ # Preserve metadata if it exists
227
+ if "metadata" in part:
228
+ new_part["metadata"] = part["metadata"]
229
+ else:
230
+ new_part["metadata"] = {
231
+ "thought_type": part.get("type", "text")
232
+ }
233
+
234
+ parts.append(new_part)
235
+
236
+ # Try to determine the type from parts for the thought dictionary
237
+ for part in item["parts"]:
238
+ if part.get("type") == "text" and part.get(
239
+ "text", ""
240
+ ).startswith("$START$"):
241
+ thought_dict["type"] = "sql"
242
+ thought_dict["query"] = part.get("text")
243
+ else:
244
+ thought_dict["type"] = "text"
245
+
246
+ elif "content" in item:
247
+ # Simple content
248
+ thought_dict["type"] = "text"
249
+ thought_dict["content"] = item["content"]
250
+ parts.append({"type": "text", "text": item["content"]})
251
+
252
+ elif "messages" in item:
253
+ # Extract content from messages
254
+ thought_dict["type"] = "message"
255
+ thought_dict["messages"] = item["messages"]
256
+
257
+ for message in item.get("messages", []):
258
+ if "content" in message:
259
+ parts.append(
260
+ {
261
+ "type": "text",
262
+ "text": message["content"],
263
+ "metadata": {"thought_type": "message"},
264
+ }
265
+ )
266
+
267
+ # Skip if we have no parts to send
268
+ if not parts:
269
+ continue
270
+
271
+ # Process each part individually to ensure true streaming
272
+ for part in parts:
273
+ # Generate a unique key for this part to avoid duplicates
274
+ part_key = str(part)
275
+ if part_key in seen_chunks:
276
+ continue
277
+ seen_chunks.add(part_key)
278
+
279
+ # Ensure metadata exists
280
+ metadata = item.get("metadata", {})
281
+
282
+ # Add the thought dictionary to metadata for frontend parsing
283
+ if thought_dict:
284
+ metadata["thought_process"] = thought_dict
285
+
286
+ # Handle error field if present
287
+ if "error" in item and not is_task_complete:
288
+ logger.warning(f"Error in streaming response: {item['error']}")
289
+ # Mark as complete if there's an error
290
+ is_task_complete = True
291
+
292
+ if not is_task_complete:
293
+ # Create a message with just this part and send it immediately
294
+ task_state = TaskState.WORKING
295
+ message = Message(role="agent", parts=[part], metadata=metadata)
296
+ task_status = TaskStatus(state=task_state, message=message)
297
+ await self._update_store(task_send_params.id, task_status, [])
298
+ task_update_event = TaskStatusUpdateEvent(
299
+ id=task_send_params.id,
300
+ status=task_status,
301
+ final=False,
302
+ )
303
+ yield SendTaskStreamingResponse(
304
+ id=request.id, result=task_update_event
305
+ )
306
+
307
+ # If this is the final chunk, send a completion message
308
+ if is_task_complete:
309
+ task_state = TaskState.COMPLETED
310
+ artifact = Artifact(parts=parts, index=0, append=False)
311
+ task_status = TaskStatus(state=task_state)
312
+ yield SendTaskStreamingResponse(
313
+ id=request.id,
314
+ result=TaskArtifactUpdateEvent(
315
+ id=task_send_params.id, artifact=artifact
316
+ ),
317
+ )
318
+ await self._update_store(
319
+ task_send_params.id, task_status, [artifact]
320
+ )
321
+ yield SendTaskStreamingResponse(
322
+ id=request.id,
323
+ result=TaskStatusUpdateEvent(
324
+ id=task_send_params.id,
325
+ status=TaskStatus(
326
+ state=task_status.state,
327
+ ),
328
+ final=True,
329
+ ),
330
+ )
331
+
332
+ except Exception as e:
333
+ logger.error(f"An error occurred while streaming the response: {e}")
334
+ error_text = f"An error occurred while streaming the response: {str(e)}"
335
+ parts = [{"type": "text", "text": error_text}]
336
+
337
+ # First send the error as an artifact
338
+ artifact = Artifact(parts=parts, index=0, append=False)
339
+ yield SendTaskStreamingResponse(
340
+ id=request.id,
341
+ result=TaskArtifactUpdateEvent(
342
+ id=task_send_params.id, artifact=artifact
343
+ ),
344
+ )
345
+
346
+ # Then mark the task as completed with an error
347
+ task_state = TaskState.FAILED
348
+ task_status = TaskStatus(state=task_state)
349
+ await self._update_store(task_send_params.id, task_status, [artifact])
350
+
351
+ # Send the final status update
352
+ yield SendTaskStreamingResponse(
353
+ id=request.id,
354
+ result=TaskStatusUpdateEvent(
355
+ id=task_send_params.id,
356
+ status=TaskStatus(
357
+ state=task_status.state,
358
+ ),
359
+ final=True,
360
+ ),
361
+ )
362
+
363
+ async def upsert_task(self, task_send_params: TaskSendParams) -> Task:
364
+ """Create or update a task in the task store.
365
+
366
+ Args:
367
+ task_send_params: The parameters for the task.
368
+
369
+ Returns:
370
+ The created or updated task.
371
+ """
372
+ logger.info(f"Upserting task {task_send_params.id}")
373
+ async with self.lock:
374
+ task = self.tasks.get(task_send_params.id)
375
+ if task is None:
376
+ # Convert the message to a dict if it's not already one
377
+ message = task_send_params.message
378
+ message_dict = message.dict() if hasattr(message, "dict") else message
379
+
380
+ # Create a new task
381
+ task = Task(
382
+ id=task_send_params.id,
383
+ sessionId=task_send_params.sessionId,
384
+ messages=[message_dict],
385
+ status=TaskStatus(state=TaskState.SUBMITTED),
386
+ history=[message_dict],
387
+ artifacts=[],
388
+ )
389
+ self.tasks[task_send_params.id] = task
390
+ else:
391
+ # Convert the message to a dict if it's not already one
392
+ message = task_send_params.message
393
+ message_dict = message.dict() if hasattr(message, "dict") else message
394
+
395
+ # Update the existing task
396
+ task.history.append(message_dict)
397
+ return task
398
+
399
+ def _validate_request(
400
+ self, request: Union[SendTaskRequest, SendTaskStreamingRequest]
401
+ ) -> Union[None, JSONRPCResponse]:
402
+ """Validate the request and return an error response if invalid."""
403
+ # Check if the request has the required parameters
404
+ if not hasattr(request, "params") or not request.params:
405
+ return JSONRPCResponse(
406
+ id=request.id,
407
+ error=InvalidRequestError(message="Missing params"),
408
+ )
409
+
410
+ # Check if the request has a message
411
+ if not hasattr(request.params, "message") or not request.params.message:
412
+ return JSONRPCResponse(
413
+ id=request.id,
414
+ error=InvalidRequestError(message="Missing message in params"),
415
+ )
416
+
417
+ # Check if the message has metadata
418
+ if (
419
+ not hasattr(request.params.message, "metadata")
420
+ or not request.params.message.metadata
421
+ ):
422
+ return JSONRPCResponse(
423
+ id=request.id,
424
+ error=InvalidRequestError(message="Missing metadata in message"),
425
+ )
426
+
427
+ # Check if the agent name is provided in the metadata
428
+ metadata = request.params.message.metadata
429
+ agent_name = metadata.get("agent_name", metadata.get("agentName"))
430
+ if not agent_name:
431
+ return JSONRPCResponse(
432
+ id=request.id,
433
+ error=InvalidRequestError(
434
+ message="Agent name is required but was not provided in the request metadata"
435
+ ),
436
+ )
437
+
438
+ return None
439
+
440
+ async def on_send_task(self, request: SendTaskRequest) -> SendTaskResponse:
441
+ error = self._validate_request(request)
442
+ if error:
443
+ return error
444
+
445
+ return await self._invoke(request)
446
+
447
+ async def on_send_task_subscribe(
448
+ self, request: SendTaskStreamingRequest
449
+ ) -> AsyncIterable[SendTaskStreamingResponse]:
450
+ error = self._validate_request(request)
451
+ if error:
452
+ # Convert JSONRPCResponse to SendTaskStreamingResponse
453
+ yield SendTaskStreamingResponse(id=request.id, error=error.error)
454
+ return
455
+
456
+ # We can't await an async generator directly, so we need to use it as is
457
+ try:
458
+ async for response in self._stream_generator(request):
459
+ yield response
460
+ except Exception as e:
461
+ # If an error occurs, yield an error response
462
+ logger.error(f"Error in on_send_task_subscribe: {str(e)}")
463
+ yield SendTaskStreamingResponse(
464
+ id=request.id,
465
+ error=InternalError(
466
+ message=f"Error processing streaming request: {str(e)}"
467
+ ),
468
+ )
469
+
470
+ async def _update_store(
471
+ self, task_id: str, status: TaskStatus, artifacts: list[Artifact]
472
+ ) -> Task:
473
+ async with self.lock:
474
+ try:
475
+ task = self.tasks[task_id]
476
+ except KeyError:
477
+ logger.error(f"Task {task_id} not found for updating the task")
478
+ # Create a new task with the provided ID if it doesn't exist
479
+ # This ensures we don't fail when a task is not found
480
+ task = Task(
481
+ id=task_id,
482
+ sessionId="recovery-session", # Use a placeholder session ID
483
+ messages=[], # No messages available
484
+ status=status, # Use the provided status
485
+ history=[], # No history available
486
+ )
487
+ self.tasks[task_id] = task
488
+
489
+ task.status = status
490
+ if artifacts is not None:
491
+ for artifact in artifacts:
492
+ if artifact.append and len(task.artifacts) > 0:
493
+ # Append to the last artifact
494
+ last_artifact = task.artifacts[-1]
495
+ for part in artifact.parts:
496
+ last_artifact.parts.append(part)
497
+ else:
498
+ # Add as a new artifact
499
+ task.artifacts.append(artifact)
500
+ return task
501
+
502
+ def _get_user_query(self, task_send_params: TaskSendParams) -> str:
503
+ """Extract the user query from the task parameters."""
504
+ message = task_send_params.message
505
+ if not message.parts:
506
+ return ""
507
+
508
+ # Find the first text part
509
+ for part in message.parts:
510
+ if part.type == "text":
511
+ return part.text
512
+
513
+ # If no text part found, return empty string
514
+ return ""
515
+
516
+ def _get_task_params(self, task_send_params: TaskSendParams) -> dict:
517
+ """Extract common parameters from task metadata."""
518
+ metadata = task_send_params.message.metadata or {}
519
+ # Check for both agent_name and agentName in the metadata
520
+ agent_name = metadata.get("agent_name", metadata.get("agentName"))
521
+ return {
522
+ "agent_name": agent_name,
523
+ "streaming": metadata.get("streaming", True),
524
+ "session_id": task_send_params.sessionId,
525
+ }
526
+
527
+ async def _invoke(self, request: SendTaskRequest) -> SendTaskResponse:
528
+ task_send_params: TaskSendParams = request.params
529
+ query = self._get_user_query(task_send_params)
530
+ params = self._get_task_params(task_send_params)
531
+ agent_name = params["agent_name"]
532
+ streaming = params["streaming"]
533
+ agent = self._create_agent(agent_name)
534
+
535
+ try:
536
+ # Always use streaming internally, but handle the response differently based on the streaming parameter
537
+ all_parts = []
538
+ final_metadata = {}
539
+
540
+ # Create a streaming generator
541
+ stream_gen = agent.stream(query, task_send_params.sessionId)
542
+
543
+ if streaming:
544
+ # For streaming mode, we'll use the streaming endpoint instead
545
+ # Just create a minimal response to acknowledge the request
546
+ task_state = TaskState.WORKING
547
+ task = await self._update_store(
548
+ task_send_params.id, TaskStatus(state=task_state), []
549
+ )
550
+ return SendTaskResponse(id=request.id, result=task)
551
+ else:
552
+ # For non-streaming mode, collect all chunks into a single response
553
+ async for chunk in stream_gen:
554
+ # Extract parts if they exist
555
+ if "parts" in chunk and chunk["parts"]:
556
+ all_parts.extend(chunk["parts"])
557
+ elif "content" in chunk:
558
+ all_parts.append({"type": "text", "text": chunk["content"]})
559
+
560
+ # Extract metadata if it exists
561
+ if "metadata" in chunk:
562
+ final_metadata.update(chunk["metadata"])
563
+
564
+ # If we didn't get any parts, create a default part
565
+ if not all_parts:
566
+ all_parts = [{"type": "text", "text": "No response from MindsDB"}]
567
+
568
+ # Create the final response
569
+ task_state = TaskState.COMPLETED
570
+ task = await self._update_store(
571
+ task_send_params.id,
572
+ TaskStatus(
573
+ state=task_state,
574
+ message=Message(
575
+ role="agent", parts=all_parts, metadata=final_metadata
576
+ ),
577
+ ),
578
+ [Artifact(parts=all_parts)],
579
+ )
580
+ return SendTaskResponse(id=request.id, result=task)
581
+ except Exception as e:
582
+ logger.error(f"Error invoking agent: {e}")
583
+ result_text = f"Error invoking agent: {e}"
584
+ parts = [{"type": "text", "text": result_text}]
585
+
586
+ task_state = TaskState.FAILED
587
+ task = await self._update_store(
588
+ task_send_params.id,
589
+ TaskStatus(
590
+ state=task_state, message=Message(role="agent", parts=parts)
591
+ ),
592
+ [Artifact(parts=parts)],
593
+ )
594
+ return SendTaskResponse(id=request.id, result=task)