solace-agent-mesh 1.7.1__py3-none-any.whl → 1.13.2__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 solace-agent-mesh might be problematic. Click here for more details.

Files changed (447) hide show
  1. solace_agent_mesh/agent/adk/alembic/README +74 -0
  2. solace_agent_mesh/agent/adk/alembic/env.py +77 -0
  3. solace_agent_mesh/agent/adk/alembic/script.py.mako +28 -0
  4. solace_agent_mesh/agent/adk/alembic/versions/e2902798564d_adk_session_db_upgrade.py +52 -0
  5. solace_agent_mesh/agent/adk/alembic.ini +112 -0
  6. solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +164 -0
  7. solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +163 -0
  8. solace_agent_mesh/agent/adk/callbacks.py +752 -127
  9. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +99 -7
  10. solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +52 -5
  11. solace_agent_mesh/agent/adk/mcp_content_processor.py +1 -1
  12. solace_agent_mesh/agent/adk/models/lite_llm.py +34 -16
  13. solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +24 -137
  14. solace_agent_mesh/agent/adk/runner.py +66 -8
  15. solace_agent_mesh/agent/adk/schema_migration.py +88 -0
  16. solace_agent_mesh/agent/adk/services.py +41 -1
  17. solace_agent_mesh/agent/adk/setup.py +220 -32
  18. solace_agent_mesh/agent/adk/stream_parser.py +229 -40
  19. solace_agent_mesh/agent/protocol/event_handlers.py +219 -33
  20. solace_agent_mesh/agent/proxies/a2a/component.py +572 -75
  21. solace_agent_mesh/agent/proxies/a2a/config.py +80 -4
  22. solace_agent_mesh/agent/proxies/base/component.py +188 -22
  23. solace_agent_mesh/agent/proxies/base/proxy_task_context.py +3 -1
  24. solace_agent_mesh/agent/sac/app.py +37 -12
  25. solace_agent_mesh/agent/sac/component.py +322 -52
  26. solace_agent_mesh/agent/sac/patch_adk.py +8 -16
  27. solace_agent_mesh/agent/sac/task_execution_context.py +90 -0
  28. solace_agent_mesh/agent/tools/__init__.py +3 -0
  29. solace_agent_mesh/agent/tools/audio_tools.py +3 -3
  30. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +698 -24
  31. solace_agent_mesh/agent/tools/deep_research_tools.py +2161 -0
  32. solace_agent_mesh/agent/tools/peer_agent_tool.py +82 -15
  33. solace_agent_mesh/agent/tools/time_tools.py +126 -0
  34. solace_agent_mesh/agent/tools/tool_config_types.py +54 -2
  35. solace_agent_mesh/agent/tools/web_search_tools.py +279 -0
  36. solace_agent_mesh/agent/tools/web_tools.py +125 -17
  37. solace_agent_mesh/agent/utils/artifact_helpers.py +243 -5
  38. solace_agent_mesh/agent/utils/context_helpers.py +17 -0
  39. solace_agent_mesh/assets/docs/404.html +6 -6
  40. solace_agent_mesh/assets/docs/assets/css/{styles.906a1503.css → styles.8162edfb.css} +1 -1
  41. solace_agent_mesh/assets/docs/assets/js/05749d90.19ac4f35.js +1 -0
  42. solace_agent_mesh/assets/docs/assets/js/15ba94aa.e186750d.js +1 -0
  43. solace_agent_mesh/assets/docs/assets/js/15e40e79.434bb30f.js +1 -0
  44. solace_agent_mesh/assets/docs/assets/js/17896441.e612dfb4.js +1 -0
  45. solace_agent_mesh/assets/docs/assets/js/2279.550aa580.js +2 -0
  46. solace_agent_mesh/assets/docs/assets/js/{17896441.a5e82f9b.js.LICENSE.txt → 2279.550aa580.js.LICENSE.txt} +6 -0
  47. solace_agent_mesh/assets/docs/assets/js/240a0364.83e37aa8.js +1 -0
  48. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.2f0db237.js +1 -0
  49. solace_agent_mesh/assets/docs/assets/js/3a6c6137.7e61915d.js +1 -0
  50. solace_agent_mesh/assets/docs/assets/js/3ac1795d.7f7ab1c1.js +1 -0
  51. solace_agent_mesh/assets/docs/assets/js/3ff0015d.e53c9b78.js +1 -0
  52. solace_agent_mesh/assets/docs/assets/js/41adc471.0e95b87c.js +1 -0
  53. solace_agent_mesh/assets/docs/assets/js/4667dc50.bf2ad456.js +1 -0
  54. solace_agent_mesh/assets/docs/assets/js/49eed117.493d6f99.js +1 -0
  55. solace_agent_mesh/assets/docs/assets/js/{509e993c.4c7a1a6d.js → 509e993c.a1fbf45a.js} +1 -1
  56. solace_agent_mesh/assets/docs/assets/js/547e15cc.8e6da617.js +1 -0
  57. solace_agent_mesh/assets/docs/assets/js/55b7b518.29d6e75d.js +1 -0
  58. solace_agent_mesh/assets/docs/assets/js/5b8d9c11.d4eb37b8.js +1 -0
  59. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.1ee87753.js +1 -0
  60. solace_agent_mesh/assets/docs/assets/js/60702c0e.a8bdd79b.js +1 -0
  61. solace_agent_mesh/assets/docs/assets/js/64195356.09dbd087.js +1 -0
  62. solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.js +1 -0
  63. solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
  64. solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.js +1 -0
  65. solace_agent_mesh/assets/docs/assets/js/729898df.7249e9fd.js +1 -0
  66. solace_agent_mesh/assets/docs/assets/js/7e294c01.7c5f6906.js +1 -0
  67. solace_agent_mesh/assets/docs/assets/js/8024126c.e3467286.js +1 -0
  68. solace_agent_mesh/assets/docs/assets/js/81a99df0.7ed65d45.js +1 -0
  69. solace_agent_mesh/assets/docs/assets/js/82fbfb93.161823a5.js +1 -0
  70. solace_agent_mesh/assets/docs/assets/js/924ffdeb.975e428a.js +1 -0
  71. solace_agent_mesh/assets/docs/assets/js/94e8668d.16083b3f.js +1 -0
  72. solace_agent_mesh/assets/docs/assets/js/9bb13469.4523ae20.js +1 -0
  73. solace_agent_mesh/assets/docs/assets/js/a7d42657.a956689d.js +1 -0
  74. solace_agent_mesh/assets/docs/assets/js/a94703ab.3e5fbcb3.js +1 -0
  75. solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e563275.js +1 -0
  76. solace_agent_mesh/assets/docs/assets/js/c93cbaa0.0e0d8baf.js +1 -0
  77. solace_agent_mesh/assets/docs/assets/js/cab03b5b.6a073091.js +1 -0
  78. solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.07e170dd.js +1 -0
  79. solace_agent_mesh/assets/docs/assets/js/e04b235d.06d23db6.js +1 -0
  80. solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.deb2b62e.js +1 -0
  81. solace_agent_mesh/assets/docs/assets/js/e3d9abda.1476f570.js +1 -0
  82. solace_agent_mesh/assets/docs/assets/js/e6f9706b.acc800d3.js +1 -0
  83. solace_agent_mesh/assets/docs/assets/js/e92d0134.c147a429.js +1 -0
  84. solace_agent_mesh/assets/docs/assets/js/ee0c2fe7.94d0a351.js +1 -0
  85. solace_agent_mesh/assets/docs/assets/js/f284c35a.cc97854c.js +1 -0
  86. solace_agent_mesh/assets/docs/assets/js/main.d634009f.js +2 -0
  87. solace_agent_mesh/assets/docs/assets/js/runtime~main.27bb82a7.js +1 -0
  88. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +68 -68
  89. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +50 -50
  90. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +42 -42
  91. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +55 -55
  92. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +75 -75
  93. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/image-tools/index.html +81 -0
  94. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +67 -50
  95. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/research-tools/index.html +136 -0
  96. solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +178 -144
  97. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +43 -42
  98. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +20 -18
  99. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +23 -23
  100. solace_agent_mesh/assets/docs/docs/documentation/components/platform-service/index.html +33 -0
  101. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +45 -45
  102. solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +98 -112
  103. solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +147 -0
  104. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +208 -125
  105. solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +52 -0
  106. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +28 -28
  107. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +29 -29
  108. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +14 -14
  109. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/index.html +47 -0
  110. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/kubernetes-deployment-guide/index.html +197 -0
  111. solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +67 -53
  112. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +17 -17
  113. solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +49 -0
  114. solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +38 -38
  115. solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +87 -87
  116. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +67 -49
  117. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +17 -17
  118. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +51 -51
  119. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +22 -22
  120. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +27 -27
  121. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +135 -135
  122. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +66 -66
  123. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +51 -51
  124. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +50 -38
  125. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +86 -86
  126. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +51 -51
  127. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +24 -24
  128. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +30 -30
  129. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +44 -44
  130. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +115 -0
  131. solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +50 -23
  132. solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +29 -24
  133. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +21 -21
  134. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +40 -37
  135. solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +324 -0
  136. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +96 -66
  137. solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +181 -181
  138. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +75 -75
  139. solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +27 -27
  140. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +44 -44
  141. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +39 -38
  142. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +30 -30
  143. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +18 -18
  144. solace_agent_mesh/assets/docs/docs/documentation/getting-started/vibe_coding/index.html +62 -0
  145. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +135 -114
  146. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +37 -37
  147. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +14 -14
  148. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +27 -25
  149. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +69 -69
  150. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +72 -72
  151. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +112 -112
  152. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +28 -28
  153. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +42 -42
  154. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +20 -20
  155. solace_agent_mesh/assets/docs/docs/documentation/migrations/platform-service-split/index.html +85 -0
  156. solace_agent_mesh/assets/docs/lunr-index-1768329217460.json +1 -0
  157. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  158. solace_agent_mesh/assets/docs/search-doc-1768329217460.json +1 -0
  159. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  160. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  161. solace_agent_mesh/cli/__init__.py +1 -1
  162. solace_agent_mesh/cli/commands/add_cmd/__init__.py +3 -1
  163. solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +6 -1
  164. solace_agent_mesh/cli/commands/add_cmd/proxy_cmd.py +100 -0
  165. solace_agent_mesh/cli/commands/eval_cmd.py +1 -1
  166. solace_agent_mesh/cli/commands/init_cmd/__init__.py +15 -0
  167. solace_agent_mesh/cli/commands/init_cmd/directory_step.py +1 -1
  168. solace_agent_mesh/cli/commands/init_cmd/env_step.py +30 -3
  169. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +3 -4
  170. solace_agent_mesh/cli/commands/init_cmd/platform_service_step.py +85 -0
  171. solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +16 -3
  172. solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +2 -1
  173. solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +1 -0
  174. solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +3 -3
  175. solace_agent_mesh/cli/commands/run_cmd.py +64 -49
  176. solace_agent_mesh/cli/commands/tools_cmd.py +315 -0
  177. solace_agent_mesh/cli/main.py +15 -0
  178. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-tcIFZLis.js → authCallback-KnKMP_vb.js} +1 -1
  179. solace_agent_mesh/client/webui/frontend/static/assets/client-DpBL2stg.js +25 -0
  180. solace_agent_mesh/client/webui/frontend/static/assets/main-Cd498TV2.js +435 -0
  181. solace_agent_mesh/client/webui/frontend/static/assets/main-rSf8Vu29.css +1 -0
  182. solace_agent_mesh/client/webui/frontend/static/assets/{vendor-CINwxvwV.js → vendor-CGk8Suyh.js} +189 -94
  183. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  184. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  185. solace_agent_mesh/client/webui/frontend/static/mockServiceWorker.js +336 -0
  186. solace_agent_mesh/client/webui/frontend/static/ui-version.json +6 -0
  187. solace_agent_mesh/common/a2a/types.py +1 -1
  188. solace_agent_mesh/common/agent_registry.py +38 -11
  189. solace_agent_mesh/common/data_parts.py +124 -0
  190. solace_agent_mesh/common/error_handlers.py +83 -0
  191. solace_agent_mesh/common/exceptions.py +24 -0
  192. solace_agent_mesh/common/oauth/__init__.py +17 -0
  193. solace_agent_mesh/common/oauth/oauth_client.py +408 -0
  194. solace_agent_mesh/common/oauth/utils.py +50 -0
  195. solace_agent_mesh/common/rag_dto.py +156 -0
  196. solace_agent_mesh/common/sac/sam_component_base.py +73 -1
  197. solace_agent_mesh/common/sam_events/event_service.py +2 -2
  198. solace_agent_mesh/common/utils/embeds/converter.py +1 -8
  199. solace_agent_mesh/common/utils/embeds/modifiers.py +2 -27
  200. solace_agent_mesh/common/utils/embeds/resolver.py +94 -25
  201. solace_agent_mesh/common/utils/embeds/types.py +1 -0
  202. solace_agent_mesh/common/utils/log_formatters.py +20 -0
  203. solace_agent_mesh/common/utils/mime_helpers.py +12 -5
  204. solace_agent_mesh/common/utils/rbac_utils.py +69 -0
  205. solace_agent_mesh/common/utils/templates/__init__.py +8 -0
  206. solace_agent_mesh/common/utils/templates/liquid_renderer.py +210 -0
  207. solace_agent_mesh/common/utils/templates/template_resolver.py +161 -0
  208. solace_agent_mesh/config_portal/backend/common.py +12 -0
  209. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-CljP4_mv.js +103 -0
  210. solace_agent_mesh/config_portal/frontend/static/client/assets/{components-Rk0n-9cK.js → components-CaC6hG8d.js} +22 -22
  211. solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-mvZjNKiz.js → entry.client-H_TM0YBt.js} +3 -3
  212. solace_agent_mesh/config_portal/frontend/static/client/assets/{index-DzNKzXrc.js → index-CnFykb2v.js} +16 -16
  213. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-f8439d40.js +1 -0
  214. solace_agent_mesh/config_portal/frontend/static/client/assets/root-BIMqslJB.css +1 -0
  215. solace_agent_mesh/config_portal/frontend/static/client/assets/root-mJmTIdIk.js +10 -0
  216. solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
  217. solace_agent_mesh/core_a2a/service.py +3 -2
  218. solace_agent_mesh/gateway/adapter/base.py +28 -1
  219. solace_agent_mesh/gateway/adapter/types.py +9 -0
  220. solace_agent_mesh/gateway/base/app.py +10 -0
  221. solace_agent_mesh/gateway/base/auth_interface.py +103 -0
  222. solace_agent_mesh/gateway/base/component.py +451 -10
  223. solace_agent_mesh/gateway/generic/component.py +274 -30
  224. solace_agent_mesh/gateway/http_sse/alembic/env.py +0 -7
  225. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +2 -43
  226. solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +2 -2
  227. solace_agent_mesh/gateway/http_sse/alembic/versions/20251108_create_prompt_tables_with_sharing.py +154 -0
  228. solace_agent_mesh/gateway/http_sse/alembic/versions/20251115_add_parent_task_id.py +32 -0
  229. solace_agent_mesh/gateway/http_sse/alembic/versions/20251126_add_background_task_fields.py +47 -0
  230. solace_agent_mesh/gateway/http_sse/alembic/versions/20251202_add_versioned_fields_to_prompts.py +52 -0
  231. solace_agent_mesh/gateway/http_sse/alembic.ini +0 -36
  232. solace_agent_mesh/gateway/http_sse/app.py +23 -6
  233. solace_agent_mesh/gateway/http_sse/component.py +158 -73
  234. solace_agent_mesh/gateway/http_sse/dependencies.py +50 -57
  235. solace_agent_mesh/gateway/http_sse/main.py +58 -482
  236. solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
  237. solace_agent_mesh/gateway/http_sse/repository/entities/project.py +1 -1
  238. solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +1 -1
  239. solace_agent_mesh/gateway/http_sse/repository/entities/session.py +3 -2
  240. solace_agent_mesh/gateway/http_sse/repository/entities/task.py +7 -0
  241. solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +2 -2
  242. solace_agent_mesh/gateway/http_sse/repository/interfaces.py +2 -2
  243. solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +5 -0
  244. solace_agent_mesh/gateway/http_sse/repository/models/prompt_model.py +159 -0
  245. solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +1 -1
  246. solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +8 -1
  247. solace_agent_mesh/gateway/http_sse/repository/project_repository.py +1 -1
  248. solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +1 -1
  249. solace_agent_mesh/gateway/http_sse/repository/session_repository.py +12 -107
  250. solace_agent_mesh/gateway/http_sse/repository/task_repository.py +86 -2
  251. solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +38 -7
  252. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +113 -7
  253. solace_agent_mesh/gateway/http_sse/routers/auth.py +69 -132
  254. solace_agent_mesh/gateway/http_sse/routers/config.py +235 -10
  255. solace_agent_mesh/gateway/http_sse/routers/dto/project_dto.py +69 -0
  256. solace_agent_mesh/gateway/http_sse/routers/dto/prompt_dto.py +255 -0
  257. solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +1 -1
  258. solace_agent_mesh/gateway/http_sse/routers/dto/responses/base_responses.py +1 -1
  259. solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +1 -0
  260. solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +3 -2
  261. solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
  262. solace_agent_mesh/gateway/http_sse/routers/feedback.py +2 -2
  263. solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
  264. solace_agent_mesh/gateway/http_sse/routers/projects.py +250 -24
  265. solace_agent_mesh/gateway/http_sse/routers/prompts.py +1416 -0
  266. solace_agent_mesh/gateway/http_sse/routers/sessions.py +14 -5
  267. solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
  268. solace_agent_mesh/gateway/http_sse/routers/sse.py +117 -4
  269. solace_agent_mesh/gateway/http_sse/routers/tasks.py +509 -149
  270. solace_agent_mesh/gateway/http_sse/routers/users.py +1 -1
  271. solace_agent_mesh/gateway/http_sse/routers/version.py +343 -0
  272. solace_agent_mesh/gateway/http_sse/routers/visualization.py +2 -1
  273. solace_agent_mesh/gateway/http_sse/services/audio_service.py +1227 -0
  274. solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +186 -0
  275. solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +1 -1
  276. solace_agent_mesh/gateway/http_sse/services/feedback_service.py +1 -1
  277. solace_agent_mesh/gateway/http_sse/services/project_service.py +539 -12
  278. solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
  279. solace_agent_mesh/gateway/http_sse/services/session_service.py +198 -21
  280. solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +354 -4
  281. solace_agent_mesh/gateway/http_sse/sse_manager.py +280 -169
  282. solace_agent_mesh/gateway/http_sse/utils/artifact_copy_utils.py +370 -0
  283. solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +41 -1
  284. solace_agent_mesh/services/__init__.py +0 -0
  285. solace_agent_mesh/services/platform/__init__.py +29 -0
  286. solace_agent_mesh/services/platform/alembic/env.py +85 -0
  287. solace_agent_mesh/services/platform/alembic/script.py.mako +28 -0
  288. solace_agent_mesh/services/platform/alembic.ini +109 -0
  289. solace_agent_mesh/services/platform/api/__init__.py +3 -0
  290. solace_agent_mesh/services/platform/api/dependencies.py +154 -0
  291. solace_agent_mesh/services/platform/api/main.py +314 -0
  292. solace_agent_mesh/services/platform/api/middleware.py +51 -0
  293. solace_agent_mesh/services/platform/api/routers/__init__.py +33 -0
  294. solace_agent_mesh/services/platform/api/routers/health_router.py +31 -0
  295. solace_agent_mesh/services/platform/app.py +215 -0
  296. solace_agent_mesh/services/platform/component.py +777 -0
  297. solace_agent_mesh/shared/__init__.py +14 -0
  298. solace_agent_mesh/shared/api/__init__.py +42 -0
  299. solace_agent_mesh/shared/auth/__init__.py +26 -0
  300. solace_agent_mesh/shared/auth/dependencies.py +204 -0
  301. solace_agent_mesh/shared/auth/middleware.py +347 -0
  302. solace_agent_mesh/shared/database/__init__.py +20 -0
  303. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/base_repository.py +1 -1
  304. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_exceptions.py +1 -1
  305. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_helpers.py +1 -1
  306. solace_agent_mesh/shared/exceptions/__init__.py +36 -0
  307. solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exception_handlers.py +1 -1
  308. solace_agent_mesh/shared/utils/__init__.py +21 -0
  309. solace_agent_mesh/templates/logging_config_template.yaml +48 -0
  310. solace_agent_mesh/templates/main_orchestrator.yaml +12 -1
  311. solace_agent_mesh/templates/platform.yaml +49 -0
  312. solace_agent_mesh/templates/plugin_readme_template.md +3 -25
  313. solace_agent_mesh/templates/plugin_tool_config_template.yaml +109 -0
  314. solace_agent_mesh/templates/proxy_template.yaml +62 -0
  315. solace_agent_mesh/templates/webui.yaml +148 -6
  316. solace_agent_mesh/tools/web_search/__init__.py +18 -0
  317. solace_agent_mesh/tools/web_search/base.py +84 -0
  318. solace_agent_mesh/tools/web_search/google_search.py +247 -0
  319. solace_agent_mesh/tools/web_search/models.py +99 -0
  320. {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/METADATA +29 -8
  321. {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/RECORD +334 -313
  322. {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/WHEEL +1 -1
  323. solace_agent_mesh/agent/adk/adk_llm.txt +0 -226
  324. solace_agent_mesh/agent/adk/adk_llm_detail.txt +0 -566
  325. solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +0 -171
  326. solace_agent_mesh/agent/adk/models/models_llm.txt +0 -189
  327. solace_agent_mesh/agent/agent_llm.txt +0 -369
  328. solace_agent_mesh/agent/agent_llm_detail.txt +0 -1702
  329. solace_agent_mesh/agent/protocol/protocol_llm.txt +0 -81
  330. solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +0 -92
  331. solace_agent_mesh/agent/proxies/a2a/a2a_llm.txt +0 -190
  332. solace_agent_mesh/agent/proxies/base/base_llm.txt +0 -148
  333. solace_agent_mesh/agent/proxies/proxies_llm.txt +0 -283
  334. solace_agent_mesh/agent/sac/sac_llm.txt +0 -189
  335. solace_agent_mesh/agent/sac/sac_llm_detail.txt +0 -200
  336. solace_agent_mesh/agent/testing/testing_llm.txt +0 -58
  337. solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
  338. solace_agent_mesh/agent/tools/tools_llm.txt +0 -276
  339. solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -275
  340. solace_agent_mesh/agent/utils/utils_llm.txt +0 -152
  341. solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
  342. solace_agent_mesh/assets/docs/assets/js/05749d90.c70b2be9.js +0 -1
  343. solace_agent_mesh/assets/docs/assets/js/15ba94aa.92fea363.js +0 -1
  344. solace_agent_mesh/assets/docs/assets/js/15e40e79.36003774.js +0 -1
  345. solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +0 -2
  346. solace_agent_mesh/assets/docs/assets/js/240a0364.c39f8388.js +0 -1
  347. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +0 -1
  348. solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +0 -1
  349. solace_agent_mesh/assets/docs/assets/js/3ac1795d.e4870a49.js +0 -1
  350. solace_agent_mesh/assets/docs/assets/js/3ff0015d.b63ee53a.js +0 -1
  351. solace_agent_mesh/assets/docs/assets/js/547e15cc.2f7790c1.js +0 -1
  352. solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +0 -1
  353. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.45b32c2b.js +0 -1
  354. solace_agent_mesh/assets/docs/assets/js/64195356.c498c4d0.js +0 -1
  355. solace_agent_mesh/assets/docs/assets/js/66d4869e.830d443f.js +0 -1
  356. solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +0 -1
  357. solace_agent_mesh/assets/docs/assets/js/8024126c.fa0e7186.js +0 -1
  358. solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +0 -1
  359. solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +0 -1
  360. solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +0 -1
  361. solace_agent_mesh/assets/docs/assets/js/94e8668d.09ed9234.js +0 -1
  362. solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +0 -1
  363. solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +0 -1
  364. solace_agent_mesh/assets/docs/assets/js/ab9708a8.245ae0ef.js +0 -1
  365. solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +0 -1
  366. solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.f902fad8.js +0 -1
  367. solace_agent_mesh/assets/docs/assets/js/db5d6442.3daf1696.js +0 -1
  368. solace_agent_mesh/assets/docs/assets/js/e04b235d.c9c50c7b.js +0 -1
  369. solace_agent_mesh/assets/docs/assets/js/e3d9abda.d11c67a7.js +0 -1
  370. solace_agent_mesh/assets/docs/assets/js/e6f9706b.045d0fa1.js +0 -1
  371. solace_agent_mesh/assets/docs/assets/js/e92d0134.3bda61dd.js +0 -1
  372. solace_agent_mesh/assets/docs/assets/js/f284c35a.5099c51e.js +0 -1
  373. solace_agent_mesh/assets/docs/assets/js/main.f213fe0c.js +0 -2
  374. solace_agent_mesh/assets/docs/assets/js/runtime~main.d9606d6a.js +0 -1
  375. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes-deployment/index.html +0 -47
  376. solace_agent_mesh/assets/docs/lunr-index-1762283454666.json +0 -1
  377. solace_agent_mesh/assets/docs/search-doc-1762283454666.json +0 -1
  378. solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +0 -250
  379. solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +0 -365
  380. solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +0 -305
  381. solace_agent_mesh/client/webui/frontend/static/assets/client-CRYdKo2Q.js +0 -25
  382. solace_agent_mesh/client/webui/frontend/static/assets/main-CojeY_1w.css +0 -1
  383. solace_agent_mesh/client/webui/frontend/static/assets/main-ILja9MCG.js +0 -353
  384. solace_agent_mesh/common/a2a/a2a_llm.txt +0 -175
  385. solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
  386. solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -445
  387. solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
  388. solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -330
  389. solace_agent_mesh/common/common_llm.txt +0 -230
  390. solace_agent_mesh/common/common_llm_detail.txt +0 -2562
  391. solace_agent_mesh/common/middleware/middleware_llm.txt +0 -174
  392. solace_agent_mesh/common/middleware/middleware_llm_detail.txt +0 -185
  393. solace_agent_mesh/common/sac/sac_llm.txt +0 -71
  394. solace_agent_mesh/common/sac/sac_llm_detail.txt +0 -82
  395. solace_agent_mesh/common/sam_events/sam_events_llm.txt +0 -104
  396. solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +0 -115
  397. solace_agent_mesh/common/services/providers/providers_llm.txt +0 -81
  398. solace_agent_mesh/common/services/services_llm.txt +0 -368
  399. solace_agent_mesh/common/services/services_llm_detail.txt +0 -459
  400. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +0 -220
  401. solace_agent_mesh/common/utils/utils_llm.txt +0 -335
  402. solace_agent_mesh/common/utils/utils_llm_detail.txt +0 -572
  403. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +0 -98
  404. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-61038fc6.js +0 -1
  405. solace_agent_mesh/config_portal/frontend/static/client/assets/root-BWvk5-gF.js +0 -10
  406. solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +0 -1
  407. solace_agent_mesh/core_a2a/core_a2a_llm.txt +0 -90
  408. solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +0 -101
  409. solace_agent_mesh/gateway/base/base_llm.txt +0 -226
  410. solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
  411. solace_agent_mesh/gateway/gateway_llm.txt +0 -369
  412. solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
  413. solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -345
  414. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_fulltext_search_indexes.py +0 -92
  415. solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -161
  416. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +0 -105
  417. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +0 -299
  418. solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +0 -3278
  419. solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +0 -221
  420. solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -257
  421. solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -308
  422. solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -450
  423. solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -133
  424. solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -123
  425. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -312
  426. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -303
  427. solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
  428. solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -319
  429. solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +0 -47
  430. solace_agent_mesh/llm.txt +0 -228
  431. solace_agent_mesh/llm_detail.txt +0 -2835
  432. solace_agent_mesh/solace_agent_mesh_llm.txt +0 -362
  433. solace_agent_mesh/solace_agent_mesh_llm_detail.txt +0 -8599
  434. solace_agent_mesh/templates/logging_config_template.ini +0 -45
  435. solace_agent_mesh/templates/templates_llm.txt +0 -147
  436. /solace_agent_mesh/assets/docs/assets/js/{main.f213fe0c.js.LICENSE.txt → main.d634009f.js.LICENSE.txt} +0 -0
  437. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/auth_utils.py +0 -0
  438. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/pagination.py +0 -0
  439. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/response_utils.py +0 -0
  440. /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/error_dto.py +0 -0
  441. /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exceptions.py +0 -0
  442. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/enums.py +0 -0
  443. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/timestamp_utils.py +0 -0
  444. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/types.py +0 -0
  445. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/utils.py +0 -0
  446. {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/entry_points.txt +0 -0
  447. {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/licenses/LICENSE +0 -0
@@ -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,
@@ -39,6 +43,7 @@ from google.adk.models.llm_request import LlmRequest
39
43
  from google.adk.runners import Runner
40
44
  from google.adk.sessions import BaseSessionService
41
45
  from google.adk.tools.mcp_tool import MCPToolset
46
+ from google.adk.tools.openapi_tool import OpenAPIToolset
42
47
  from google.genai import types as adk_types
43
48
  from pydantic import BaseModel, ValidationError
44
49
  from solace_ai_connector.common.event import Event, EventType
@@ -73,9 +78,11 @@ from ...common.constants import (
73
78
  HEALTH_CHECK_INTERVAL_SECONDS,
74
79
  HEALTH_CHECK_TTL_SECONDS,
75
80
  )
76
- from ...common.data_parts import AgentProgressUpdateData
81
+ from ...common.a2a.types import ArtifactInfo
82
+ from ...common.data_parts import AgentProgressUpdateData, ArtifactSavedData
77
83
  from ...common.middleware.registry import MiddlewareRegistry
78
84
  from ...common.sac.sam_component_base import SamComponentBase
85
+ from ...common.utils.rbac_utils import validate_agent_access
79
86
 
80
87
  log = logging.getLogger(__name__)
81
88
 
@@ -104,6 +111,7 @@ info = {
104
111
  }
105
112
  InstructionProvider = Callable[[ReadonlyContext], str]
106
113
 
114
+
107
115
  class SamAgentComponent(SamComponentBase):
108
116
  """
109
117
  A Solace AI Connector component that hosts a Google ADK agent,
@@ -128,7 +136,11 @@ class SamAgentComponent(SamComponentBase):
128
136
 
129
137
  super().__init__(info, **kwargs)
130
138
  self.agent_name = self.get_config("agent_name")
131
- log.info("%s Initializing agent: %s (A2A ADK Host Component)...", self.log_identifier, self.agent_name)
139
+ log.info(
140
+ "%s Initializing agent: %s (A2A ADK Host Component)...",
141
+ self.log_identifier,
142
+ self.agent_name,
143
+ )
132
144
 
133
145
  # Initialize the agent registry for health tracking
134
146
  self.agent_registry = AgentRegistry()
@@ -416,28 +428,6 @@ class SamAgentComponent(SamComponentBase):
416
428
  # We still need a future to signal completion from the async thread.
417
429
  self._async_init_future = concurrent.futures.Future()
418
430
 
419
- publish_interval_sec = self.agent_card_publishing_config.get(
420
- "interval_seconds"
421
- )
422
- if publish_interval_sec and publish_interval_sec > 0:
423
- log.info(
424
- "%s Scheduling agent card publishing every %d seconds.",
425
- self.log_identifier,
426
- publish_interval_sec,
427
- )
428
- # Register timer with callback
429
- self.add_timer(
430
- delay_ms=1000,
431
- timer_id=self._card_publish_timer_id,
432
- interval_ms=publish_interval_sec * 1000,
433
- callback=lambda timer_data: publish_agent_card(self),
434
- )
435
- else:
436
- log.warning(
437
- "%s Agent card publishing interval not configured or invalid, card will not be published periodically.",
438
- self.log_identifier,
439
- )
440
-
441
431
  # Set up health check timer if enabled
442
432
  health_check_interval_seconds = self.agent_discovery_config.get(
443
433
  "health_check_interval_seconds", HEALTH_CHECK_INTERVAL_SECONDS
@@ -793,13 +783,8 @@ class SamAgentComponent(SamComponentBase):
793
783
  log_retrigger,
794
784
  len(new_response_parts),
795
785
  )
796
- new_adk_event = ADKEvent(
797
- invocation_id=paused_invocation_id,
798
- author=self.agent_name,
799
- content=adk_types.Content(role="tool", parts=new_response_parts),
800
- )
801
- await self.session_service.append_event(
802
- session=session, event=new_adk_event
786
+ new_tool_response_content = adk_types.Content(
787
+ role="tool", parts=new_response_parts
803
788
  )
804
789
 
805
790
  # Always use SSE streaming mode for the ADK runner, even on re-trigger.
@@ -818,7 +803,12 @@ class SamAgentComponent(SamComponentBase):
818
803
  )
819
804
  try:
820
805
  await run_adk_async_task_thread_wrapper(
821
- self, session, None, run_config, original_task_context
806
+ self,
807
+ session,
808
+ new_tool_response_content,
809
+ run_config,
810
+ original_task_context,
811
+ append_context_event=False,
822
812
  )
823
813
  finally:
824
814
  log.info(
@@ -1007,12 +997,13 @@ class SamAgentComponent(SamComponentBase):
1007
997
  )
1008
998
  if peer_tool_instance.name not in llm_request.tools_dict:
1009
999
  peer_tools_to_add.append(peer_tool_instance)
1010
- description = (
1011
- getattr(agent_card, "description", "No description")
1012
- or "No description"
1000
+ # Get enhanced description from the tool instance
1001
+ # which includes capabilities, skills, and tools
1002
+ enhanced_desc = peer_tool_instance._build_enhanced_description(
1003
+ agent_card
1013
1004
  )
1014
1005
  allowed_peer_descriptions.append(
1015
- f"- `peer_{peer_name}`: {description}"
1006
+ f"\n### `peer_{peer_name}`\n{enhanced_desc}"
1016
1007
  )
1017
1008
  except Exception as e:
1018
1009
  log.error(
@@ -1025,12 +1016,18 @@ class SamAgentComponent(SamComponentBase):
1025
1016
  if allowed_peer_descriptions:
1026
1017
  peer_list_str = "\n".join(allowed_peer_descriptions)
1027
1018
  instruction_text = (
1028
- "You can delegate tasks to other specialized agents if they are better suited.\n"
1029
- "Use the `peer_<agent_name>(task_description: str, user_query: str)` tool for delegation. "
1030
- "Replace `<agent_name>` with the actual name of the target agent.\n"
1031
- "Provide a clear `task_description` for the peer and include the original `user_query` for context.\n"
1032
- "Be aware that the peer agent may not have access to your session history, so you must provide all required context necessary to fulfill the request.\n\n"
1033
- "Available peer agents you can delegate to (use the `peer_...` tool name):\n"
1019
+ "## Peer Agent Delegation\n\n"
1020
+ "You can delegate tasks to other specialized agents if they are better suited.\n\n"
1021
+ "**How to delegate:**\n"
1022
+ "- Use the `peer_<agent_name>(task_description: str)` tool for delegation\n"
1023
+ "- Replace `<agent_name>` with the actual name of the target agent\n"
1024
+ "- Provide a clear and detailed `task_description` for the peer agent\n"
1025
+ "- **Important:** The peer agent does not have access to your session history, "
1026
+ "so you must provide all required context necessary to fulfill the request\n\n"
1027
+ "IMPORTANT: When a peer agent's response contains citation markers like [[cite:search0]], [[cite:file1]], etc., "
1028
+ "you MUST preserve these markers in your response to the user. These markers link to source references and are "
1029
+ "essential for proper attribution. Include them exactly as they appear in the peer's response. DO NOT repeat them without markers.\n\n"
1030
+ "## Available Peer Agents\n"
1034
1031
  f"{peer_list_str}"
1035
1032
  )
1036
1033
  callback_context.state["peer_tool_instructions"] = instruction_text
@@ -1544,6 +1541,70 @@ class SamAgentComponent(SamComponentBase):
1544
1541
  )
1545
1542
  return False
1546
1543
 
1544
+ async def notify_artifact_saved(
1545
+ self,
1546
+ artifact_info: ArtifactInfo,
1547
+ a2a_context: Dict[str, Any],
1548
+ function_call_id: Optional[str] = None,
1549
+ ) -> None:
1550
+ """
1551
+ Publishes an artifact saved notification signal.
1552
+
1553
+ This is a separate event from ArtifactCreationProgressData and does not
1554
+ follow the start->updates->end protocol. It's a single notification that
1555
+ an artifact has been successfully saved to storage.
1556
+
1557
+ Args:
1558
+ artifact_info: Information about the saved artifact
1559
+ a2a_context: The A2A context dictionary for the current task
1560
+ function_call_id: Optional function call ID if artifact was created by a tool
1561
+ """
1562
+ log_identifier = (
1563
+ f"{self.log_identifier}[ArtifactSaved:{artifact_info.filename}]"
1564
+ )
1565
+
1566
+ try:
1567
+ # Create artifact saved signal
1568
+ artifact_signal = ArtifactSavedData(
1569
+ type="artifact_saved",
1570
+ filename=artifact_info.filename,
1571
+ version=artifact_info.version,
1572
+ mime_type=artifact_info.mime_type or "application/octet-stream",
1573
+ size_bytes=artifact_info.size,
1574
+ description=artifact_info.description,
1575
+ function_call_id=function_call_id,
1576
+ )
1577
+
1578
+ # Create and publish status update event
1579
+ logical_task_id = a2a_context.get("logical_task_id")
1580
+ context_id = a2a_context.get("contextId")
1581
+
1582
+ status_update_event = a2a.create_data_signal_event(
1583
+ task_id=logical_task_id,
1584
+ context_id=context_id,
1585
+ signal_data=artifact_signal,
1586
+ agent_name=self.agent_name,
1587
+ )
1588
+
1589
+ await self._publish_status_update_with_buffer_flush(
1590
+ status_update_event,
1591
+ a2a_context,
1592
+ skip_buffer_flush=False,
1593
+ )
1594
+
1595
+ log.debug(
1596
+ "%s Published artifact saved notification for '%s' v%s.",
1597
+ log_identifier,
1598
+ artifact_info.filename,
1599
+ artifact_info.version,
1600
+ )
1601
+ except Exception as e:
1602
+ log.error(
1603
+ "%s Failed to publish artifact saved notification: %s",
1604
+ log_identifier,
1605
+ e,
1606
+ )
1607
+
1547
1608
  async def _publish_status_update_with_buffer_flush(
1548
1609
  self,
1549
1610
  status_update_event: TaskStatusUpdateEvent,
@@ -1738,8 +1799,13 @@ class SamAgentComponent(SamComponentBase):
1738
1799
  is_final_turn_event = not adk_event.partial
1739
1800
 
1740
1801
  try:
1741
- from solace_agent_mesh_enterprise.auth.tool_auth import handle_tool_auth_event
1742
- auth_status_update = await handle_tool_auth_event(adk_event, self, a2a_context)
1802
+ from solace_agent_mesh_enterprise.auth.tool_auth import (
1803
+ handle_tool_auth_event,
1804
+ )
1805
+
1806
+ auth_status_update = await handle_tool_auth_event(
1807
+ adk_event, self, a2a_context
1808
+ )
1743
1809
  if auth_status_update:
1744
1810
  await self._publish_status_update_with_buffer_flush(
1745
1811
  auth_status_update,
@@ -1754,6 +1820,25 @@ class SamAgentComponent(SamComponentBase):
1754
1820
  if adk_event.content and adk_event.content.parts:
1755
1821
  for part in adk_event.content.parts:
1756
1822
  if part.text is not None:
1823
+ # Check if this is a new turn by comparing invocation_id
1824
+ if adk_event.invocation_id:
1825
+ task_context.check_and_update_invocation(
1826
+ adk_event.invocation_id
1827
+ )
1828
+ is_first_text = task_context.is_first_text_in_turn()
1829
+ should_add_spacing = task_context.should_add_turn_spacing()
1830
+
1831
+ # Add spacing if this is the first text of a new turn
1832
+ # We add it BEFORE the text, regardless of current buffer content
1833
+ if should_add_spacing and is_first_text:
1834
+ # Add double newline to separate turns (new paragraph)
1835
+ task_context.append_to_streaming_buffer("\n\n")
1836
+ log.debug(
1837
+ "%s Added turn spacing before new invocation %s",
1838
+ log_id_main,
1839
+ adk_event.invocation_id,
1840
+ )
1841
+
1757
1842
  task_context.append_to_streaming_buffer(part.text)
1758
1843
  log.debug(
1759
1844
  "%s Appended text to buffer. New buffer size: %d bytes",
@@ -2203,6 +2288,19 @@ class SamAgentComponent(SamComponentBase):
2203
2288
  self.log_identifier,
2204
2289
  len(task_context.produced_artifacts),
2205
2290
  )
2291
+ else:
2292
+ if not task_context:
2293
+ log.warning(
2294
+ "%s TaskExecutionContext not found for task %s during finalization, cannot attach produced artifacts.",
2295
+ self.log_identifier,
2296
+ logical_task_id,
2297
+ )
2298
+ else:
2299
+ log.debug(
2300
+ "%s No produced artifacts to attach for task %s.",
2301
+ self.log_identifier,
2302
+ logical_task_id,
2303
+ )
2206
2304
 
2207
2305
  # Add token usage summary
2208
2306
  if task_context:
@@ -2640,11 +2738,24 @@ class SamAgentComponent(SamComponentBase):
2640
2738
  peer_reply_topic = a2a_context.get("replyToTopic")
2641
2739
  namespace = self.get_config("namespace")
2642
2740
 
2741
+ # Detect context limit errors and provide user-friendly message
2742
+ error_message = "An unexpected error occurred during tool execution. Please try your request again. If the problem persists, contact an administrator."
2743
+
2744
+ if isinstance(exception, BadRequestError):
2745
+ # Use centralized error handler
2746
+ error_message, is_context_limit = get_error_message(exception)
2747
+
2748
+ if is_context_limit:
2749
+ log.error(
2750
+ "%s Context limit exceeded for task %s. Error: %s",
2751
+ self.log_identifier,
2752
+ logical_task_id,
2753
+ exception,
2754
+ )
2755
+
2643
2756
  failed_status = a2a.create_task_status(
2644
2757
  state=TaskState.failed,
2645
- message=a2a.create_agent_text_message(
2646
- text="An unexpected error occurred during tool execution. Please try your request again. If the problem persists, contact an administrator."
2647
- ),
2758
+ message=a2a.create_agent_text_message(text=error_message),
2648
2759
  )
2649
2760
 
2650
2761
  final_task = a2a.create_final_task(
@@ -2771,7 +2882,9 @@ class SamAgentComponent(SamComponentBase):
2771
2882
  with self.active_tasks_lock:
2772
2883
  task_context = self.active_tasks.get(logical_task_id)
2773
2884
  if task_context:
2774
- original_message = task_context.get_original_solace_message()
2885
+ original_message = (
2886
+ task_context.get_original_solace_message()
2887
+ )
2775
2888
 
2776
2889
  if original_message:
2777
2890
  try:
@@ -2953,6 +3066,17 @@ class SamAgentComponent(SamComponentBase):
2953
3066
  main_task_id,
2954
3067
  )
2955
3068
 
3069
+ # Validate agent access is allowed
3070
+ validate_agent_access(
3071
+ user_config=user_config,
3072
+ target_agent_name=target_agent_name,
3073
+ validation_context={
3074
+ "delegating_agent": self.get_config("agent_name"),
3075
+ "source": "agent_delegation",
3076
+ },
3077
+ log_identifier=log_identifier_helper,
3078
+ )
3079
+
2956
3080
  peer_request_topic = self._get_agent_request_topic(target_agent_name)
2957
3081
 
2958
3082
  # Create a compliant SendMessageRequest
@@ -3103,6 +3227,31 @@ class SamAgentComponent(SamComponentBase):
3103
3227
  or "No description available.",
3104
3228
  }
3105
3229
  )
3230
+ elif isinstance(tool, OpenAPIToolset):
3231
+ try:
3232
+ log.debug(
3233
+ "%s Retrieving tools from OpenAPIToolset for Agent %s...",
3234
+ self.log_identifier,
3235
+ self.agent_name,
3236
+ )
3237
+ openapi_tools = await tool.get_tools()
3238
+ except Exception as e:
3239
+ log.error(
3240
+ "%s Error retrieving tools from OpenAPIToolset for Agent Card %s: %s",
3241
+ self.log_identifier,
3242
+ self.agent_name,
3243
+ e,
3244
+ )
3245
+ continue
3246
+ for openapi_tool in openapi_tools:
3247
+ tool_manifest.append(
3248
+ {
3249
+ "id": openapi_tool.name,
3250
+ "name": openapi_tool.name,
3251
+ "description": openapi_tool.description
3252
+ or "No description available.",
3253
+ }
3254
+ )
3106
3255
  else:
3107
3256
  tool_name = getattr(tool, "name", getattr(tool, "__name__", None))
3108
3257
  if tool_name is not None:
@@ -3160,6 +3309,7 @@ class SamAgentComponent(SamComponentBase):
3160
3309
  "%s _perform_async_init: _async_init_future is None or already done before signaling failure.",
3161
3310
  self.log_identifier,
3162
3311
  )
3312
+ raise e
3163
3313
 
3164
3314
  def cleanup(self):
3165
3315
  """Clean up resources on component shutdown."""
@@ -3288,6 +3438,80 @@ class SamAgentComponent(SamComponentBase):
3288
3438
  """Returns the dedicated asyncio event loop for this component's async tasks."""
3289
3439
  return self._async_loop
3290
3440
 
3441
+ def publish_data_signal_from_thread(
3442
+ self,
3443
+ a2a_context: Dict[str, Any],
3444
+ signal_data: BaseModel,
3445
+ skip_buffer_flush: bool = False,
3446
+ log_identifier: Optional[str] = None,
3447
+ ) -> bool:
3448
+ """
3449
+ Publishes a data signal status update from any thread by scheduling it on the async loop.
3450
+
3451
+ This is a convenience method for tools and callbacks that need to publish status updates
3452
+ but are not running in an async context. It handles:
3453
+ 1. Extracting task_id and context_id from a2a_context
3454
+ 2. Creating the status update event
3455
+ 3. Checking if the async loop is available and running
3456
+ 4. Scheduling the publish operation on the async loop
3457
+
3458
+ Args:
3459
+ a2a_context: The A2A context dictionary containing logical_task_id and contextId
3460
+ signal_data: A Pydantic BaseModel instance (e.g., AgentProgressUpdateData,
3461
+ DeepResearchProgressData, ArtifactCreationProgressData)
3462
+ skip_buffer_flush: If True, skip buffer flushing before publishing
3463
+ log_identifier: Optional log identifier for debugging
3464
+
3465
+ Returns:
3466
+ bool: True if the publish was successfully scheduled, False otherwise
3467
+ """
3468
+ from ...common import a2a
3469
+
3470
+ log_id = log_identifier or f"{self.log_identifier}[PublishDataSignal]"
3471
+
3472
+ if not a2a_context:
3473
+ log.error("%s No a2a_context provided. Cannot publish data signal.", log_id)
3474
+ return False
3475
+
3476
+ logical_task_id = a2a_context.get("logical_task_id")
3477
+ context_id = a2a_context.get("contextId")
3478
+
3479
+ if not logical_task_id:
3480
+ log.error("%s No logical_task_id in a2a_context. Cannot publish data signal.", log_id)
3481
+ return False
3482
+
3483
+ # Create status update event using the standard data signal pattern
3484
+ status_update_event = a2a.create_data_signal_event(
3485
+ task_id=logical_task_id,
3486
+ context_id=context_id,
3487
+ signal_data=signal_data,
3488
+ agent_name=self.agent_name,
3489
+ )
3490
+
3491
+ # Get the async loop and schedule the publish
3492
+ loop = self.get_async_loop()
3493
+ if loop and loop.is_running():
3494
+ asyncio.run_coroutine_threadsafe(
3495
+ self._publish_status_update_with_buffer_flush(
3496
+ status_update_event,
3497
+ a2a_context,
3498
+ skip_buffer_flush=skip_buffer_flush,
3499
+ ),
3500
+ loop,
3501
+ )
3502
+ log.debug(
3503
+ "%s Scheduled data signal status update (type: %s).",
3504
+ log_id,
3505
+ type(signal_data).__name__,
3506
+ )
3507
+ return True
3508
+ else:
3509
+ log.error(
3510
+ "%s Async loop not available or not running. Cannot publish data signal.",
3511
+ log_id,
3512
+ )
3513
+ return False
3514
+
3291
3515
  def set_agent_system_instruction_string(self, instruction_string: str) -> None:
3292
3516
  """
3293
3517
  Sets a static string to be injected into the LLM system prompt.
@@ -3551,16 +3775,62 @@ class SamAgentComponent(SamComponentBase):
3551
3775
  )
3552
3776
  return raw_text, [], ""
3553
3777
 
3778
+ def _publish_agent_card(self) -> None:
3779
+ """
3780
+ Schedules periodic publishing of the agent card based on configuration.
3781
+ """
3782
+ try:
3783
+ publish_interval_sec = self.agent_card_publishing_config.get(
3784
+ "interval_seconds"
3785
+ )
3786
+ if publish_interval_sec and publish_interval_sec > 0:
3787
+ log.info(
3788
+ "%s Scheduling agent card publishing every %d seconds.",
3789
+ self.log_identifier,
3790
+ publish_interval_sec,
3791
+ )
3792
+ # Register timer with callback
3793
+ self.add_timer(
3794
+ delay_ms=1000,
3795
+ timer_id=self._card_publish_timer_id,
3796
+ interval_ms=publish_interval_sec * 1000,
3797
+ callback=lambda timer_data: publish_agent_card(self),
3798
+ )
3799
+ else:
3800
+ log.warning(
3801
+ "%s Agent card publishing interval not configured or invalid, card will not be published periodically.",
3802
+ self.log_identifier,
3803
+ )
3804
+ except Exception as e:
3805
+ log.exception(
3806
+ "%s Error during _publish_agent_card setup: %s",
3807
+ self.log_identifier,
3808
+ e,
3809
+ )
3810
+ raise e
3811
+
3554
3812
  async def _async_setup_and_run(self) -> None:
3555
3813
  """
3556
3814
  Main async logic for the agent component.
3557
3815
  This is called by the base class's `_run_async_operations`.
3558
3816
  """
3559
- # Call base class to initialize Trust Manager
3560
- await super()._async_setup_and_run()
3817
+ try:
3818
+ # Call base class to initialize Trust Manager
3819
+ await super()._async_setup_and_run()
3820
+
3821
+ # Perform agent-specific async initialization
3822
+ await self._perform_async_init()
3823
+
3824
+ self._publish_agent_card()
3561
3825
 
3562
- # Perform agent-specific async initialization
3563
- await self._perform_async_init()
3826
+ except Exception as e:
3827
+ log.exception(
3828
+ "%s Error during _async_setup_and_run: %s",
3829
+ self.log_identifier,
3830
+ e,
3831
+ )
3832
+ self.cleanup()
3833
+ raise e
3564
3834
 
3565
3835
  def _pre_async_cleanup(self) -> None:
3566
3836
  """
@@ -7,9 +7,10 @@
7
7
  # Purpose: Fix event filtering and function response handling in LLM flows
8
8
  # =============================================================================
9
9
  import google.adk.flows.llm_flows.contents
10
+ from google.adk.flows.llm_flows.contents import _contains_empty_content
10
11
  from google.adk.flows.llm_flows.contents import _is_event_belongs_to_branch
11
12
  from google.adk.flows.llm_flows.contents import _is_auth_event
12
- from google.adk.flows.llm_flows.contents import _convert_foreign_event
13
+ from google.adk.flows.llm_flows.contents import _present_other_agent_message
13
14
  from google.adk.flows.llm_flows.contents import _is_other_agent_reply
14
15
  from google.adk.flows.llm_flows.contents import _rearrange_events_for_async_function_responses_in_history
15
16
  from google.adk.flows.llm_flows.contents import remove_client_function_call_id
@@ -39,16 +40,7 @@ def _patch_get_contents(
39
40
  # Parse the events, leaving the contents and the function calls and
40
41
  # responses from the current agent.
41
42
  for event in events:
42
- if (
43
- not event.content
44
- or not event.content.role
45
- or not event.content.parts
46
- or (event.content.parts[0].text == '' and not event.content.parts[0].function_response)
47
- ):
48
- # Skip events without content, or generated neither by user nor by model
49
- # or has empty text.
50
- # E.g. events purely for mutating session states.
51
-
43
+ if _contains_empty_content(event):
52
44
  continue
53
45
  if not _is_event_belongs_to_branch(current_branch, event):
54
46
  # Skip events not belong to current branch.
@@ -56,11 +48,11 @@ def _patch_get_contents(
56
48
  if _is_auth_event(event):
57
49
  # Skip auth events.
58
50
  continue
59
- filtered_events.append(
60
- _convert_foreign_event(event)
61
- if _is_other_agent_reply(agent_name, event)
62
- else event
63
- )
51
+ if _is_other_agent_reply(agent_name, event):
52
+ if converted_event := _present_other_agent_message(event):
53
+ filtered_events.append(converted_event)
54
+ else:
55
+ filtered_events.append(event)
64
56
 
65
57
  # Rearrange events for proper function call/response pairing
66
58
  result_events = filtered_events
@@ -45,6 +45,9 @@ class TaskExecutionContext:
45
45
  self.token_usage_by_model: Dict[str, Dict[str, int]] = {}
46
46
  self.token_usage_by_source: Dict[str, Dict[str, int]] = {}
47
47
 
48
+ # Generic flags storage for task-level state
49
+ self._flags: Dict[str, Any] = {}
50
+
48
51
  # Generic security storage (enterprise use only)
49
52
  self._security_context: Dict[str, Any] = {}
50
53
 
@@ -52,6 +55,11 @@ class TaskExecutionContext:
52
55
  # Stored here instead of a2a_context to avoid serialization issues
53
56
  self._original_solace_message: Optional["SolaceMessage"] = None
54
57
 
58
+ # Turn tracking for proper spacing between LLM turns
59
+ self._current_invocation_id: Optional[str] = None
60
+ self._first_text_seen_in_turn: bool = False
61
+ self._need_spacing_before_next_text: bool = False
62
+
55
63
  def cancel(self) -> None:
56
64
  """Signals that the task should be cancelled."""
57
65
  self.cancellation_event.set()
@@ -354,3 +362,85 @@ class TaskExecutionContext:
354
362
  """
355
363
  with self.lock:
356
364
  return self._original_solace_message
365
+
366
+ def check_and_update_invocation(self, new_invocation_id: str) -> bool:
367
+ """
368
+ Check if this is a new turn (different invocation_id) and update tracking.
369
+
370
+ Args:
371
+ new_invocation_id: The invocation_id from the current ADK event
372
+
373
+ Returns:
374
+ True if this is a new turn (invocation_id changed), False otherwise
375
+ """
376
+ with self.lock:
377
+ is_new_turn = (
378
+ self._current_invocation_id is not None
379
+ and self._current_invocation_id != new_invocation_id
380
+ )
381
+
382
+ if is_new_turn:
383
+ # Mark that we need spacing before the next text
384
+ self._need_spacing_before_next_text = True
385
+
386
+ if is_new_turn or self._current_invocation_id is None:
387
+ self._current_invocation_id = new_invocation_id
388
+ self._first_text_seen_in_turn = False
389
+
390
+ return is_new_turn
391
+
392
+ def is_first_text_in_turn(self) -> bool:
393
+ """
394
+ Check if this is the first text we're seeing in the current turn,
395
+ and mark it as seen.
396
+
397
+ Returns:
398
+ True if this is the first text in the turn, False otherwise
399
+ """
400
+ with self.lock:
401
+ if not self._first_text_seen_in_turn:
402
+ self._first_text_seen_in_turn = True
403
+ return True
404
+ return False
405
+
406
+ def should_add_turn_spacing(self) -> bool:
407
+ """
408
+ Check if we need to add spacing before the next text (because it's a new turn).
409
+ This flag is set when a new invocation starts and cleared after spacing is added.
410
+
411
+ Returns:
412
+ True if spacing should be added, False otherwise
413
+ """
414
+ with self.lock:
415
+ if self._need_spacing_before_next_text:
416
+ self._need_spacing_before_next_text = False
417
+ return True
418
+ return False
419
+
420
+ def set_flag(self, key: str, value: Any) -> None:
421
+ """
422
+ Set a task-level flag.
423
+
424
+ This method provides a generic mechanism for storing task-level state
425
+ that needs to persist across different parts of the task execution.
426
+
427
+ Args:
428
+ key: The flag name
429
+ value: The flag value
430
+ """
431
+ with self.lock:
432
+ self._flags[key] = value
433
+
434
+ def get_flag(self, key: str, default: Any = None) -> Any:
435
+ """
436
+ Get a task-level flag.
437
+
438
+ Args:
439
+ key: The flag name
440
+ default: Default value to return if flag not found
441
+
442
+ Returns:
443
+ The flag value, or default if not found
444
+ """
445
+ with self.lock:
446
+ return self._flags.get(key, default)