solace-agent-mesh 1.11.2__py3-none-any.whl → 1.12.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.
Files changed (308) hide show
  1. solace_agent_mesh/agent/adk/callbacks.py +177 -10
  2. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +3 -0
  3. solace_agent_mesh/agent/adk/models/lite_llm.py +34 -16
  4. solace_agent_mesh/agent/adk/runner.py +66 -8
  5. solace_agent_mesh/agent/adk/setup.py +61 -26
  6. solace_agent_mesh/agent/protocol/event_handlers.py +48 -0
  7. solace_agent_mesh/agent/proxies/a2a/component.py +27 -0
  8. solace_agent_mesh/agent/sac/component.py +84 -2
  9. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +41 -22
  10. solace_agent_mesh/agent/tools/peer_agent_tool.py +19 -12
  11. solace_agent_mesh/agent/tools/tool_config_types.py +21 -1
  12. solace_agent_mesh/agent/utils/artifact_helpers.py +54 -0
  13. solace_agent_mesh/assets/docs/404.html +3 -3
  14. solace_agent_mesh/assets/docs/assets/js/15ba94aa.e186750d.js +1 -0
  15. solace_agent_mesh/assets/docs/assets/js/240a0364.83e37aa8.js +1 -0
  16. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.2f0db237.js +1 -0
  17. solace_agent_mesh/assets/docs/assets/js/3a6c6137.7e61915d.js +1 -0
  18. solace_agent_mesh/assets/docs/assets/js/{3ac1795d.28b7c67b.js → 3ac1795d.dc006e20.js} +1 -1
  19. solace_agent_mesh/assets/docs/assets/js/3ff0015d.f08618fb.js +1 -0
  20. solace_agent_mesh/assets/docs/assets/js/4667dc50.bf2ad456.js +1 -0
  21. solace_agent_mesh/assets/docs/assets/js/547e15cc.8e6da617.js +1 -0
  22. solace_agent_mesh/assets/docs/assets/js/5b8d9c11.d4eb37b8.js +1 -0
  23. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.1ee87753.js +1 -0
  24. solace_agent_mesh/assets/docs/assets/js/64195356.09dbd087.js +1 -0
  25. solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.js +1 -0
  26. solace_agent_mesh/assets/docs/assets/js/729898df.7249e9fd.js +1 -0
  27. solace_agent_mesh/assets/docs/assets/js/7e294c01.7c5f6906.js +1 -0
  28. solace_agent_mesh/assets/docs/assets/js/8024126c.e3467286.js +1 -0
  29. solace_agent_mesh/assets/docs/assets/js/81a99df0.95be65d4.js +1 -0
  30. solace_agent_mesh/assets/docs/assets/js/9bb13469.4523ae20.js +1 -0
  31. solace_agent_mesh/assets/docs/assets/js/a7d42657.a956689d.js +1 -0
  32. solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e563275.js +1 -0
  33. solace_agent_mesh/assets/docs/assets/js/e04b235d.06d23db6.js +1 -0
  34. solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.deb2b62e.js +1 -0
  35. solace_agent_mesh/assets/docs/assets/js/e6f9706b.acc800d3.js +1 -0
  36. solace_agent_mesh/assets/docs/assets/js/e92d0134.c147a429.js +1 -0
  37. solace_agent_mesh/assets/docs/assets/js/ee0c2fe7.94d0a351.js +1 -0
  38. solace_agent_mesh/assets/docs/assets/js/f284c35a.08fab659.js +1 -0
  39. solace_agent_mesh/assets/docs/assets/js/main.b241af3e.js +2 -0
  40. solace_agent_mesh/assets/docs/assets/js/runtime~main.4ca7d2e2.js +1 -0
  41. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +4 -4
  42. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +4 -4
  43. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +4 -4
  44. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +4 -4
  45. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +4 -4
  46. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/image-tools/index.html +81 -0
  47. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +14 -12
  48. solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +30 -9
  49. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +4 -4
  50. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +6 -4
  51. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +4 -4
  52. solace_agent_mesh/assets/docs/docs/documentation/components/platform-service/index.html +33 -0
  53. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +4 -4
  54. solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +4 -4
  55. solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +4 -4
  56. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +4 -4
  57. solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +4 -4
  58. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +4 -4
  59. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +5 -5
  60. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +4 -4
  61. solace_agent_mesh/assets/docs/docs/documentation/deploying/{kubernetes-deployment → kubernetes}/index.html +6 -6
  62. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/kubernetes-deployment-guide/index.html +197 -0
  63. solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +11 -6
  64. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +4 -4
  65. solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +4 -4
  66. solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +4 -4
  67. solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +4 -4
  68. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +23 -5
  69. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +4 -4
  70. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +4 -4
  71. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +4 -4
  72. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +4 -4
  73. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +4 -4
  74. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +4 -4
  75. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +4 -4
  76. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +17 -8
  77. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +4 -4
  78. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +4 -4
  79. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +4 -4
  80. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +4 -4
  81. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +4 -4
  82. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +4 -4
  83. solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +5 -5
  84. solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +4 -4
  85. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +4 -4
  86. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +4 -4
  87. solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +4 -4
  88. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +4 -4
  89. solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +4 -4
  90. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +4 -4
  91. solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +4 -4
  92. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +4 -4
  93. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +6 -5
  94. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +4 -4
  95. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +4 -4
  96. solace_agent_mesh/assets/docs/docs/documentation/getting-started/vibe_coding/index.html +62 -0
  97. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +25 -4
  98. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +4 -4
  99. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +4 -4
  100. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +4 -4
  101. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +4 -4
  102. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +4 -4
  103. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +4 -4
  104. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +4 -4
  105. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +4 -4
  106. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +4 -4
  107. solace_agent_mesh/assets/docs/docs/documentation/migrations/platform-service-split/index.html +85 -0
  108. solace_agent_mesh/assets/docs/lunr-index-1767712284328.json +1 -0
  109. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  110. solace_agent_mesh/assets/docs/search-doc-1767712284328.json +1 -0
  111. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  112. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  113. solace_agent_mesh/cli/__init__.py +1 -1
  114. solace_agent_mesh/cli/commands/init_cmd/__init__.py +15 -0
  115. solace_agent_mesh/cli/commands/init_cmd/directory_step.py +1 -1
  116. solace_agent_mesh/cli/commands/init_cmd/env_step.py +29 -2
  117. solace_agent_mesh/cli/commands/init_cmd/platform_service_step.py +85 -0
  118. solace_agent_mesh/cli/commands/tools_cmd.py +315 -0
  119. solace_agent_mesh/cli/main.py +2 -0
  120. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-Dj3JtK42.js → authCallback-8Nihi8rv.js} +1 -1
  121. solace_agent_mesh/client/webui/frontend/static/assets/{client-ZKk9kEJ5.js → client-DYtZN8p-.js} +1 -1
  122. solace_agent_mesh/client/webui/frontend/static/assets/main-BYGUHQMk.js +435 -0
  123. solace_agent_mesh/client/webui/frontend/static/assets/main-D2CSH1bp.css +1 -0
  124. solace_agent_mesh/client/webui/frontend/static/assets/{vendor-BNV4kZN0.js → vendor-XBWAmrun.js} +106 -101
  125. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  126. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  127. solace_agent_mesh/client/webui/frontend/static/ui-version.json +1 -1
  128. solace_agent_mesh/common/a2a/types.py +1 -1
  129. solace_agent_mesh/common/agent_registry.py +38 -11
  130. solace_agent_mesh/common/data_parts.py +28 -0
  131. solace_agent_mesh/common/error_handlers.py +83 -0
  132. solace_agent_mesh/common/sam_events/event_service.py +2 -2
  133. solace_agent_mesh/config_portal/backend/common.py +2 -0
  134. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ZV-jX48T.js +103 -0
  135. solace_agent_mesh/config_portal/frontend/static/client/assets/{manifest-ba77705e.js → manifest-ce5bc5da.js} +1 -1
  136. solace_agent_mesh/config_portal/frontend/static/client/index.html +1 -1
  137. solace_agent_mesh/core_a2a/service.py +3 -2
  138. solace_agent_mesh/gateway/adapter/base.py +28 -1
  139. solace_agent_mesh/gateway/adapter/types.py +9 -0
  140. solace_agent_mesh/gateway/base/auth_interface.py +103 -0
  141. solace_agent_mesh/gateway/base/component.py +68 -1
  142. solace_agent_mesh/gateway/generic/component.py +195 -30
  143. solace_agent_mesh/gateway/http_sse/app.py +23 -6
  144. solace_agent_mesh/gateway/http_sse/component.py +9 -61
  145. solace_agent_mesh/gateway/http_sse/dependencies.py +9 -51
  146. solace_agent_mesh/gateway/http_sse/main.py +28 -418
  147. solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
  148. solace_agent_mesh/gateway/http_sse/repository/entities/project.py +1 -1
  149. solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +1 -1
  150. solace_agent_mesh/gateway/http_sse/repository/entities/session.py +2 -2
  151. solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +2 -2
  152. solace_agent_mesh/gateway/http_sse/repository/interfaces.py +2 -2
  153. solace_agent_mesh/gateway/http_sse/repository/models/prompt_model.py +1 -1
  154. solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +1 -1
  155. solace_agent_mesh/gateway/http_sse/repository/project_repository.py +1 -1
  156. solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +1 -1
  157. solace_agent_mesh/gateway/http_sse/repository/session_repository.py +4 -4
  158. solace_agent_mesh/gateway/http_sse/repository/task_repository.py +2 -2
  159. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +16 -15
  160. solace_agent_mesh/gateway/http_sse/routers/auth.py +61 -132
  161. solace_agent_mesh/gateway/http_sse/routers/config.py +12 -8
  162. solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +1 -1
  163. solace_agent_mesh/gateway/http_sse/routers/dto/responses/base_responses.py +1 -1
  164. solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +2 -2
  165. solace_agent_mesh/gateway/http_sse/routers/feedback.py +2 -2
  166. solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
  167. solace_agent_mesh/gateway/http_sse/routers/projects.py +2 -1
  168. solace_agent_mesh/gateway/http_sse/routers/prompts.py +2 -1
  169. solace_agent_mesh/gateway/http_sse/routers/sessions.py +3 -3
  170. solace_agent_mesh/gateway/http_sse/routers/speech.py +1 -1
  171. solace_agent_mesh/gateway/http_sse/routers/tasks.py +3 -2
  172. solace_agent_mesh/gateway/http_sse/routers/users.py +1 -1
  173. solace_agent_mesh/gateway/http_sse/routers/visualization.py +2 -1
  174. solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +1 -1
  175. solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +1 -1
  176. solace_agent_mesh/gateway/http_sse/services/feedback_service.py +1 -1
  177. solace_agent_mesh/gateway/http_sse/services/session_service.py +4 -4
  178. solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +1 -1
  179. solace_agent_mesh/services/platform/__init__.py +23 -12
  180. solace_agent_mesh/services/platform/api/dependencies.py +23 -16
  181. solace_agent_mesh/services/platform/api/main.py +118 -43
  182. solace_agent_mesh/services/platform/api/routers/__init__.py +12 -3
  183. solace_agent_mesh/services/platform/api/routers/health_router.py +31 -0
  184. solace_agent_mesh/services/platform/app.py +101 -7
  185. solace_agent_mesh/services/platform/component.py +552 -33
  186. solace_agent_mesh/shared/__init__.py +14 -0
  187. solace_agent_mesh/shared/api/__init__.py +42 -0
  188. solace_agent_mesh/shared/auth/__init__.py +26 -0
  189. solace_agent_mesh/shared/auth/dependencies.py +204 -0
  190. solace_agent_mesh/shared/auth/middleware.py +291 -0
  191. solace_agent_mesh/shared/database/__init__.py +20 -0
  192. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/base_repository.py +1 -1
  193. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_exceptions.py +1 -1
  194. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_helpers.py +1 -1
  195. solace_agent_mesh/shared/exceptions/__init__.py +36 -0
  196. solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exception_handlers.py +1 -1
  197. solace_agent_mesh/shared/utils/__init__.py +21 -0
  198. solace_agent_mesh/templates/platform.yaml +49 -0
  199. solace_agent_mesh/templates/webui.yaml +12 -3
  200. {solace_agent_mesh-1.11.2.dist-info → solace_agent_mesh-1.12.0.dist-info}/METADATA +2 -1
  201. {solace_agent_mesh-1.11.2.dist-info → solace_agent_mesh-1.12.0.dist-info}/RECORD +214 -258
  202. solace_agent_mesh/agent/adk/adk_llm.txt +0 -226
  203. solace_agent_mesh/agent/adk/adk_llm_detail.txt +0 -566
  204. solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +0 -171
  205. solace_agent_mesh/agent/adk/models/models_llm.txt +0 -189
  206. solace_agent_mesh/agent/agent_llm.txt +0 -369
  207. solace_agent_mesh/agent/agent_llm_detail.txt +0 -1702
  208. solace_agent_mesh/agent/protocol/protocol_llm.txt +0 -81
  209. solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +0 -92
  210. solace_agent_mesh/agent/proxies/a2a/a2a_llm.txt +0 -190
  211. solace_agent_mesh/agent/proxies/base/base_llm.txt +0 -148
  212. solace_agent_mesh/agent/proxies/proxies_llm.txt +0 -283
  213. solace_agent_mesh/agent/sac/sac_llm.txt +0 -189
  214. solace_agent_mesh/agent/sac/sac_llm_detail.txt +0 -200
  215. solace_agent_mesh/agent/testing/testing_llm.txt +0 -58
  216. solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
  217. solace_agent_mesh/agent/tools/tools_llm.txt +0 -276
  218. solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -275
  219. solace_agent_mesh/agent/utils/utils_llm.txt +0 -152
  220. solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
  221. solace_agent_mesh/assets/docs/assets/js/15ba94aa.92fea363.js +0 -1
  222. solace_agent_mesh/assets/docs/assets/js/240a0364.9ad94d1b.js +0 -1
  223. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +0 -1
  224. solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +0 -1
  225. solace_agent_mesh/assets/docs/assets/js/3ff0015d.2ddc75c0.js +0 -1
  226. solace_agent_mesh/assets/docs/assets/js/547e15cc.2f7790c1.js +0 -1
  227. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.90a87880.js +0 -1
  228. solace_agent_mesh/assets/docs/assets/js/64195356.c498c4d0.js +0 -1
  229. solace_agent_mesh/assets/docs/assets/js/66d4869e.b77431fc.js +0 -1
  230. solace_agent_mesh/assets/docs/assets/js/8024126c.fa0e7186.js +0 -1
  231. solace_agent_mesh/assets/docs/assets/js/81a99df0.2484b8d9.js +0 -1
  232. solace_agent_mesh/assets/docs/assets/js/9bb13469.b2333011.js +0 -1
  233. solace_agent_mesh/assets/docs/assets/js/ab9708a8.245ae0ef.js +0 -1
  234. solace_agent_mesh/assets/docs/assets/js/db5d6442.3daf1696.js +0 -1
  235. solace_agent_mesh/assets/docs/assets/js/e04b235d.52cb25ed.js +0 -1
  236. solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.b1068f9b.js +0 -1
  237. solace_agent_mesh/assets/docs/assets/js/e6f9706b.4488e34c.js +0 -1
  238. solace_agent_mesh/assets/docs/assets/js/e92d0134.3bda61dd.js +0 -1
  239. solace_agent_mesh/assets/docs/assets/js/f284c35a.250993bf.js +0 -1
  240. solace_agent_mesh/assets/docs/assets/js/main.7acf7ace.js +0 -2
  241. solace_agent_mesh/assets/docs/assets/js/runtime~main.9e0813a2.js +0 -1
  242. solace_agent_mesh/assets/docs/lunr-index-1765810064709.json +0 -1
  243. solace_agent_mesh/assets/docs/search-doc-1765810064709.json +0 -1
  244. solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +0 -250
  245. solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +0 -365
  246. solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +0 -305
  247. solace_agent_mesh/client/webui/frontend/static/assets/main-BcUaNZ-Q.css +0 -1
  248. solace_agent_mesh/client/webui/frontend/static/assets/main-vjch4RYc.js +0 -435
  249. solace_agent_mesh/common/a2a/a2a_llm.txt +0 -175
  250. solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
  251. solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -445
  252. solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
  253. solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -330
  254. solace_agent_mesh/common/common_llm.txt +0 -230
  255. solace_agent_mesh/common/common_llm_detail.txt +0 -2562
  256. solace_agent_mesh/common/middleware/middleware_llm.txt +0 -174
  257. solace_agent_mesh/common/middleware/middleware_llm_detail.txt +0 -185
  258. solace_agent_mesh/common/sac/sac_llm.txt +0 -71
  259. solace_agent_mesh/common/sac/sac_llm_detail.txt +0 -82
  260. solace_agent_mesh/common/sam_events/sam_events_llm.txt +0 -104
  261. solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +0 -115
  262. solace_agent_mesh/common/services/providers/providers_llm.txt +0 -81
  263. solace_agent_mesh/common/services/services_llm.txt +0 -368
  264. solace_agent_mesh/common/services/services_llm_detail.txt +0 -459
  265. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +0 -220
  266. solace_agent_mesh/common/utils/utils_llm.txt +0 -335
  267. solace_agent_mesh/common/utils/utils_llm_detail.txt +0 -572
  268. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-DiOiAjzL.js +0 -103
  269. solace_agent_mesh/core_a2a/core_a2a_llm.txt +0 -90
  270. solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +0 -101
  271. solace_agent_mesh/gateway/base/base_llm.txt +0 -226
  272. solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
  273. solace_agent_mesh/gateway/gateway_llm.txt +0 -369
  274. solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
  275. solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -345
  276. solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -161
  277. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +0 -105
  278. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +0 -299
  279. solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +0 -3278
  280. solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +0 -221
  281. solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -257
  282. solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -308
  283. solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -450
  284. solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -133
  285. solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -123
  286. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -312
  287. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -303
  288. solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
  289. solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -319
  290. solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +0 -47
  291. solace_agent_mesh/llm.txt +0 -228
  292. solace_agent_mesh/llm_detail.txt +0 -2835
  293. solace_agent_mesh/solace_agent_mesh_llm.txt +0 -362
  294. solace_agent_mesh/solace_agent_mesh_llm_detail.txt +0 -8599
  295. solace_agent_mesh/templates/templates_llm.txt +0 -147
  296. /solace_agent_mesh/assets/docs/assets/js/{main.7acf7ace.js.LICENSE.txt → main.b241af3e.js.LICENSE.txt} +0 -0
  297. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/auth_utils.py +0 -0
  298. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/pagination.py +0 -0
  299. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/response_utils.py +0 -0
  300. /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/error_dto.py +0 -0
  301. /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exceptions.py +0 -0
  302. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/enums.py +0 -0
  303. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/timestamp_utils.py +0 -0
  304. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/types.py +0 -0
  305. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/utils.py +0 -0
  306. {solace_agent_mesh-1.11.2.dist-info → solace_agent_mesh-1.12.0.dist-info}/WHEEL +0 -0
  307. {solace_agent_mesh-1.11.2.dist-info → solace_agent_mesh-1.12.0.dist-info}/entry_points.txt +0 -0
  308. {solace_agent_mesh-1.11.2.dist-info → solace_agent_mesh-1.12.0.dist-info}/licenses/LICENSE +0 -0
@@ -15,6 +15,7 @@ from google.adk.models.llm_request import LlmRequest
15
15
  from google.adk.models.llm_response import LlmResponse
16
16
  from google.adk.runners import Runner
17
17
  from google.adk.tools import BaseTool, ToolContext
18
+ from google.adk.tools.mcp_tool import MCPTool
18
19
  from google.adk.tools.mcp_tool.mcp_session_manager import (
19
20
  SseServerParams,
20
21
  StdioConnectionParams,
@@ -625,14 +626,30 @@ async def _load_mcp_tool(component: "SamAgentComponent", tool_config: Dict) -> T
625
626
  else:
626
627
  raise ValueError(f"Unsupported MCP connection type: {connection_type}")
627
628
 
628
- tool_filter_list = (
629
- [tool_config_model.tool_name] if tool_config_model.tool_name else None
630
- )
631
- if tool_filter_list:
629
+ # Determine tool filter based on configuration
630
+ # tool_name, allow_list, and deny_list are mutually exclusive (validated by pydantic)
631
+ tool_filter = None
632
+ filter_description = "none (all tools)"
633
+
634
+ if tool_config_model.tool_name:
635
+ # Backward compatible: single tool name becomes a list
636
+ tool_filter = [tool_config_model.tool_name]
637
+ filter_description = f"tool_name='{tool_config_model.tool_name}'"
638
+ elif tool_config_model.allow_list:
639
+ # Allow list: pass directly as list of tool names
640
+ tool_filter = tool_config_model.allow_list
641
+ filter_description = f"allow_list={tool_config_model.allow_list}"
642
+ elif tool_config_model.deny_list:
643
+ # Deny list: create a ToolPredicate that excludes these tools
644
+ deny_set = set(tool_config_model.deny_list)
645
+ tool_filter = lambda tool, ctx=None, _deny=deny_set: tool.name not in _deny
646
+ filter_description = f"deny_list={tool_config_model.deny_list}"
647
+
648
+ if tool_filter:
632
649
  log.info(
633
- "%s MCP tool config specifies tool_name: '%s'. Applying as tool_filter.",
650
+ "%s MCP tool config specifies filter: %s",
634
651
  component.log_identifier,
635
- tool_config_model.tool_name,
652
+ filter_description,
636
653
  )
637
654
 
638
655
  additional_params = {}
@@ -647,7 +664,7 @@ async def _load_mcp_tool(component: "SamAgentComponent", tool_config: Dict) -> T
647
664
  tool_type="mcp",
648
665
  tool_config=tool_config,
649
666
  connection_params=connection_params,
650
- tool_filter=tool_filter_list,
667
+ tool_filter=tool_filter,
651
668
  )
652
669
  except Exception as e:
653
670
  log.error(
@@ -664,7 +681,8 @@ async def _load_mcp_tool(component: "SamAgentComponent", tool_config: Dict) -> T
664
681
  # Create the EmbedResolvingMCPToolset with base parameters
665
682
  toolset_params = {
666
683
  "connection_params": connection_params,
667
- "tool_filter": tool_filter_list,
684
+ "tool_filter": tool_filter,
685
+ "tool_name_prefix": tool_config_model.tool_name_prefix,
668
686
  "tool_config": tool_config,
669
687
  }
670
688
 
@@ -677,7 +695,7 @@ async def _load_mcp_tool(component: "SamAgentComponent", tool_config: Dict) -> T
677
695
  log.info(
678
696
  "%s Initialized MCPToolset (filter: %s) for server: %s",
679
697
  component.log_identifier,
680
- (tool_filter_list if tool_filter_list else "none (all tools)"),
698
+ filter_description,
681
699
  connection_params,
682
700
  )
683
701
 
@@ -893,19 +911,7 @@ async def load_adk_tools(
893
911
  for tool in new_tools:
894
912
  if isinstance(tool, EmbedResolvingMCPToolset):
895
913
  # Special handling for MCPToolset which can load multiple tools
896
- try:
897
- mcp_tools = await tool.get_tools()
898
- for mcp_tool in mcp_tools:
899
- _check_and_register_tool_name(
900
- mcp_tool.name, "mcp", loaded_tool_names
901
- )
902
- except Exception as e:
903
- log.error(
904
- "%s Failed to discover tools from MCP server for name registration: %s",
905
- component.log_identifier,
906
- str(e),
907
- )
908
- raise
914
+ await _check_and_register_tool_name_mcp(component, loaded_tool_names, tool)
909
915
  else:
910
916
  tool_name = getattr(
911
917
  tool, "name", getattr(tool, "__name__", None)
@@ -949,6 +955,25 @@ async def load_adk_tools(
949
955
  return loaded_tools, enabled_builtin_tools, cleanup_hooks
950
956
 
951
957
 
958
+ async def _check_and_register_tool_name_mcp(component, loaded_tool_names: set[str], tool: EmbedResolvingMCPToolset):
959
+ try:
960
+ mcp_tools: list[MCPTool] = await tool.get_tools()
961
+ for mcp_tool in mcp_tools:
962
+ toolname = mcp_tool.name
963
+ if tool.tool_name_prefix != None:
964
+ toolname = f"{tool.tool_name_prefix}_{toolname}"
965
+ _check_and_register_tool_name(
966
+ toolname, "mcp", loaded_tool_names
967
+ )
968
+ except Exception as e:
969
+ log.error(
970
+ "%s Failed to discover tools from MCP server for name registration: %s",
971
+ component.log_identifier,
972
+ str(e),
973
+ )
974
+ raise
975
+
976
+
952
977
  def initialize_adk_agent(
953
978
  component,
954
979
  loaded_explicit_tools: List[Union[BaseTool, Callable]],
@@ -1221,7 +1246,17 @@ def initialize_adk_agent(
1221
1246
  # The callbacks are executed in the order they are added to this list.
1222
1247
  callbacks_in_order_for_after_model = []
1223
1248
 
1224
- # 1. Fenced Artifact Block Processing (must run before auto-continue)
1249
+ # 1. Pre-register long-running tools (must run BEFORE tool execution)
1250
+ preregister_cb = functools.partial(
1251
+ adk_callbacks.preregister_long_running_tools_callback, host_component=component
1252
+ )
1253
+ callbacks_in_order_for_after_model.append(preregister_cb)
1254
+ log.debug(
1255
+ "%s Added preregister_long_running_tools_callback to after_model chain.",
1256
+ component.log_identifier,
1257
+ )
1258
+
1259
+ # 2. Fenced Artifact Block Processing (must run before auto-continue)
1225
1260
  artifact_block_cb = functools.partial(
1226
1261
  adk_callbacks.process_artifact_blocks_callback, host_component=component
1227
1262
  )
@@ -1231,7 +1266,7 @@ def initialize_adk_agent(
1231
1266
  component.log_identifier,
1232
1267
  )
1233
1268
 
1234
- # 2. Auto-Continuation (may short-circuit the chain)
1269
+ # 3. Auto-Continuation (may short-circuit the chain)
1235
1270
  auto_continue_cb = functools.partial(
1236
1271
  adk_callbacks.auto_continue_on_max_tokens_callback, host_component=component
1237
1272
  )
@@ -1241,13 +1276,13 @@ def initialize_adk_agent(
1241
1276
  component.log_identifier,
1242
1277
  )
1243
1278
 
1244
- # 3. Solace LLM Response Logging
1279
+ # 4. Solace LLM Response Logging
1245
1280
  solace_llm_response_cb = functools.partial(
1246
1281
  adk_callbacks.solace_llm_response_callback, host_component=component
1247
1282
  )
1248
1283
  callbacks_in_order_for_after_model.append(solace_llm_response_cb)
1249
1284
 
1250
- # 4. Chunk Logging
1285
+ # 5. Chunk Logging
1251
1286
  log_chunk_cb = functools.partial(
1252
1287
  adk_callbacks.log_streaming_chunk_callback, host_component=component
1253
1288
  )
@@ -8,6 +8,8 @@ import json
8
8
  import logging
9
9
  from typing import TYPE_CHECKING, Any, Dict
10
10
 
11
+ from litellm.exceptions import BadRequestError
12
+
11
13
  from a2a.types import (
12
14
  A2ARequest,
13
15
  AgentCapabilities,
@@ -31,6 +33,7 @@ from ...agent.adk.callbacks import _publish_data_part_status_update
31
33
  from ...agent.adk.runner import TaskCancelledError, run_adk_async_task_thread_wrapper
32
34
  from ...agent.utils.artifact_helpers import generate_artifact_metadata_summary
33
35
  from ...common import a2a
36
+ from ...common.error_handlers import get_error_message
34
37
  from ...common.utils.embeds.constants import (
35
38
  EMBED_DELIMITER_OPEN,
36
39
  EMBED_DELIMITER_CLOSE,
@@ -975,6 +978,51 @@ async def handle_a2a_request(component, message: SolaceMessage):
975
978
  component.handle_error(e, Event(EventType.MESSAGE, message))
976
979
  return None
977
980
 
981
+ except BadRequestError as e:
982
+ log.error(
983
+ "%s Bad Request error handling A2A request: %s", component.log_identifier, e
984
+ )
985
+
986
+ # Use centralized error handler
987
+ error_message, is_context_limit = get_error_message(e)
988
+
989
+ if is_context_limit:
990
+ log.error(
991
+ "%s Context limit exceeded for task %s",
992
+ component.log_identifier,
993
+ logical_task_id,
994
+ )
995
+
996
+ error_response = a2a.create_invalid_request_error_response(
997
+ message=error_message,
998
+ request_id=jsonrpc_request_id,
999
+ data={"taskId": logical_task_id},
1000
+ )
1001
+ target_topic = reply_topic_from_peer or (
1002
+ get_client_response_topic(namespace, client_id) if client_id else None
1003
+ )
1004
+ if target_topic:
1005
+ component.publish_a2a_message(
1006
+ error_response.model_dump(exclude_none=True),
1007
+ target_topic,
1008
+ )
1009
+
1010
+ try:
1011
+ message.call_negative_acknowledgements()
1012
+ log.warning(
1013
+ "%s NACKed original A2A request due to bad request error.",
1014
+ component.log_identifier,
1015
+ )
1016
+ except Exception as nack_e:
1017
+ log.error(
1018
+ "%s Failed to NACK message after bad request error: %s",
1019
+ component.log_identifier,
1020
+ nack_e,
1021
+ )
1022
+
1023
+ component.handle_error(e, Event(EventType.MESSAGE, message))
1024
+ return None
1025
+
978
1026
  except OperationalError as e:
979
1027
  log.error(
980
1028
  "%s Database error while processing A2A request: %s",
@@ -28,6 +28,7 @@ from a2a.types import (
28
28
  Artifact,
29
29
  CancelTaskRequest,
30
30
  DataPart,
31
+ InternalError,
31
32
  Message,
32
33
  SendMessageRequest,
33
34
  SendStreamingMessageRequest,
@@ -322,6 +323,8 @@ class A2AProxyComponent(BaseProxyComponent):
322
323
 
323
324
  # Step 3: Normal request flow for all other auth types
324
325
  # (static_bearer, static_apikey, oauth2_client_credentials, or authorized oauth2_authorization_code)
326
+ received_final_task = False
327
+
325
328
  while auth_retry_count <= max_auth_retries:
326
329
  try:
327
330
  # Get or create A2AClient
@@ -382,6 +385,10 @@ class A2AProxyComponent(BaseProxyComponent):
382
385
  await self._process_downstream_response(
383
386
  raw_event, task_context, client, agent_name
384
387
  )
388
+ # Check if this is a final task
389
+ if isinstance(raw_event, Task) and raw_event.status:
390
+ if raw_event.status.state in [TaskState.completed, TaskState.failed, TaskState.canceled]:
391
+ received_final_task = True
385
392
  else:
386
393
  # Non-streaming: use normal client method (works fine)
387
394
  log.debug(
@@ -394,6 +401,12 @@ class A2AProxyComponent(BaseProxyComponent):
394
401
  await self._process_downstream_response(
395
402
  event, task_context, client, agent_name
396
403
  )
404
+ # Check if this is a final task (event is tuple of (Task, Optional[UpdateEvent]))
405
+ if isinstance(event, tuple) and len(event) > 0:
406
+ task = event[0]
407
+ if isinstance(task, Task) and task.status:
408
+ if task.status.state in [TaskState.completed, TaskState.failed, TaskState.canceled]:
409
+ received_final_task = True
397
410
  elif isinstance(request, CancelTaskRequest):
398
411
  # Forward cancel request to downstream agent using the downstream task ID
399
412
  # The request.params.id contains SAM's task ID, but we need to send
@@ -555,6 +568,20 @@ class A2AProxyComponent(BaseProxyComponent):
555
568
  # and publish an error response.
556
569
  raise
557
570
 
571
+ # After retry loop completes - check if we received a final task
572
+ # This detects cases where the stream closes without error but also without final response
573
+ if not received_final_task and isinstance(request, (SendStreamingMessageRequest, SendMessageRequest)):
574
+ from ....common.a2a import create_error_response
575
+
576
+ error_msg = f"Remote agent '{agent_name}' disconnected without completing the task. Agent may have crashed."
577
+ log.error("%s %s", log_identifier, error_msg)
578
+
579
+ error = InternalError(message=error_msg, data={"agent_name": agent_name})
580
+ reply_topic = task_context.a2a_context.get("reply_to_topic")
581
+ if reply_topic:
582
+ response = create_error_response(error=error, request_id=task_context.a2a_context.get("jsonrpc_request_id"))
583
+ self._publish_a2a_message(response.model_dump(exclude_none=True), reply_topic)
584
+
558
585
  async def _handle_auth_error(
559
586
  self, agent_name: str, task_context: ProxyTaskContext
560
587
  ) -> bool:
@@ -13,6 +13,10 @@ import threading
13
13
  import time
14
14
  from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union
15
15
 
16
+ from litellm.exceptions import BadRequestError
17
+
18
+ from ...common.error_handlers import get_error_message
19
+
16
20
  from a2a.types import (
17
21
  AgentCard,
18
22
  MessageSendParams,
@@ -74,7 +78,8 @@ from ...common.constants import (
74
78
  HEALTH_CHECK_INTERVAL_SECONDS,
75
79
  HEALTH_CHECK_TTL_SECONDS,
76
80
  )
77
- from ...common.data_parts import AgentProgressUpdateData
81
+ from ...common.a2a.types import ArtifactInfo
82
+ from ...common.data_parts import AgentProgressUpdateData, ArtifactSavedData
78
83
  from ...common.middleware.registry import MiddlewareRegistry
79
84
  from ...common.sac.sam_component_base import SamComponentBase
80
85
  from ...common.utils.rbac_utils import validate_agent_access
@@ -1526,6 +1531,68 @@ class SamAgentComponent(SamComponentBase):
1526
1531
  )
1527
1532
  return False
1528
1533
 
1534
+ async def notify_artifact_saved(
1535
+ self,
1536
+ artifact_info: ArtifactInfo,
1537
+ a2a_context: Dict[str, Any],
1538
+ function_call_id: Optional[str] = None,
1539
+ ) -> None:
1540
+ """
1541
+ Publishes an artifact saved notification signal.
1542
+
1543
+ This is a separate event from ArtifactCreationProgressData and does not
1544
+ follow the start->updates->end protocol. It's a single notification that
1545
+ an artifact has been successfully saved to storage.
1546
+
1547
+ Args:
1548
+ artifact_info: Information about the saved artifact
1549
+ a2a_context: The A2A context dictionary for the current task
1550
+ function_call_id: Optional function call ID if artifact was created by a tool
1551
+ """
1552
+ log_identifier = f"{self.log_identifier}[ArtifactSaved:{artifact_info.filename}]"
1553
+
1554
+ try:
1555
+ # Create artifact saved signal
1556
+ artifact_signal = ArtifactSavedData(
1557
+ type="artifact_saved",
1558
+ filename=artifact_info.filename,
1559
+ version=artifact_info.version,
1560
+ mime_type=artifact_info.mime_type or "application/octet-stream",
1561
+ size_bytes=artifact_info.size,
1562
+ description=artifact_info.description,
1563
+ function_call_id=function_call_id,
1564
+ )
1565
+
1566
+ # Create and publish status update event
1567
+ logical_task_id = a2a_context.get("logical_task_id")
1568
+ context_id = a2a_context.get("contextId")
1569
+
1570
+ status_update_event = a2a.create_data_signal_event(
1571
+ task_id=logical_task_id,
1572
+ context_id=context_id,
1573
+ signal_data=artifact_signal,
1574
+ agent_name=self.agent_name,
1575
+ )
1576
+
1577
+ await self._publish_status_update_with_buffer_flush(
1578
+ status_update_event,
1579
+ a2a_context,
1580
+ skip_buffer_flush=False,
1581
+ )
1582
+
1583
+ log.debug(
1584
+ "%s Published artifact saved notification for '%s' v%s.",
1585
+ log_identifier,
1586
+ artifact_info.filename,
1587
+ artifact_info.version,
1588
+ )
1589
+ except Exception as e:
1590
+ log.error(
1591
+ "%s Failed to publish artifact saved notification: %s",
1592
+ log_identifier,
1593
+ e,
1594
+ )
1595
+
1529
1596
  async def _publish_status_update_with_buffer_flush(
1530
1597
  self,
1531
1598
  status_update_event: TaskStatusUpdateEvent,
@@ -2646,10 +2713,25 @@ class SamAgentComponent(SamComponentBase):
2646
2713
  peer_reply_topic = a2a_context.get("replyToTopic")
2647
2714
  namespace = self.get_config("namespace")
2648
2715
 
2716
+ # Detect context limit errors and provide user-friendly message
2717
+ error_message = "An unexpected error occurred during tool execution. Please try your request again. If the problem persists, contact an administrator."
2718
+
2719
+ if isinstance(exception, BadRequestError):
2720
+ # Use centralized error handler
2721
+ error_message, is_context_limit = get_error_message(exception)
2722
+
2723
+ if is_context_limit:
2724
+ log.error(
2725
+ "%s Context limit exceeded for task %s. Error: %s",
2726
+ self.log_identifier,
2727
+ logical_task_id,
2728
+ exception,
2729
+ )
2730
+
2649
2731
  failed_status = a2a.create_task_status(
2650
2732
  state=TaskState.failed,
2651
2733
  message=a2a.create_agent_text_message(
2652
- text="An unexpected error occurred during tool execution. Please try your request again. If the problem persists, contact an administrator."
2734
+ text=error_message
2653
2735
  ),
2654
2736
  )
2655
2737
 
@@ -175,6 +175,7 @@ async def _internal_create_artifact(
175
175
  timestamp=timestamp_for_artifact,
176
176
  schema_max_keys=max_keys_to_use,
177
177
  tool_context=tool_context,
178
+ suppress_visualization_signal=True, # Fenced blocks handle their own visualization signals
178
179
  )
179
180
  log.info(
180
181
  "%s Result from save_artifact_with_metadata: %s", log_identifier, result
@@ -1740,18 +1741,20 @@ tool_registry.register(extract_content_from_artifact_tool_def)
1740
1741
  async def delete_artifact(
1741
1742
  filename: str,
1742
1743
  version: Optional[int] = None,
1744
+ confirm_delete: bool = False,
1743
1745
  tool_context: ToolContext = None,
1744
1746
  ) -> Dict[str, Any]:
1745
1747
  """
1746
- Deletes a specific version of an artifact, or all versions if no version is specified.
1748
+ Deletes all versions of an artifact. Version-specific deletion is not currently supported.
1747
1749
 
1748
1750
  Args:
1749
1751
  filename: The name of the artifact to delete.
1750
- version: The specific version number to delete. If not provided, all versions will be deleted.
1752
+ version: Reserved for future use. Currently not supported - returns error if specified.
1753
+ confirm_delete: Must be set to True to confirm deletion. If False, returns confirmation prompt.
1751
1754
  tool_context: The context provided by the ADK framework.
1752
1755
 
1753
1756
  Returns:
1754
- A dictionary indicating the result of the deletion.
1757
+ A dictionary indicating the result of the deletion or requesting confirmation.
1755
1758
  """
1756
1759
  if not tool_context:
1757
1760
  return {
@@ -1760,9 +1763,7 @@ async def delete_artifact(
1760
1763
  "message": "ToolContext is missing, cannot delete artifact.",
1761
1764
  }
1762
1765
 
1763
- log_identifier = (
1764
- f"[BuiltinArtifactTool:delete_artifact:{filename}:{version or 'all'}]"
1765
- )
1766
+ log_identifier = f"[BuiltinArtifactTool:delete_artifact:{filename}]"
1766
1767
  log.debug("%s Processing request.", log_identifier)
1767
1768
 
1768
1769
  try:
@@ -1780,14 +1781,32 @@ async def delete_artifact(
1780
1781
  "ArtifactService does not support deleting artifacts."
1781
1782
  )
1782
1783
 
1784
+ # Error if version-specific deletion requested (not currently supported)
1783
1785
  if version is not None:
1784
- log.warning(
1785
- "%s Deleting a specific version (%s) is not supported by the current artifact service interface. "
1786
- "All versions of the artifact will be deleted.",
1787
- log_identifier,
1788
- version,
1789
- )
1786
+ return {
1787
+ "status": "error",
1788
+ "filename": filename,
1789
+ "version_requested": version,
1790
+ "message": f"Deleting a specific version ({version}) is not currently supported. Only deletion of ALL versions is supported. To delete all versions, omit 'version' and set confirm_delete=True.",
1791
+ }
1792
+
1793
+ # Get version list for confirmation message
1794
+ versions = await artifact_service.list_versions(
1795
+ app_name=app_name, user_id=user_id, session_id=session_id, filename=filename
1796
+ )
1790
1797
 
1798
+ # Require confirmation before deleting
1799
+ if not confirm_delete:
1800
+ count = len(versions) if versions else "unknown number of"
1801
+ return {
1802
+ "status": "confirmation_required",
1803
+ "filename": filename,
1804
+ "version_count": len(versions) if versions else None,
1805
+ "versions": versions,
1806
+ "message": f"WARNING: This operation is irreversible and will permanently delete artifact '{filename}' and ALL {count} version(s). To proceed, call this tool again with confirm_delete=True.",
1807
+ }
1808
+
1809
+ # Proceed with deletion
1791
1810
  await artifact_service.delete_artifact(
1792
1811
  app_name=app_name,
1793
1812
  user_id=user_id,
@@ -1795,17 +1814,12 @@ async def delete_artifact(
1795
1814
  filename=filename,
1796
1815
  )
1797
1816
 
1798
- log.info(
1799
- "%s Successfully deleted artifact '%s' version '%s'.",
1800
- log_identifier,
1801
- filename,
1802
- version or "all",
1803
- )
1817
+ log.info("%s Successfully deleted artifact '%s'.", log_identifier, filename)
1804
1818
  return {
1805
1819
  "status": "success",
1806
1820
  "filename": filename,
1807
- "version": version or "all",
1808
- "message": f"Artifact '{filename}' version '{version or 'all'}' deleted successfully.",
1821
+ "versions_deleted": len(versions) if versions else None,
1822
+ "message": f"Artifact '{filename}' deleted successfully.",
1809
1823
  }
1810
1824
 
1811
1825
  except FileNotFoundError as e:
@@ -1829,7 +1843,7 @@ async def delete_artifact(
1829
1843
  delete_artifact_tool_def = BuiltinTool(
1830
1844
  name="delete_artifact",
1831
1845
  implementation=delete_artifact,
1832
- description="Deletes a specific version of an artifact, or all versions if no version is specified.",
1846
+ description="Deletes all versions of an artifact. IMPORTANT: Requires explicit confirmation via confirm_delete=True parameter. The first call without confirmation will return details about what will be deleted.",
1833
1847
  category="artifact_management",
1834
1848
  category_name=CATEGORY_NAME,
1835
1849
  category_description=CATEGORY_DESCRIPTION,
@@ -1843,7 +1857,12 @@ delete_artifact_tool_def = BuiltinTool(
1843
1857
  ),
1844
1858
  "version": adk_types.Schema(
1845
1859
  type=adk_types.Type.INTEGER,
1846
- description="The specific version number to delete. If not provided, all versions will be deleted.",
1860
+ description="Reserved for future use. Version-specific deletion is not currently supported - will return error if specified.",
1861
+ nullable=True,
1862
+ ),
1863
+ "confirm_delete": adk_types.Schema(
1864
+ type=adk_types.Type.BOOLEAN,
1865
+ description="Must be set to True to actually perform the deletion. If False or omitted, returns a confirmation prompt with details about what will be deleted (including version count).",
1847
1866
  nullable=True,
1848
1867
  ),
1849
1868
  },
@@ -20,6 +20,7 @@ from ...common.exceptions import MessageSizeExceededError
20
20
 
21
21
  log = logging.getLogger(__name__)
22
22
 
23
+
23
24
  class ArtifactIdentifier(BaseModel):
24
25
  """Identifies a specific version of an artifact."""
25
26
 
@@ -90,7 +91,10 @@ class PeerAgentTool(BaseTool):
90
91
  Enhanced description string with markdown formatting
91
92
  """
92
93
  # Start with base description - ensure it's clean (no extra whitespace)
93
- base_desc = agent_card.description or f"Interact with the {self.target_agent_name} agent."
94
+ base_desc = (
95
+ agent_card.description
96
+ or f"Interact with the {self.target_agent_name} agent."
97
+ )
94
98
  base_desc = " ".join(base_desc.split()) # Normalize whitespace
95
99
 
96
100
  # Extract skills information
@@ -101,7 +105,7 @@ class PeerAgentTool(BaseTool):
101
105
  skill_names = []
102
106
  for skill in agent_card.skills[:max_skills_to_show]:
103
107
  # Prefer name, fallback to id
104
- skill_name = getattr(skill, 'name', None) or getattr(skill, 'id', None)
108
+ skill_name = getattr(skill, "name", None) or getattr(skill, "id", None)
105
109
  if skill_name:
106
110
  skill_names.append(skill_name)
107
111
 
@@ -113,7 +117,9 @@ class PeerAgentTool(BaseTool):
113
117
 
114
118
  # Include skill count in the header
115
119
  if skill_count > 1:
116
- enhanced_desc = f"{base_desc}\n\n**Skills ({skill_count}):** {skills_str}"
120
+ enhanced_desc = (
121
+ f"{base_desc}\n\n**Skills ({skill_count}):** {skills_str}"
122
+ )
117
123
  else:
118
124
  enhanced_desc = f"{base_desc}\n\n**Skills:** {skills_str}"
119
125
 
@@ -122,7 +128,9 @@ class PeerAgentTool(BaseTool):
122
128
  # Truncate to first 4 skills to keep it concise
123
129
  skill_names = []
124
130
  for skill in agent_card.skills[:4]:
125
- skill_name = getattr(skill, 'name', None) or getattr(skill, 'id', None)
131
+ skill_name = getattr(skill, "name", None) or getattr(
132
+ skill, "id", None
133
+ )
126
134
  if skill_name:
127
135
  skill_names.append(skill_name)
128
136
  skills_str = ", ".join(skill_names)
@@ -131,7 +139,9 @@ class PeerAgentTool(BaseTool):
131
139
  skills_str += f" ({remaining} more...)"
132
140
 
133
141
  if skill_count > 1:
134
- enhanced_desc = f"{base_desc}\n\n**Skills ({skill_count}):** {skills_str}"
142
+ enhanced_desc = (
143
+ f"{base_desc}\n\n**Skills ({skill_count}):** {skills_str}"
144
+ )
135
145
  else:
136
146
  enhanced_desc = f"{base_desc}\n\n**Skills:** {skills_str}"
137
147
  else:
@@ -264,13 +274,10 @@ class PeerAgentTool(BaseTool):
264
274
  f"TaskExecutionContext not found for task '{main_logical_task_id}'"
265
275
  )
266
276
 
267
- task_context_obj.register_parallel_call_sent(invocation_id)
268
- log.info(
269
- "%s Registered parallel call for invocation %s. Current state: %s",
270
- log_identifier,
271
- invocation_id,
272
- task_context_obj.parallel_tool_calls.get(invocation_id),
273
- )
277
+ # NOTE: register_parallel_call_sent is called in
278
+ # preregister_long_running_tools_callback (after_model_callback)
279
+ # BEFORE tool execution begins. This prevents race conditions where
280
+ # one tool completes before another registers.
274
281
 
275
282
  a2a_message_parts = self._prepare_a2a_parts(args, tool_context)
276
283
  a2a_metadata = {}
@@ -47,11 +47,31 @@ class McpToolConfig(BaseToolConfig):
47
47
  """Configuration for an MCP tool or toolset."""
48
48
  tool_type: Literal["mcp"]
49
49
  connection_params: Dict[str, Any]
50
- tool_name: Optional[str] = None # Optional filter
50
+ tool_name: Optional[str] = None # Single tool filter (backward compat)
51
+ tool_name_prefix: Optional[str] = None # Optional prefix for tool names
51
52
  environment_variables: Optional[Dict[str, Any]] = None
52
53
  auth: dict[str, Any] | None = None
53
54
  manifest: list[dict[str, Any]] | None = None
54
55
 
56
+ # Tool filtering options (mutually exclusive with each other AND with tool_name)
57
+ allow_list: Optional[List[str]] = None # Include only these tools
58
+ deny_list: Optional[List[str]] = None # Exclude these tools
59
+
60
+ @model_validator(mode='after')
61
+ def validate_tool_filtering(self):
62
+ """Ensure tool_name, allow_list, and deny_list are mutually exclusive."""
63
+ filters_specified = [
64
+ self.tool_name is not None,
65
+ self.allow_list is not None,
66
+ self.deny_list is not None,
67
+ ]
68
+ if sum(filters_specified) > 1:
69
+ raise ValueError(
70
+ "MCP tool configuration error: 'tool_name', 'allow_list', and 'deny_list' "
71
+ "are mutually exclusive. Please use only one."
72
+ )
73
+ return self
74
+
55
75
 
56
76
  class OpenApiToolConfig(BaseToolConfig):
57
77
  """Configuration for OpenAPI-based tools."""