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