MindsDB 25.5.4.0__py3-none-any.whl → 25.5.4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of MindsDB might be problematic. Click here for more details.

@@ -1,19 +1,15 @@
1
- mindsdb/__about__.py,sha256=qdyLrPJthOack70IzRcKOJ9is1w28JD60cFxanFX8sQ,456
1
+ mindsdb/__about__.py,sha256=QDcsJNqSqjZ8PJ0cUrDKDkRlBeCubeeLB5R6sxAlm1U,456
2
2
  mindsdb/__init__.py,sha256=fZopLiAYa9MzMZ0d48JgHc_LddfFKDzh7n_8icsjrVs,54
3
3
  mindsdb/__main__.py,sha256=bkLqiYLsx1KyCyi6tJjyMBkpMvO3g37wOC0PymMbiHU,24037
4
4
  mindsdb/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  mindsdb/api/a2a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- mindsdb/api/a2a/__main__.py,sha256=x8-7l-S3j6DpxQUrg6Y9yOGG2vC77DqYNi2gPNy25EE,3592
7
- mindsdb/api/a2a/a2a_client.py,sha256=Lyw7CFj031pZNK_wvY4MAR1ptZoDRaitbCi0jmN4wQA,13634
6
+ mindsdb/api/a2a/__main__.py,sha256=zrzTzt9zgN38NImInrmxCsdr66urJNS0JOq0xJaKHac,4712
8
7
  mindsdb/api/a2a/agent.py,sha256=DN3VCsdFuoFBXyQDeH4C9pNGnHSEM-KnHSCjL-HY4ls,13007
9
8
  mindsdb/api/a2a/constants.py,sha256=1BmvDneWzNG6YJFUc-gZ9CNCO4wq2_12vFe6aw23yX4,2292
10
- mindsdb/api/a2a/run_a2a.py,sha256=7uvTtc6Te4qBiF9I0_48dVBZmY4YmKrMT0jbBwnGGhE,4347
11
- mindsdb/api/a2a/task_manager.py,sha256=7zYsAizpZlE4WlsEotpRSos742dZbzpVyeKvuTaUXLs,24620
9
+ mindsdb/api/a2a/run_a2a.py,sha256=IQa7pSvgDoh7u5V2Ec5flzoeAJsNuSMnkRehEMPrI3Q,2878
10
+ mindsdb/api/a2a/task_manager.py,sha256=SwTwDC4_4pLIm8471Bi10WFvpI7uQ7qFLTDMcpg9mgI,23970
12
11
  mindsdb/api/a2a/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
12
  mindsdb/api/a2a/common/types.py,sha256=EYBpqEj-nZapSKe2jI8BcNDfSlTXXTbw8RcSA1DII9Q,8787
14
- mindsdb/api/a2a/common/client/__init__.py,sha256=V8lbSEpOWNM2XjG5ky7NIUM0Q2HZTexzL3I8WqZfo-w,117
15
- mindsdb/api/a2a/common/client/card_resolver.py,sha256=yCDxwNAgAz-6lDWGr8uhj8V0DGs9kSiybPsmhK3vh8Y,671
16
- mindsdb/api/a2a/common/client/client.py,sha256=VLZaBTf1vhbLq_4Wr5Z4o1PMMW2NsCdTTVQDlGJklA8,3346
17
13
  mindsdb/api/a2a/common/server/__init__.py,sha256=Bl7Qa3Pk4QWY4yDPRNyHeTzNJpAe9HgUJd8-oTnMPv8,152
18
14
  mindsdb/api/a2a/common/server/server.py,sha256=ymnM0HblF9iH1Htay-LfFu-_CQjXieN_ZEgyHYkHPfk,6352
19
15
  mindsdb/api/a2a/common/server/task_manager.py,sha256=NnKO2ZcI-KBWiX4wNc8FbLmnVsb5KeIm62B4jdX73IU,10189
@@ -21,7 +17,7 @@ mindsdb/api/a2a/common/server/utils.py,sha256=1k_fBfECT0JQFlFcAJhpNlTYYOruxDlV0S
21
17
  mindsdb/api/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
18
  mindsdb/api/common/check_auth.py,sha256=cQEZqsnCbrRtUf8j4H6uPF98cDPu79t8TdtwBi5g30w,1345
23
19
  mindsdb/api/executor/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
24
- mindsdb/api/executor/command_executor.py,sha256=uaKdegKhR4cswXE0uN3zuIFlJD8MnohRQ1HSGfFIwag,80825
20
+ mindsdb/api/executor/command_executor.py,sha256=mXpbe1KI83mvJCWK-RVWErr6iAaaq8XQ_eROe98s1I8,78515
25
21
  mindsdb/api/executor/exceptions.py,sha256=SoxhetIKIVOAwbVP_NatfoKnwt-Xj2yFCiAIqSDxpIE,566
26
22
  mindsdb/api/executor/controllers/__init__.py,sha256=px47lPVKqfpqgcoEBHyWoax-ad01rNOTJQCgQmG0Flo,50
27
23
  mindsdb/api/executor/controllers/session_controller.py,sha256=2Jf-V0nj7k0aB4scujNVyx91h54odkDrdK1ydsCo46g,3072
@@ -83,7 +79,7 @@ mindsdb/api/http/namespaces/agents.py,sha256=H3C4MmNCsrk3Dv8Cw1kx0j7EvNOia5PfyfQ
83
79
  mindsdb/api/http/namespaces/analysis.py,sha256=maYxI-TP9RswWHgKX3KAZQJK_XSBQfpZMqv0ZH1ZC0k,4295
84
80
  mindsdb/api/http/namespaces/auth.py,sha256=Qm1ZUBdbv_nTDzSQHdzXEosdpYCRzIa17k1yYErOeuk,5483
85
81
  mindsdb/api/http/namespaces/chatbots.py,sha256=pLSaTzm2GtqJM-RW8MrEQTIJybLRCMbLv99BNABxMjw,11877
86
- mindsdb/api/http/namespaces/config.py,sha256=tC7MItEt_hjpG1O8-y85sEqPtwX_iPj7mNdTQ6zSg-0,8785
82
+ mindsdb/api/http/namespaces/config.py,sha256=eHZybqUA-HryK7zTvEteMqcDw39J-yKtEs3nRdvrtz8,8454
87
83
  mindsdb/api/http/namespaces/databases.py,sha256=QuHD5zSIftfb5qRdPJS3UtZEnfQnf1fp0wVKe98h7Rg,18543
88
84
  mindsdb/api/http/namespaces/default.py,sha256=r8PXn00Um2eyKB5e_Kj7fzk4e4LYH-JCzXCpxgJA2vY,4729
89
85
  mindsdb/api/http/namespaces/file.py,sha256=ONMsQDDC2Ug-O38cbPKSL8UpQ78soQKsPHOfzUj-Bfo,6933
@@ -359,7 +355,7 @@ mindsdb/integrations/handlers/byom_handler/byom_handler.py,sha256=uI-UN2XLx7jAx7
359
355
  mindsdb/integrations/handlers/byom_handler/connection_args.py,sha256=chqPtpiEBtko8kxS15ImkZ6Q3kuhv7vwOzV3JeyU4cU,522
360
356
  mindsdb/integrations/handlers/byom_handler/icon.svg,sha256=q8G2Qws-_E79MdxpSDHtNCqLwK0RWauNmRwGszIs_FE,2542
361
357
  mindsdb/integrations/handlers/byom_handler/proc_wrapper.py,sha256=GqOB8Zw4-SYsn4lu3tkYORaNfgM4bm0HMDPyOJtErKk,5644
362
- mindsdb/integrations/handlers/byom_handler/requirements.txt,sha256=WIPqhfnSGN4zXV7N9gor-Mjk5xsua3vH9ENBltRP9dY,27
358
+ mindsdb/integrations/handlers/byom_handler/requirements.txt,sha256=VSOkZhUmawzRmgjd4WHhL7PW6yP63v3EBL7JmC-WWR4,10
363
359
  mindsdb/integrations/handlers/cassandra_handler/__about__.py,sha256=rMC_DPK11JoHKA9UceTm_jkUOggj04XKkAUqw5P8wXg,347
364
360
  mindsdb/integrations/handlers/cassandra_handler/__init__.py,sha256=US2TGuaKp48HJX_ayeNypltbagOASrnKSSUsCMNjsl4,564
365
361
  mindsdb/integrations/handlers/cassandra_handler/cassandra_handler.py,sha256=HoQPp0Ox20BDCNB8rtrwAEoGLuh7gWDiP4YQC4_pQhU,787
@@ -873,7 +869,7 @@ mindsdb/integrations/handlers/lancedb_handler/__init__.py,sha256=nwShTdkEcKKhiDL
873
869
  mindsdb/integrations/handlers/lancedb_handler/connection_args.py,sha256=KtHvSBLPS9P7LKlXULwRlUTUCvpG69bES2DUL-e2xME,956
874
870
  mindsdb/integrations/handlers/lancedb_handler/icon.svg,sha256=UHDcgJDgSbA74qyN6dLXKquPHXjYHd93g-TyQlIR84s,3475
875
871
  mindsdb/integrations/handlers/lancedb_handler/lancedb_handler.py,sha256=zQik_f_QjArzSrla_uxwYPQIdiKIwnYZIIABQmI__Zc,12399
876
- mindsdb/integrations/handlers/lancedb_handler/requirements.txt,sha256=yBw6h3zm01B_3qmewTg3ymJ1U_nRAenRda4t0i5wvTo,37
872
+ mindsdb/integrations/handlers/lancedb_handler/requirements.txt,sha256=syp4bJ3vJNjPo7QEMRnpjQcNsUTpwiWZeCzg_OVVWnk,21
877
873
  mindsdb/integrations/handlers/lancedb_handler/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
878
874
  mindsdb/integrations/handlers/lancedb_handler/tests/test_lancedb_handler.py,sha256=dHFnAMplZCfXk0DwpDM1gKIsG42vEypx9-51nRoCQZc,3351
879
875
  mindsdb/integrations/handlers/langchain_embedding_handler/__about__.py,sha256=CqrMPm5gho1vYeXuFNSisjwl32JpHR3IoKv3xw_7fx8,388
@@ -935,7 +931,7 @@ mindsdb/integrations/handlers/lindorm_handler/tests/test_lindorm_handler.py,sha2
935
931
  mindsdb/integrations/handlers/litellm_handler/__about__.py,sha256=qKuzAOGHI5gYpkNeGTTulSTMuQdHqmWFPTtJhLil4jw,341
936
932
  mindsdb/integrations/handlers/litellm_handler/__init__.py,sha256=phvu1-lcM1HovXh4GHunND_ScTON4Yb3s4VXNVd_epU,550
937
933
  mindsdb/integrations/handlers/litellm_handler/icon.png,sha256=mfPLH1-n3D1q3U57hADzl7s2G-W-EDevUHzmvnLTjy8,37122
938
- mindsdb/integrations/handlers/litellm_handler/litellm_handler.py,sha256=-C82eH--GVPD-4P7_lPk3GbcTGmyqYLjuGZwW9iQ4pk,4911
934
+ mindsdb/integrations/handlers/litellm_handler/litellm_handler.py,sha256=1lE0R1Z1S4Nwtv5PVfR3uohfxNsO_WNjDe3QJLRYdhM,5625
939
935
  mindsdb/integrations/handlers/litellm_handler/requirements.txt,sha256=dy-zvg7q-XWnmLu6dh1DSphrzDsLZHec2oSRuF-jWmw,18
940
936
  mindsdb/integrations/handlers/litellm_handler/settings.py,sha256=LUnndIS2pqpQB84fLe2AhBWzSzpeHbeoeVNz3T6-Rlk,2301
941
937
  mindsdb/integrations/handlers/llama_index_handler/__about__.py,sha256=BtxlhE6R27NMF-AQRn5hhTK3cSdkyUDU6f9venjZ0dU,359
@@ -1719,8 +1715,8 @@ mindsdb/integrations/libs/response.py,sha256=YMRiPLoQ6UR2jj9XD3yuqniTgyL5xT_p9F8
1719
1715
  mindsdb/integrations/libs/storage_handler.py,sha256=g4rcAD4TzmxWmEtS00235_NAnrdulIir4If6E4y_OUo,3512
1720
1716
  mindsdb/integrations/libs/vectordatabase_handler.py,sha256=p4wWZIl1fq6PnCiHSjTPW5Jlrmdw9MzU7RzKvpDUXVA,18445
1721
1717
  mindsdb/integrations/libs/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1722
- mindsdb/integrations/libs/llm/config.py,sha256=FH5ODdNmiqdwTLHpXmEla0zwEPlitNactTm_i2UUmC0,4337
1723
- mindsdb/integrations/libs/llm/utils.py,sha256=K5jc9NyME4MZWyVyirhgQA_Dq6HRvP4lhJqnlrcjWy0,25101
1718
+ mindsdb/integrations/libs/llm/config.py,sha256=p_N1E3b-KB2g-OT2gC66QP1ahh7VftjXublf4k_uLig,4957
1719
+ mindsdb/integrations/libs/llm/utils.py,sha256=Wz2aptwngVyPX8tVrNx1yUHffpgnMDHQG-e01LoXFwc,25140
1724
1720
  mindsdb/integrations/libs/ml_handler_process/__init__.py,sha256=TW1DslwZTaD8oeGaxPx99uYkPAeDIeHWAturBcnDBFU,756
1725
1721
  mindsdb/integrations/libs/ml_handler_process/create_engine_process.py,sha256=YHbk1x7GEIZXcM0IazB2z2tvu5Yd24Fb4aJPpUg321A,788
1726
1722
  mindsdb/integrations/libs/ml_handler_process/create_validation_process.py,sha256=-69NRhBGnNG0hgNi9O_W5LffIxPBUmuxy4bbQY2Z-_8,444
@@ -1785,7 +1781,7 @@ mindsdb/integrations/utilities/rag/loaders/vector_store_loader/vector_store_load
1785
1781
  mindsdb/integrations/utilities/rag/pipelines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1786
1782
  mindsdb/integrations/utilities/rag/pipelines/rag.py,sha256=Ij91MJ0QpqocHs2vLfLO43PFZPFCyt1mvFjwvDecVU4,15551
1787
1783
  mindsdb/integrations/utilities/rag/rerankers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1788
- mindsdb/integrations/utilities/rag/rerankers/base_reranker.py,sha256=dtXKri1RHsjhbfkgsKDTvrx0MedhFxc6iwlARpJDQ0c,17998
1784
+ mindsdb/integrations/utilities/rag/rerankers/base_reranker.py,sha256=6ZcyEDeiykNKeTH_jH_vGBYA3yAsiIzmumvXVuVVqYc,16005
1789
1785
  mindsdb/integrations/utilities/rag/rerankers/reranker_compressor.py,sha256=IN7R2dtqEtqdhPQh5r62oZOII_4m_ZU-XCpnbvSqjw0,3729
1790
1786
  mindsdb/integrations/utilities/rag/retrievers/__init__.py,sha256=Kuo3AJxzHVXMxPFxGqz2AXNPzjBzyMuk2yQj9pFpOsI,128
1791
1787
  mindsdb/integrations/utilities/rag/retrievers/auto_retriever.py,sha256=ODNXqeBuDfatGQLvKvogO0aA-A5v3Z4xbCbvO5ICvt4,3923
@@ -1800,9 +1796,9 @@ mindsdb/interfaces/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVG
1800
1796
  mindsdb/interfaces/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1801
1797
  mindsdb/interfaces/agents/agents_controller.py,sha256=l_lC08HnE7F_Iki-hm9VznEY8Afmv1-diO7YJIyqfSo,27106
1802
1798
  mindsdb/interfaces/agents/callback_handlers.py,sha256=_iOUz-g5Hglf2wtfpx6ENKNCu2Cba-ZbpQtXyR2xElY,6700
1803
- mindsdb/interfaces/agents/constants.py,sha256=7drGeBdnwJOBnPKgjd8lKhIYu1yYlYrDUxMvStIuEsA,5822
1799
+ mindsdb/interfaces/agents/constants.py,sha256=ms_XhYhxzGcQ27fPKZxZgWvG9H5TdyVOSbsesyCzz4I,5927
1804
1800
  mindsdb/interfaces/agents/event_dispatch_callback_handler.py,sha256=-76yTtxTHO5AkFTtr_RvYfkdUROJHcKZx6KJDZvj_-M,1331
1805
- mindsdb/interfaces/agents/langchain_agent.py,sha256=GUaxPkT7a5qXCKo2j3p-M8qpiJkwLfZv0C3epxbrMAU,28313
1801
+ mindsdb/interfaces/agents/langchain_agent.py,sha256=p_gSmIvIkEkfOlm_vdForcJMBRlqoQeIu3QHrkJU1Ps,28543
1806
1802
  mindsdb/interfaces/agents/langfuse_callback_handler.py,sha256=-51IWB5U2_m71xx00IwSOAK6gJ2n-HD_CzbtbmEfbBQ,11598
1807
1803
  mindsdb/interfaces/agents/litellm_server.py,sha256=j33LqHlUt9XApMozP4mHy9iFGT1Lx7WRqKHwGfJfT8w,11366
1808
1804
  mindsdb/interfaces/agents/mcp_client_agent.py,sha256=9oki-GDsN1H6fYsNLBQWTMYSHGpWliYF9I5AZSuXS8U,9814
@@ -1833,7 +1829,7 @@ mindsdb/interfaces/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
1833
1829
  mindsdb/interfaces/jobs/jobs_controller.py,sha256=2-L61saLbpaQ4hAT_HepIq0DUqdUxsPuNNMkj3ZfAJk,18299
1834
1830
  mindsdb/interfaces/jobs/scheduler.py,sha256=eHBWTpZozI_AC-hKmg4p0qRoGZW8O3gEt5Y9nDhHWpw,3696
1835
1831
  mindsdb/interfaces/knowledge_base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1836
- mindsdb/interfaces/knowledge_base/controller.py,sha256=UZww7HeADl03JC6GkfjVI8SuoZiylf2B_qqeX_pLiOQ,46617
1832
+ mindsdb/interfaces/knowledge_base/controller.py,sha256=DOiZpyN5iLukWL96cA0sFVrdL36Lkfd9q3KFsrXMsDE,48218
1837
1833
  mindsdb/interfaces/knowledge_base/utils.py,sha256=gRWJkHVic5mOy1rnjd7eON5mo7rdAyxVYfEbg0iJxmk,855
1838
1834
  mindsdb/interfaces/knowledge_base/preprocessing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1839
1835
  mindsdb/interfaces/knowledge_base/preprocessing/constants.py,sha256=iW5q65albIfTT1ZuxNceJ8o7yrOcttCH1Kx4Vdo-iPY,296
@@ -1945,7 +1941,7 @@ mindsdb/migrations/versions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
1945
1941
  mindsdb/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1946
1942
  mindsdb/utilities/auth.py,sha256=nfC8oqvaN3GAATc_LeHJ34Kg3PYfyfJ-KI6TN_fOB48,2568
1947
1943
  mindsdb/utilities/cache.py,sha256=nkfEt8Pw5H_8sPNXMaS2SZCC3NrEMi486K8m61zqu-s,7590
1948
- mindsdb/utilities/config.py,sha256=qF1Tr1YPz0c2O5GqUbZZkWKci_7kstCkuL-5OXAFJgI,26578
1944
+ mindsdb/utilities/config.py,sha256=lEQH2rkaf3PwoSSdnHecc0Yhskm0Zp1niFtW6KSlePw,26360
1949
1945
  mindsdb/utilities/context.py,sha256=IdH0bXIIBHuJ_HzVQIRAZhOs4GD15AwDpXTlNnTBHek,1846
1950
1946
  mindsdb/utilities/context_executor.py,sha256=OcJu-FgHZUmtAa_jOfXtwr7LPH3Vw2FPPJlx_9cWi7w,1945
1951
1947
  mindsdb/utilities/exception.py,sha256=q-9cwMLmQvuPpwdjRG0xNZ23z9cxHSfyT2295Rk6waA,1034
@@ -1981,8 +1977,8 @@ mindsdb/utilities/profiler/__init__.py,sha256=d4VXl80uSm1IotR-WwbBInPmLmACiK0Azx
1981
1977
  mindsdb/utilities/profiler/profiler.py,sha256=KCUtOupkbM_nCoof9MtiuhUzDGezx4a4NsBX6vGWbPA,3936
1982
1978
  mindsdb/utilities/render/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1983
1979
  mindsdb/utilities/render/sqlalchemy_render.py,sha256=6NqOcfz19dhd0PEyNfOtNHsBt1fGjq2E3nFNUad5HOk,31444
1984
- mindsdb-25.5.4.0.dist-info/licenses/LICENSE,sha256=ziqdjujs6WDn-9g3t0SISjHCBc2pLRht3gnRbQoXmIs,5804
1985
- mindsdb-25.5.4.0.dist-info/METADATA,sha256=fildVyD-98sD9p-kaIUtYeQlu3EQhWdw5hW8VhWFXPk,44945
1986
- mindsdb-25.5.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1987
- mindsdb-25.5.4.0.dist-info/top_level.txt,sha256=10wPR96JDf3hM8aMP7Fz0lDlmClEP480zgXISJKr5jE,8
1988
- mindsdb-25.5.4.0.dist-info/RECORD,,
1980
+ mindsdb-25.5.4.1.dist-info/licenses/LICENSE,sha256=ziqdjujs6WDn-9g3t0SISjHCBc2pLRht3gnRbQoXmIs,5804
1981
+ mindsdb-25.5.4.1.dist-info/METADATA,sha256=lt4b5XplYOvrc1hkuBhDoh0TTt-xF7OTX69ce9Yoko8,44798
1982
+ mindsdb-25.5.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1983
+ mindsdb-25.5.4.1.dist-info/top_level.txt,sha256=10wPR96JDf3hM8aMP7Fz0lDlmClEP480zgXISJKr5jE,8
1984
+ mindsdb-25.5.4.1.dist-info/RECORD,,
@@ -1,439 +0,0 @@
1
- #!/usr/bin/env python
2
- """Simple command-line tool to interact with an A2A server.
3
-
4
- This script can:
5
- • fetch the agent card (metadata) from the server
6
- • send a single (non-streaming) task request
7
- • send a streaming request and live-print SSE events
8
-
9
- Originally located at the repository root; restored to that location.
10
- """
11
-
12
- from __future__ import annotations
13
-
14
- import argparse
15
- import json
16
- import sys
17
- import uuid
18
- from typing import Iterator, Optional
19
- import logging
20
-
21
- import requests
22
-
23
- DEFAULT_HOST = "localhost"
24
- DEFAULT_PORT = 10002
25
-
26
- ###############################################################################
27
- # Helper functions
28
- ###############################################################################
29
-
30
-
31
- def _log_json(log_func, obj: dict, *, prefix: str = "") -> None:
32
- """Log JSON helper."""
33
- log_func(prefix + json.dumps(obj, indent=2))
34
-
35
-
36
- def get_agent_info(
37
- a2a_host: str = DEFAULT_HOST,
38
- a2a_port: int = DEFAULT_PORT,
39
- ) -> Optional[dict]:
40
- """Retrieve the agent card from `/.well-known/agent.json` (or legacy path)."""
41
-
42
- url = f"http://{a2a_host}:{a2a_port}/.well-known/agent.json"
43
-
44
- logging.debug(f"Fetching agent info from {url} …")
45
-
46
- try:
47
- response = requests.get(url, timeout=10)
48
- if response.status_code == 404:
49
- legacy_url = f"http://{a2a_host}:{a2a_port}/agent-card"
50
- logging.debug(f"Not found, trying legacy path {legacy_url}")
51
- response = requests.get(legacy_url, timeout=10)
52
-
53
- if response.ok:
54
- card = response.json()
55
- _log_json(logging.debug, card, prefix="Received agent card:\n")
56
- return card
57
-
58
- logging.debug(f"Failed to fetch agent card – status: {response.status_code}")
59
- except requests.RequestException as exc:
60
- logging.debug(f"Connection error while fetching agent card: {exc}")
61
-
62
- return None
63
-
64
-
65
- ###############################################################################
66
- # Task helpers
67
- ###############################################################################
68
-
69
-
70
- def _new_ids() -> tuple[str, str, str]:
71
- """Generate fresh UUID4 strings for taskId, sessionId, requestId."""
72
-
73
- return uuid.uuid4().hex, uuid.uuid4().hex, uuid.uuid4().hex
74
-
75
-
76
- def _post_json(url: str, payload: dict, *, stream: bool = False) -> requests.Response:
77
- headers = {"Content-Type": "application/json"}
78
- if stream:
79
- headers["Accept"] = "text/event-stream"
80
- return requests.post(
81
- url, json=payload, headers=headers, stream=stream, timeout=None
82
- )
83
-
84
-
85
- ###############################################################################
86
- # Non-streaming request
87
- ###############################################################################
88
-
89
-
90
- def send_a2a_query(
91
- query: str,
92
- *,
93
- a2a_host: str = DEFAULT_HOST,
94
- a2a_port: int = DEFAULT_PORT,
95
- ) -> bool:
96
- """Send a *blocking* `tasks/send` request and print the result."""
97
-
98
- task_id, session_id, request_id = _new_ids()
99
-
100
- payload = {
101
- "jsonrpc": "2.0",
102
- "id": request_id,
103
- "method": "tasks/send",
104
- "params": {
105
- "id": task_id,
106
- "sessionId": session_id,
107
- "message": {
108
- "role": "user",
109
- "parts": [
110
- {"type": "text", "text": query},
111
- ],
112
- },
113
- "acceptedOutputModes": ["text/plain"],
114
- },
115
- }
116
-
117
- url = f"http://{a2a_host}:{a2a_port}/a2a"
118
- logging.debug(f"POST {url}")
119
- _log_json(logging.debug, payload, prefix="Request →\n")
120
- logging.info("Sending query …")
121
-
122
- try:
123
- response = _post_json(url, payload)
124
- except requests.RequestException as exc:
125
- logging.error(f"⚠️ Network error: {exc}")
126
- return False
127
-
128
- if not response.ok:
129
- logging.error(f"⚠️ HTTP {response.status_code}\n{response.text}")
130
- return False
131
-
132
- try:
133
- data = response.json()
134
- except ValueError:
135
- logging.error(f"⚠️ Invalid JSON response: {response.text[:200]}")
136
- return False
137
-
138
- _log_json(logging.debug, data, prefix="Full response ←\n")
139
-
140
- if "error" in data:
141
- logging.error(f"⚠️ RPC error: {data['error'].get('message')}")
142
- return False
143
-
144
- result = data.get("result")
145
- if not result:
146
- logging.error("⚠️ No result field in response")
147
- return False
148
-
149
- # Print status/"thinking" message
150
- status = result.get("status", {})
151
- msg_parts = status.get("message", {}).get("parts", [])
152
- if msg_parts:
153
- logging.info("\nAgent thinking:")
154
- _log_parts(logging.info, msg_parts)
155
-
156
- # Print artifacts (agent answer)
157
- artifacts = result.get("artifacts") or []
158
- if artifacts:
159
- logging.info("\nAgent response:")
160
- for artifact in artifacts:
161
- _log_parts(logging.info, artifact.get("parts", []))
162
- else:
163
- logging.info("(No artifacts returned)")
164
-
165
- return True
166
-
167
-
168
- ###############################################################################
169
- # Streaming request helpers
170
- ###############################################################################
171
-
172
-
173
- def _iter_sse_lines(resp: requests.Response) -> Iterator[str]:
174
- """Yield raw Server-Sent-Event lines (decoded)."""
175
- buf = ""
176
- for chunk in resp.iter_content(chunk_size=1024):
177
- if not chunk:
178
- continue
179
- buf += chunk.decode()
180
- while "\n" in buf:
181
- line, buf = buf.split("\n", 1)
182
- yield line.rstrip("\r")
183
-
184
-
185
- def _parse_sse_event(lines: list[str]) -> dict | None:
186
- """Parse an SSE event block into a dict."""
187
- data_lines = [line_content[6:] for line_content in lines if line_content.startswith("data: ")]
188
- if not data_lines:
189
- return None
190
- try:
191
- return json.loads("\n".join(data_lines))
192
- except json.JSONDecodeError:
193
- return None
194
-
195
-
196
- def send_streaming_query(
197
- query: str,
198
- *,
199
- a2a_host: str = DEFAULT_HOST,
200
- a2a_port: int = DEFAULT_PORT,
201
- ) -> bool:
202
- """Send a `tasks/sendSubscribe` request and stream responses as they arrive."""
203
-
204
- task_id, session_id, request_id = _new_ids()
205
-
206
- payload = {
207
- "jsonrpc": "2.0",
208
- "id": request_id,
209
- "method": "tasks/sendSubscribe",
210
- "params": {
211
- "id": task_id,
212
- "sessionId": session_id,
213
- "message": {
214
- "role": "user",
215
- "parts": [
216
- {"type": "text", "text": query},
217
- ],
218
- },
219
- "acceptedOutputModes": ["text/plain"],
220
- },
221
- }
222
-
223
- url = f"http://{a2a_host}:{a2a_port}/a2a"
224
- logging.debug(f"POST (stream) {url}")
225
- _log_json(logging.debug, payload, prefix="Request →\n")
226
-
227
- try:
228
- response = _post_json(url, payload, stream=True)
229
- except requests.RequestException as exc:
230
- logging.error(f"⚠️ Network error: {exc}")
231
- return False
232
-
233
- if not response.ok:
234
- logging.error(f"⚠️ HTTP {response.status_code}\n{response.text}")
235
- return False
236
-
237
- logging.info("Streaming events (Ctrl-C to abort):")
238
-
239
- try:
240
- event_lines: list[str] = []
241
- for line in _iter_sse_lines(response):
242
- if line == "": # blank = dispatch event
243
- event = _parse_sse_event(event_lines)
244
- event_lines.clear()
245
- if event is not None:
246
- _handle_stream_event(event)
247
- continue
248
- event_lines.append(line)
249
- except KeyboardInterrupt:
250
- logging.info("\nInterrupted by user.")
251
- return False
252
-
253
- return True
254
-
255
-
256
- ###############################################################################
257
- # Output helpers
258
- ###############################################################################
259
-
260
-
261
- def _log_parts(log_func, parts: list[dict]) -> None:
262
- for part in parts:
263
- if part.get("type") == "text":
264
- log_func(part.get("text", ""))
265
- elif part.get("type") == "data":
266
- log_func("\nStructured data:")
267
- _log_json(log_func, part.get("data", {}))
268
-
269
-
270
- def _handle_stream_event(event: dict) -> None:
271
- """Handle a single SSE event parsed as JSON.
272
-
273
- The server sends JSON-RPC messages of the form::
274
-
275
- {"jsonrpc":"2.0","id":"…","result":{…}}
276
-
277
- where *result* is either a TaskStatusUpdateEvent or a TaskArtifactUpdateEvent.
278
- These objects do not carry an explicit ``type`` field, so we infer it based
279
- on their keys.
280
- """
281
-
282
- # If logging level is DEBUG, log the raw event and mimic the original 'return' behavior
283
- if logging.getLogger().isEnabledFor(logging.DEBUG):
284
- _log_json(logging.debug, event, prefix="Raw Event (DEBUG) ← ")
285
- # This return mimics the original behavior where verbose mode would
286
- # print the raw event and skip further processing for this event.
287
- return
288
-
289
- # If the server uses an older "typed" envelope just keep legacy handling
290
- if "type" in event:
291
- etype = event["type"]
292
- if etype == "status":
293
- message = event.get("status", {}).get("message", {})
294
- parts = message.get("parts", [])
295
- if parts:
296
- _log_parts(logging.info, parts)
297
- elif etype == "artifact":
298
- artifacts = event.get("artifacts") or []
299
- for artifact in artifacts:
300
- _log_parts(logging.info, artifact.get("parts", []))
301
- elif etype == "end":
302
- logging.info("\n[stream end]")
303
- return
304
-
305
- # ---- New A2A 0.2 style messages ---------------------------------------
306
- # Extract "result" or "error" from the JSON-RPC envelope.
307
- if "error" in event:
308
- err = event["error"]
309
- logging.error(f"RPC error: {err.get('message')}")
310
- return
311
-
312
- result = event.get("result")
313
- if not result:
314
- # Nothing useful to display
315
- return
316
-
317
- # Status update? (TaskStatusUpdateEvent)
318
- if "status" in result:
319
- message = result["status"].get("message", {})
320
- parts = message.get("parts", [])
321
- if parts:
322
- _log_parts(logging.info, parts)
323
-
324
- # If final flag present we can acknowledge.
325
- if result.get("final"):
326
- logging.info("\n[completed]")
327
- return
328
-
329
- # Artifact update? (TaskArtifactUpdateEvent)
330
- if "artifact" in result:
331
- artifact = result["artifact"]
332
- _log_parts(logging.info, artifact.get("parts", []))
333
- return
334
-
335
-
336
- ###############################################################################
337
- # CLI argument parsing
338
- ###############################################################################
339
-
340
-
341
- def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
342
- parser = argparse.ArgumentParser(description="Interact with an A2A server")
343
-
344
- parser.add_argument(
345
- "query", nargs="*", help="Query to send. If omitted, just fetch agent card."
346
- )
347
-
348
- parser.add_argument(
349
- "--host", default=DEFAULT_HOST, help="A2A host (default: %(default)s)"
350
- )
351
- parser.add_argument(
352
- "--port", type=int, default=DEFAULT_PORT, help="A2A port (default: %(default)s)"
353
- )
354
-
355
- parser.add_argument(
356
- "--stream",
357
- action="store_true",
358
- help="Use streaming subscribe request instead of blocking send",
359
- )
360
-
361
- parser.add_argument("--verbose", action="store_true", help="Verbose output (debug)")
362
-
363
- return parser.parse_args(argv)
364
-
365
-
366
- ###############################################################################
367
- # Main entry-point
368
- ###############################################################################
369
-
370
-
371
- def main(argv: list[str] | None = None) -> None:
372
- args = parse_args(argv)
373
-
374
- # Configure logging
375
- log_level = logging.DEBUG if args.verbose else logging.INFO
376
- logging.basicConfig(format="%(message)s", level=log_level, stream=sys.stdout)
377
- if args.verbose:
378
- logging.debug("Verbose mode enabled.")
379
-
380
- # 1. Always fetch agent-card first (helps verify server is live)
381
- agent_info = get_agent_info(args.host, args.port)
382
- if agent_info is None:
383
- logging.critical("⚠️ Could not retrieve agent info – abort")
384
- sys.exit(1)
385
-
386
- if not args.query:
387
- # Enter interactive REPL style mode
388
- logging.info("Interactive mode – type 'exit' or Ctrl-D to quit.")
389
- try:
390
- while True:
391
- try:
392
- user_input = input("> ").strip()
393
- except EOFError:
394
- # Ctrl-D
395
- logging.info("")
396
- break
397
-
398
- if user_input.lower() in {"exit", "quit"}:
399
- break
400
-
401
- if not user_input:
402
- continue
403
-
404
- ok = (
405
- send_streaming_query(
406
- user_input,
407
- a2a_host=args.host,
408
- a2a_port=args.port,
409
- )
410
- if args.stream
411
- else send_a2a_query(
412
- user_input,
413
- a2a_host=args.host,
414
- a2a_port=args.port,
415
- )
416
- )
417
-
418
- # Add separator between queries
419
- if ok:
420
- logging.info("\n" + "—" * 30)
421
- except KeyboardInterrupt:
422
- # Ctrl-C to exit
423
- logging.info("")
424
- sys.exit(0)
425
-
426
- # Single query passed via CLI
427
- query_str = " ".join(args.query)
428
-
429
- ok = (
430
- send_streaming_query(query_str, a2a_host=args.host, a2a_port=args.port)
431
- if args.stream
432
- else send_a2a_query(query_str, a2a_host=args.host, a2a_port=args.port)
433
- )
434
-
435
- sys.exit(0 if ok else 2)
436
-
437
-
438
- if __name__ == "__main__":
439
- main()
@@ -1,4 +0,0 @@
1
- from .client import A2AClient
2
- from .card_resolver import A2ACardResolver
3
-
4
- __all__ = ["A2AClient", "A2ACardResolver"]
@@ -1,21 +0,0 @@
1
- import httpx
2
- from common.types import (
3
- AgentCard,
4
- A2AClientJSONError,
5
- )
6
- import json
7
-
8
-
9
- class A2ACardResolver:
10
- def __init__(self, base_url, agent_card_path="/.well-known/agent.json"):
11
- self.base_url = base_url.rstrip("/")
12
- self.agent_card_path = agent_card_path.lstrip("/")
13
-
14
- def get_agent_card(self) -> AgentCard:
15
- with httpx.Client() as client:
16
- response = client.get(self.base_url + "/" + self.agent_card_path)
17
- response.raise_for_status()
18
- try:
19
- return AgentCard(**response.json())
20
- except json.JSONDecodeError as e:
21
- raise A2AClientJSONError(str(e)) from e